SimpleDateFormat неделя год - PullRequest
       10

SimpleDateFormat неделя год

2 голосов
/ 06 января 2020

java8 GregorianCalendar DO C

Недельный год синхронизирован c с циклом WEEK_OF_YEAR. Все недели между первой и последней неделями (включительно) имеют одинаковое значение года в году. Поэтому первый и последний дни года могут иметь разные значения календарного года.

Например, 1 января 1998 года - четверг. Если getFirstDayOfWeek () имеет значение MONDAY, а getMinimalDaysInFirstWeek () имеет значение 4 (стандарт, совместимый со стандартом ISO 8601), то первая неделя 1998 года начинается 29 декабря 1997 года и заканчивается 4 января 1998 года. Год недели 1998 за последние три дня календарного года 1997. Если, однако, getFirstDayOfWeek () имеет значение SUNDAY, то первая неделя 1998 года начинается 4 января 1998 года и заканчивается 10 января 1998 года; первые три дня 1998 года являются частью недели 53 1997 года, а год недели - 1997.

Как сказано в DO C, если я установлю для FirstDayOfWeek значение SUNDAY и MinimalDaysInFirstWeek, равное 4, то есть год недели 1998-01-01 должен быть 1997, но результат junit - 1998.

Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, 1998);
    calendar.set(Calendar.MONTH, 0);
    calendar.set(Calendar.DAY_OF_MONTH, 1);
    calendar.setMinimalDaysInFirstWeek(4);
    calendar.setFirstDayOfWeek(Calendar.SUNDAY);

    System.out.println(calendar.getTimeZone());
    System.out.println(calendar.getMinimalDaysInFirstWeek());
    System.out.println(calendar.getFirstDayOfWeek());

    SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
    System.out.println(sdf.format(calendar.getTime()));

Результат junit: sun.util.calendar.ZoneInfo [id = "Asia / Shanghai", offset = 28800000, dstSavings = 0, useDaylight = false, переходы = 29, lastRule = null]

4

1

1998-01-01

1 Ответ

4 голосов
/ 06 января 2020

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 году, как и в подавляющем большинстве регионов.

...