Java 8: DateTimeFormatter не переводит часовой пояс в зависимости от локали - PullRequest
0 голосов
/ 03 января 2019

Я использую 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 'Есть)?

Любая помощь будет оценена.

Ответы [ 3 ]

0 голосов
/ 03 января 2019

ТЛ; др

➥ Обновление до 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

3 декабря 2015 г., 18:15:30 heure normale de l’Est nord-américain

Но вы утверждаете, что видели этот результат:

3 декабря 2015 18 ч. 15 EST

Почему разница?

Java 10 против Java 8

Хорошо, я запускал Java 10. Давайте попробуем Java 8 вместо этого.

1.8.0_181

3 декабря 2015 г. 18 ч. 15 м. Д.

Ах-ха! Теперь я вижу ваши результаты.

Ошибочное смещение

Между прочим, как обнаруженный Мено Хохшильдом , данные вашего примера "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 переключился с использования своих собственных определений данных локализации на аутсорсинг с * 1062. * Консорциум Unicode Репозиторий данных общих локалей (CLDR) . См. JEP 252. Использование данных локали CLDR по умолчанию .

Среди многих видов данных представлены «Переводы для часовых поясов и примеров городов (или аналогичных) для часовых поясов».

Так что никаких ошибок, никаких проблем. Локализация - это сложный процесс, в котором часто существует несколько мнений о подходящих вариантах. Вы нашли пример, когда авторы данных локализации, связанных с OpenJDK 8 и более ранними версиями, не соглашаются с авторами в Консорциуме Unicode. Или, возможно, культурные нормы изменились со временем для этого конкретного региона.

Одним из значительных преимуществ CLDR, помимо гораздо более богатого набора данных о локалях, является то, что CLDR является стандартным источником de facto для данных о локалях. 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.

Язык = язык + культура

Совет: Трy чтобы не использовать просто «FRENCH» при указании вашей локали.Локаль - это сочетание человеческого языка плюс кода страны, представляющего набор культурных норм, определяющих такие вопросы, как использование заглавных букв, сокращение, упорядочение элементов (например, год-месяц-день) и тому подобное.В то время как Locale.FRENCH может прибегнуть к использованию страны, такой как Франция, я предлагаю вам быть явным.Используйте Locale.FRANCE или Locale.CANADA_FRENCH например.

Для использования сотен языков и кодов стран, не определенных в нескольких константах Java, используйте стандартные строковые коды, как описано в документации.Например, fr-FR для французского во Франции.

Кроме того, обратите внимание, что CLDR имеет много более подробной и детальной информации о локали, поэтому вы можете теперь выбрать использование множества вариантов и расширений (в основном субкультур в национальной культуре), которые не были определеныв старом наборе данных локали.См. Locale и сайт Консорциума Unicode для получения дополнительной информации.

0 голосов
/ 03 января 2019

Вопрос и другие ответы, данные до сих пор, сосредоточены только на теме переводов названий зон.Но основная проблема - неправильный результат времени парсинга .Теперь давайте углубимся в детали.

  • Комбинация фиксированного смещения (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-Bug решен, но только для Java 9+, но не для бэкпорта Java-8.

  • По поводу перевода, сказал Василий Буркнекоторые правильные вещи о введении данных CLDR в качестве стандарта / по умолчанию для Java 9 и выше.Изменение репозитория по умолчанию может быть сделано в Java-8 путем , установив системное свойство в "java.locale.providers = CLDR, JRE". Эта конфигурация, вероятно, решит вашу проблему перевода для Java-8, но другая проблема неправильного разбора времени все еще остается.

  • Поэтому моя последняя рекомендация - перейти на Java 9+.
0 голосов
/ 03 января 2019

Вы должны использовать подходящую Зону среди глобальных зон, определенных корпорацией 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#getAvailableIDs%28%29 https://garygregory.wordpress.com/2013/06/18/what-are-the-java-timezone-ids/ https://dzone.com/articles/deeper-look-java-8-date-and

...