TL; DR: программа форматирования использует собственную нумерацию недель
Программа форматирования даты использует собственную схему нумерации недель, а не дату (в вашем случае это схема *) 1005 * объект). Я демонстрирую использование java .time современного Java API даты и времени. В частности, я использую LocalDate
. LocalDate
всегда является датой в календарной системе ISO.
LocalDate date = LocalDate.of(1998, Month.JANUARY, 1);
DateTimeFormatter baseFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd");
DateTimeFormatter chinaFormatter = baseFormatter.withLocale(Locale.CHINA);
System.out.println("China: " + date.format(chinaFormatter));
DateTimeFormatter franceFormatter = baseFormatter.withLocale(Locale.FRANCE);
System.out.println("France: " + date.format(franceFormatter));
DateTimeFormatter irelandFormatter = baseFormatter.withLocale(Locale.forLanguageTag("en-IE"));
System.out.println("Ireland: " + date.format(irelandFormatter));
Выходные данные из этого фрагмента:
China: 1998-01-01
France: 1998-01-01
Ireland: 1997-01-01
- Если по умолчанию локаль Китай, ваш форматер использовал недели Китай. Они начинаются в воскресенье, а неделя 1 - это неделя, которая содержит 1 января (как в США, как другой пример). Поэтому 1 января 1998 года должно принадлежать недельному 1998 году.
- Франция использует нумерацию ISO: неделя начинается в понедельник, и, как вы сказали, в этом случае неделя 1 1998 года начинается 29 декабря 1997 года. Итак, мы получите снова 1998 год.
- Ирландия - одна из немногих стран, использующих смешанную схему, которую вы пытались получить в своем вопросе: минимальное количество дней в первой неделе - 4 (как в ISO), а воскресенье - первый день. недели (как в Китае и США). Таким образом, использование форматера с Ирландией в качестве локали дает вам результат, который вы пытались получить, 1997.
Другой способ получить недельный 1997 год от вашей даты - поставить свое собственное WeekFields
объект вместе. Тогда вам не нужно беспокоиться о локали.
WeekFields myWeekFields = WeekFields.of(DayOfWeek.SUNDAY, 4);
int weekYear = date.get(myWeekFields.weekBasedYear());
System.out.println("Week year: " + weekYear);
Год недели: 1997
java .time ??
Используемые вами классы даты и времени Calendar
и SimpleDateFormat
плохо спроектированы и сильно устарели.
Из ссылки на ваш документ видно, что вы используете Java 8 и если да, то нет абсолютно никакой причины, почему вы должны бороться со старыми классами. Используйте java .time, как я делаю выше. Существует также бэкпорт для Java 6 и 7.
Почему код в вопросе не сработал?
Вы отнимали время у своего Calendar
с использованием calendar.getTime()
. Это возвращает Date
(еще один плохо спроектированный и давно устаревший класс). Date
- это момент времени, не более того. У этого нет никакого понятия номера недели или года недели. Вы передали это Date
своему SimpleDateFormat
, который никак не мог обнаружить, что Date
изначально был получен от Calendar
объекта с определенными настройками дней в первую неделю и первый день недели. Вместо этого SimpleDateFormat
использует свое собственное определение недель. Это всегда так. Поскольку вы не задали явно язык или календарь для SimpleDateFormat
, он использовал язык по умолчанию для вашей JVM. Это привело к недельному 1998 году, как и в подавляющем большинстве регионов.