Получение TimeZoneID для часового пояса

Я имею дело со временем и датой в Java.

У меня дата как: 2018-08-22T22:00:00-0500 Смещение моего часового пояса здесь -0500 Как я могу получить список доступных идентификаторов часовых поясов?

Моя главная цель здесь - установить дату для определенного часового пояса. Однако я не знаю часовой пояс, поскольку он встроен в этот формат даты.

Обновление: мой вопрос отличается от смещения Java TimeZone, так как в соответствии с принятым ответом на этот вопрос мне нужна информация о часовом поясе: "Европа / Осло" . Однако у меня есть только смещение. Смотрите ниже принятый ответ, который решает мою проблему.

2 ответа

Решение

ТЛ; др

eachZoneId.getRules().getOffset(
    OffsetDateTime.parse( 
        "2018-08-22T22:00:00-0500" , 
        DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" ) 
    ).toInstant()
).equals( myTargetZoneOffset )

Смещение против зоны

Я не знаю часовой пояс, поскольку он встроен в этот формат даты.

Нет, ваша входная строка 2018-08-22T22:00:00-0500 не имеет часового пояса. Он имеет только простое смещение от UTC.

Смещение - это просто количество часов, минут и секунд смещения до или после UTC. Ваш показывает смещение на пять часов позади UTC. В противоположность этому, часовой пояс - это история прошлых, настоящих и будущих изменений в смещении, используемом людьми определенного региона.

OffsetDateTime

В java.time мы представляем момент со смещением как OffsetDateTime учебный класс.

Ваша входная строка в стандартном формате ISO 8601. Поэтому мы должны иметь возможность выполнять синтаксический анализ напрямую без указания шаблона форматирования, поскольку классы java.time по умолчанию используют форматы ISO 8601 при синтаксическом анализе / генерации строк. Однако вашему вводу не хватает двоеточия в смещении между часами и минутами. Хотя это допускается стандартом, OffsetDateTime Классическая небольшая ошибка в Java 8 & 9, которая по умолчанию не может разобрать такие значения. В качестве обходного пути укажите DateTimeFormatter,

String input = "2018-08-22T22:00:00-0000";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" );  // Specify formatting pattern to match input string.
OffsetDateTime odt = OffsetDateTime.parse( input , f );  // Parse from dumb string to smart `OffsetDateTime` object.

odt.toString(): 2018-08-22T22:00-05:00

Названия часовых поясов

Как я могу получить список доступных идентификаторов часовых поясов?

Не уверен, что вы подразумеваете под "идентификаторами часовых поясов". Я предполагаю, что вы запрашиваете список всех часовых поясов, использующих это конкретное смещение от UTC в данный конкретный момент.

Правильное название часового пояса имеет формат continent/region, такие как America/Montreal, Africa/Casablanca, или же Pacific/Auckland, Никогда не используйте 3-4 буквенное сокращение, такое как EST или же IST поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!).

Мы представляем часовой пояс, используя ZoneId, TimeZone класс теперь унаследован, и его следует избегать.

Чтобы получить наш список ZoneId объекты с этим смещением, используемым на эту дату, нам нужно сначала извлечь смещение (ZoneOffset) от нашего OffsetDateTime,

ZoneOffset offset = odt.getOffset() ;

offset.toString(): -05:00

Следующим этапом является опрос всех известных часовых поясов с запросом каждого смещения, действующего на момент нашего OffsetDateTime, Аргумент на этот момент должен быть в UTC, Instant объект. Таким образом, мы должны извлечь Instant от нашего OffsetDateTime, Все тот же момент, та же точка на временной шкале, но видимая через объектив другого времени настенных часов.

Instant instant = odt.toInstant() ;  // Extract a UTC value (`Instant`) from our `OffsetDateTime` object.

instant.toString (): 2018-08-23T03: 00: 00Z

Z на конце не хватает Zulu и означает UTC.

Составьте пустой список, чтобы собрать нужные зоны.

List< ZoneId > hits = new ArrayList<>() ;  // Make an empty list of `ZoneId` objects found to have our desired offset-from-UTC.

Теперь получите все известные зоны. Существует метод, предоставляющий набор всех имен зон, но не объектов зон. Таким образом, для каждой итерации мы должны создавать ZoneId, Затем мы запрашиваем у зоны ее правила, список изменений, действующих с течением времени для этого региона. По правилам мы передаем наш момент (Instant) и получить обратно ZoneOffset в то время Если это смещение соответствует нашему целевому смещению, мы добавляем зону в наш список.

Имейте в виду, что многие зоны могут быть по сути дубликатами или устаревшими. Список зон имеет раздробленную историю, со многими изменениями, и некоторые из них являются просто псевдонимами для других.

    Set < String > names = ZoneId.getAvailableZoneIds();  // Get a collection of all known time zones’ names.
    for ( String name : names )                           // Loop each name.
    {
        ZoneId z = ZoneId.of( name );                     // Instantiate a `ZoneId` for that zone name.
        ZoneRules rules = z.getRules();                   // Get the history of past, present, and future changes in offset used by the people of this particular region (time zone).
        ZoneOffset o = rules.getOffset( instant );        // Get the offset-from-UTC in effect at this moment for the people of this region.
        if( o.equals( offset )) {                         // Compare this particular offset to see if it is the same number of hours, minutes, and seconds as our target offset.
            hits.add( z );                                // If we have a hit, add to our collection of `ZoneId` objects.
        }
    }

Свалить наш hits Сборник на консоль.

[Америка / Панама, Америка / Чикаго, Америка /Eirunepe, Etc/GMT+5, Тихий океан / Пасха, Мексика / Генерал, Америка / Porto_Acre, Америка / Гуаякиль, Америка /Rankin_Inlet, США / Центр, Америка /Rainy_River, Америка / Индиана / Нокс, Америка / Северная_Дакота / Беула, Америка / Монтеррей, Америка / Ямайка, Америка / Атикокан, Америка / Корал-Харбор, Америка / Северная_Дакота / Центр, Америка / Кайман, Америка / Индиана /Tell_City, Чили /EasterIsland, Америка /Mexico_City, Америка /Matamoros, CST6CDT, Америка /Knox_IN, Америка / Богота, Америка /Menominee, Америка / Решительный, SystemV/EST5, Канада / Центральный, Бразилия / Акр, Америка / Канкун, Америка / Лима, Америка /Bahia_Banderas, США / Индиана-Старке, Америка /Rio_Branco, SystemV/CST6CDT, Ямайка, Америка / Мерида, Америка / Северная Дакота / Новый_Салем, Америка / Виннипег]

Имейте в виду, что этот список зон действителен только для выбранного нами конкретного момента. В более ранние или более поздние времена некоторые из этих зон могут использовать другое смещение от UTC. И наоборот, в другие моменты некоторые зоны, не входящие в этот список, могут использовать желаемое смещение.


О java.time

Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date, Calendar & SimpleDateFormat,

Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.

Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310.

Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классы.

Где взять классы java.time?

  • Java SE 8, Java SE 9 и более поздние
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
  • Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval, YearWeek, YearQuarter и многое другое.

Вы можете конвертировать свою дату в календарь. Calendar.getTimeZone() вернет TimeZone, соответствующий календарю. И тогда TimeZone.getAvailableIDs() выдаст вам доступные идентификаторы.

Другие вопросы по тегам