Получение 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
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.
Вы можете конвертировать свою дату в календарь. Calendar.getTimeZone() вернет TimeZone, соответствующий календарю. И тогда TimeZone.getAvailableIDs() выдаст вам доступные идентификаторы.