Java 8: DateTimeFormatter не переводит часовой пояс в зависимости от локали
Я использую DateTimeFormatter для форматирования даты:
ZonedDateTime date = ZonedDateTime.parse("2015-12-03T18:15:30+01:00[America/New_York]");
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
.withLocale(Locale.FRENCH);
System.out.println(formatter.format(date));
Вывод кода:
jeudi 3 décembre 2015 18 h 15 EST
Как я могу также перевести часовой пояс с EST на французский HNE (Heure Normale de l'Est)?
Любая помощь будет оценена.
3 ответа
ТЛ; др
Beyond Обновление до Java 8.
Java 9 и более поздние версии, использующие CLDR, теперь демонстрируют различное поведение локализации для некоторых локалей.
Запуск вашего кода в Java 8 показывает ваши наблюдаемые результаты jeudi 3 décembre 2015 18 h 15 EST
во время работы в Java 9 и более поздних показывает желаемые результаты jeudi 3 décembre 2015 à 18:15:30 heure normale de l’Est nord-américain
,
подробности
Я попробовал ваш код как есть, за исключением имени переменной.
System.out.println( System.getProperty( "java.version" ) );
ZonedDateTime zdt = ZonedDateTime.parse( "2015-12-03T18:15:30-05:00[America/New_York]" );
DateTimeFormatter formatter =
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( Locale.FRENCH );
System.out.println( formatter.format( zdt ) );
Результаты:
10.0.2
Jeudi 3 декабря 2015 по 18:15:30 Heure Normale De L'Est Nord-Américain
Но вы утверждаете, что видели этот результат:
Jeudi 3 декабря 2015 18 ч 15 EST
Почему разница?
Java 10 против Java 8
Ну, у меня была Java 10. Давайте попробуем Java 8 вместо этого.
1.8.0_181
Jeudi 3 декабря 2015 18 ч 15 EST
Ах-ха! Теперь я вижу ваши результаты.
Ошибочное смещение
Кстати, как обнаружил Мено Хохшильд, ваш пример данных "2015-12-03T18:15:30+01:00[America/New_York]"
использует неверное смещение от UTC +01:00
для зоны America/New_York
, Должно было -05:00
, Я исправил вашу строку для использования в этом ответе. Смотрите этот ответ Хохшильда для дальнейшего обсуждения.
CLDR
Я подозреваю, что это связано с серьезными изменениями, внесенными в Java 9, по крайней мере, в реализации Java 9. основанные на OpenJDK. В Java 9 OpenJDK переключился с использования своих собственных определений данных локализации на аутсорсинг от консорциума Unicode Common Locale Репозиторий данных (CLDR). См. JEP 252. Использование данных локали CLDR по умолчанию.
Среди многих видов данных представлены "Переводы для часовых поясов и примеров городов (или аналогичных) для часовых поясов".
Так что никаких ошибок, никаких проблем. Локализация - это сложный процесс, в котором часто существует несколько мнений о подходящих вариантах. Вы нашли пример, когда авторы данных локализации, связанных с OpenJDK 8 и более ранними версиями, не соглашаются с авторами в Консорциуме Unicode. Или, возможно, культурные нормы изменились со временем для этого конкретного региона.
Одним из больших преимуществ CLDR, помимо гораздо более богатого набора данных о локалях, является то, что CLDR является де-факто стандартным источником данных о локалях. CLDR был принят многими другими системами. Так что теперь Java-приложения будут демонстрировать поведение, идентичное другим системам, или почти идентичное с некоторыми возможными различиями из-за управления версиями.
И если говорить о версиях, то, как мы надеемся, изменения в большинстве локалей будут незначительными, поскольку Консорциум Unicode много лет работал над этим. CLDR должен быть относительно полным и стабильным в наше время. Хотя некоторые Java-приложения, переходящие с Java <=8 на Java >=9, могут видеть некоторые существенные изменения в поведении, как видно из этого Вопроса, в будущем вы должны увидеть очень мало сюрпризов / изменений.
Предостережение: все это обсуждение здесь относится к реализациям Java на основе OpenJDK. В настоящее время это означает, что большинство поставщиков (Azul, AdoptOpenJDK.net, Amazon Corretto, IBM, Oracle JDK и Oracle строят OpenJDK). Но любая реализация Java, не построенная из OpenJDK, может использовать альтернативный источник данных и поведения локализации, отличный от CLDR.
Обходной путь для Java 8
CLDR фактически включен в OpenJDK 8, согласно JEP 127, но по умолчанию не используется. Что изменилось в OpenJDK 9 и более поздних версиях, так это то, что CLDR был повышен по умолчанию до того, что он стал первым провайдером данных локали, к которому обращались, согласно JEP 252. См. Ответ Мено Хохшильда, чтобы сделать CLDR основным поставщиком данных локали в 8.
Локаль = язык + культура
Совет: старайтесь не использовать просто "FRENCH" при указании вашей локали. Локаль - это сочетание человеческого языка и кода страны, представляющего набор культурных норм, определяющих такие вопросы, как использование заглавных букв, сокращение, упорядочение элементов (например, год-месяц-день) и тому подобное. В то время как Locale.FRENCH
может прибегнуть к использованию страны, такой как Франция, я предлагаю вам быть явным. использование Locale.FRANCE
или жеLocale.CANADA_FRENCH
например.
Для использования сотен языков и кодов стран, не определенных в нескольких константах Java, используйте стандартные строковые коды, как описано в документации. Например,fr-FR
для французского во Франции.
Кроме того, обратите внимание, что CLDR имеет гораздо более подробную и детальную информацию о локали, поэтому вы можете теперь выбрать использование многих вариантов и расширений (в основном субкультур внутри национальной культуры), которые не были определены в старом наборе данных локали. УвидетьLocale
и сайт Консорциума Unicode для получения дополнительной информации.
Вопрос и другие ответы, данные до сих пор, концентрируются только на теме переводов названий зон. Но главная проблема - неправильный результат анализа времени. Теперь давайте углубимся в детали.
Комбинация фиксированного смещения (UTC+01) и идентификатора зоны "America/New_York" является несколько странной, потому что зона, обозначенная "America/New_York", знает только смещения UTC-05 (и UTC-04 летом).
Такое двойственное и противоречивое сочетание должно быть проанализировано с приоритетом, отданным зачету. Таким образом, время "2015-12-03T18:15:30+01:00" совпадает с "2015-12-03T12:15:30-05:00", но вы все равно проанализировали то же местное время "18:15:30"в зоне EST (со смещением UTC-05), что является серьезной ошибкой. Связанная ошибка JDK решена, но только для Java 9+, но не для бэкпорта Java-8.
Что касается перевода, Басил Бурк сказал несколько правильных слов о введении данных CLDR в качестве стандарта / по умолчанию для Java 9 и более поздних версий. Изменить репозиторий по умолчанию можно в Java-8, установив системное свойство в "java.locale.providers=CLDR,JRE". Эта конфигурация, вероятно, решит проблему перевода для Java-8, но другая проблема неправильного разбора времени все еще остается.
- Поэтому моя последняя рекомендация - перейти на Java 9+.
Вы должны использовать подходящую Зону среди глобальных зон, определенных корпорацией Oracle. TimeZone.getAvailableIDs()
может использоваться для просмотра всех доступных часовых поясов в виде String
массив. По вашему требованию вы можете использовать Europe/Paris
часовой пояс. Определите новую дату с новым часовым поясом без изменения даты следующим образом:
ZonedDateTime dateParis =
date.withZoneSameLocal( ZoneId.of( "Europe/Paris" ) );
Пожалуйста, обратитесь к следующим ссылкам для получения дополнительной информации https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html https://garygregory.wordpress.com/2013/ 06/18 / идентификаторы часового пояса "что такое ява" / https://dzone.com/articles/deeper-look-java-8-date-and