Это два поля в пакете java.time.temporal
:
WeekFields.ISO.weekBasedYear()
ISO-8601 определяет так называемую недельную дату, кроме двух других видов даты, а именно обычную календарную дату (состоящую из года, месяца и дня месяца) и порядковой даты (состоящей из года и дня, от года). Учет недели определяется в формате YYYY -WWww-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). Я не нашел никакой исходной или официальной документации для этого поведения. Кто-нибудь знает, где мы можем найти оправдание разницы между этими двумя полями? Доступна ли какая-либо документация об алгоритмическом поведении?
UPDATE:
Теперь я попытался проверить самосогласованность нового 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 может просветить нас?