Как исправить
Следующие два параметра эквивалентны. Выберите тот, который вы считаете наиболее подходящим для вашей ситуации.
WeekFields.ISO
WeekFields.of(Locale.GERMANY)
с использованием страны, Германии, вместо языка, немецкого.
Почему это происходит? CLDR и страна против языка
Здесь есть два отличия:
- Различные данные о локали по умолчанию в разных версиях Java.
- Как уже говорили другие, разница между языковым языком и языком, который включает страну.
Определение недельных схем в разных локалях является частью данных локали. Java может получать данные о локали из четырех источников. Java включала свои собственные данные локали из ранних версий, и они были по умолчанию вплоть до Java 8. Из Java 8 также были включены данные CLDR (Unicode Common Locale Data Repository), и они стали значениями по умолчанию из Java 9. Что, очевидно, изменило некоторые функциональность и сломал некоторый старый код, как вы уже испытали Точнее, по умолчанию:
- Java 8: JRE, SPI, где JRE ссылается на собственные данные локали Java.
- Java 9, 10 и 11: CLDR, COMPAT, где CLDR - это то, что говорит, а COMPAT - это новое имя для данных JRE.
Значения по умолчанию можно изменить, установив системное свойство java.locale.providers
. Таким образом, мы можем получить поведение Java 8 в Java 9 и более поздних версиях, установив для этого свойства значение COMPAT,SPI
. И наоборот, мы можем получить поведение Java 10 в Java 8, установив для него CLDR,JRE
. Таким образом, в основе лежит не столько разница между версиями Java, сколько их значения по умолчанию.
Переход от данных Java к данным CLDR заключается в следующем: данным языковых стандартов Java назначаются недельные определения для языковых языковых стандартов (например, немецких) в зависимости от того, на каком языке в основном говорят. В отличие от этого, философия CLDR заключается в том, что вы можете говорить на любом языке в любой стране мира и предпочитаете выбирать недельную схему в зависимости от страны, а не языка. Как следствие, для регионов, в которых не указана страна (например, для Германии), используется определение недели по умолчанию во всем мире.
Почему в CLDR по умолчанию используется определение недели по умолчанию «воскресенье, 1», я не понимаю. Как и другие, я ожидал и предпочел ISO международный стандарт «Понедельник, 4». Как я сказал в комментарии, я также обнаружил заметку о том, что так и должно быть, но это не так (по крайней мере, в версиях CLDR, используемых в Java с 8 по 11).
Java 9 особенная
Как вы заметили, в Java 9 с данными локали по умолчанию вы получаете «Monday 4» из Locale.GERMAN
хотя CLDR должен быть первым по умолчанию. С другой стороны, если я установлю java.locale.providers
на CLDR
в одиночку, я получу «воскресенье 1», как в Java 10 и 11.
Возможное объяснение состоит в том, что версия CLDR, используемая в Java 9, не включает определение недели для немецкого языка. Таким образом, с провайдерами по умолчанию, CLDR, COMPAT, Java возвращается к COMPAT, который предоставляет «Понедельник, 4» для немецкого языка. Когда я использую только CLDR, он возвращается к базовому значению по всему миру, «Sunday, 1». Если это объяснение верное (что я не могу гарантировать), может показаться, что версии данных CLDR, используемые в Java 10 и 11, содержат недельное определение для немецкого языка.
Ссылки
Документация LocaleServiceProvider
с информацией о провайдерах региональных данных и спецификациях провайдеров по умолчанию:
Ссылки CLDR: