Какова мотивация для двух разных определений недельного года в JSR-310?
Это два поля в пакетеjava.time.temporal
:
WeekFields.ISO.weekBasedYear ()
ISO-8601 определяет так называемую дату недели, помимо двух других типов даты, а именно: обычную календарную дату (состоящую из года, месяца и дня месяца) и порядковую дату (состоящую из года и дня года ).Дата недели определяется в формате YYYY-'W'ww-e, w обозначает неделю года, e - числовой ISO-день недели. Y обозначает недельный год и идентичен календарному году, за исключением начала или конца календарного года, поскольку недельный год связан с недельным циклом, который может в конечном итоге начаться в предыдущем году. Два правила важны для понимания того, как формируется недельная дата:
Недели всегда начинаются в понедельник.Первая неделя календарного года - это неделя, которая содержит не менее четырех дней.На первый взгляд оба поля JSR-310 кажутся идентичными, поскольку в ISO-8601 упоминается только один тип недельного года. Но подождите, сюрприз. Давайте рассмотрим следующий пример кода:
LocalDate date1 =
LocalDate.of(2000, 2, 29).with(IsoFields.WEEK_BASED_YEAR, 2014);
System.out.println("IsoFields-Test: " + date1); // output: 2014-03-01
LocalDate date2 =
LocalDate.of(2000, 2, 29).with(WeekFields.ISO.weekBasedYear(), 2014);
System.out.println("WeekFields-Test: " + date2); // output: 2014-02-25
Хотя я очень хорошо понимаю второй вариант, я действительно удивлен, увидев другой результат для первого свидания, который использует «официальную» ссылку ISO-8601 в своем названии класса. Чтобы объяснить рассчитанные результаты:
Дата 2000-02-29 соответствует 2000-W09-2 в нотации ISO-weekdate, а 2014-02-25 соответствует 2014-W09-2сохранение недели года и дня недели, Пока все хорошо. Это сохранение характеристик для небольших полей аналогично правилу, как изменять календарный год (который в большинстве случаев должен сохранять месяц и день месяца в календарной дате без изменений).
Но как насчет результата 2014-03-01? Здесь алгоритм просто добавил четыре дня к соответствующей дате недели, чтобы учесть разницу в поле «день месяца» (29 против 25). Я не нашел никакого источника или официальной документации для этого поведения. Кто-нибудь знает, где мы можем найти обоснование разницы между этими двумя полями? Есть ли документация об алгоритмическом поведении?
ОБНОВИТЬ:
Теперь я попытался проверить самосогласованность нового API с этим выражением, чтобы выяснить, какое из двух полей лучше поддерживается:
System.out.println(
"14 week-based-years later = "
+ LocalDate.of(2000, 2, 29).plus(14, IsoFields.WEEK_BASED_YEARS));
Вывод 2014-03-01 аналогичен описанному случаюIsoFields.WEEK_BASED_YEAR
, хотя я все еще нахожу результат 2014-02-25 (= 2014-W09-2) гораздо более логичным. Так как эта временная единица также находится в классеIsoFields
до сих пор поведение является самосогласованным в классеIsoFields
, Выглядит как недокументированная и неинтуитивная «фича».
Я использую версию:java.runtime.version = 1.8.0-B132
Больше тестирования:
LocalDate d = LocalDate.of(2014, 3, 1); // 2014-W09-6
System.out.println(
"week-of-year in 2014-03-01: "
+ d.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
System.out.println(
"day-of-week in 2014-03-01: "
+ d.get(ChronoField.DAY_OF_WEEK));
LocalDate later = d.plus(14, IsoFields.WEEK_BASED_YEARS); // 2028-03-02 = 2028-W09-4
System.out.println(
"14 week-based-years later = "
+ later);
System.out.println(
"week-of-year in " + later + ": "
+ later.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
System.out.println(
"day-of-week in " + later + ": "
+ later.get(ChronoField.DAY_OF_WEEK));
Выход:
week-of-year in 2014-03-01: 9
day-of-week in 2014-03-01: 6
14 week-based-years later = 2028-03-02
week-of-year in 2028-03-02: 9
day-of-week in 2028-03-02: 4
Я не признаю никаких четких правил. Ни день недели не сохраняется, ни день месяца не сохраняется при добавлении 14 недельных годов.Так что это дополнительный вопрос: какое правило стоит заIsoFields.WEEK_BASED_YEARS
? Может быть, команда JSR-310 может просветить нас?