Вот обновление Java 8 с некоторым кодом, поскольку GregorianCalendar, вероятно, будет устаревшим или удаленным из будущих версий JDK.
Новый код обрабатывается в WeekFields
классе, особенно для нижнего y
/ верхнего регистра Y
с помощью weekBasedYear()
метода доступа к полю.
Возвращает поле для доступа к году недели на основе этого поля WeekFields. Это представляет собой концепцию года, когда недели начинаются в фиксированный день недели, например понедельник, а каждая неделя принадлежит ровно одному году. Это поле обычно используется с dayOfWeek () и weekOfWeekBasedYear ().
Первая (1) неделя - это неделя, начинающаяся с getFirstDayOfWeek (), когда в году есть как минимум дни getMinimalDaysInFirstWeek (). Таким образом, первая неделя может начаться до начала года. Если первая неделя начинается после начала года, то предшествующий период приходится на последнюю неделю предыдущего года.
Это поле можно использовать с любой календарной системой.
На этапе разрешения синтаксического анализа дату можно создать из года на основе недели, недели года и дня недели.
В строгом режиме все три поля проверяются на соответствие диапазону допустимых значений. Поле неделя года проверяется, чтобы гарантировать, что итоговый год на основе недели является запрошенным годом на основе недели.
В интеллектуальном режиме все три поля проверяются по диапазону допустимых значений. Поле года на основе недели-недели проверяется от 1 до 53, что означает, что результирующая дата может быть в следующем году, основанном на неделях, по сравнению с указанным.
В мягком режиме год и день недели проверяются по диапазону допустимых значений. Полученная дата рассчитывается аналогично следующему трехэтапному подходу. Сначала создайте дату в первый день первой недели запрошенного недельного года. Затем возьмите год, основанный на неделях, вычтите единицу и прибавьте к дате сумму в неделях. Наконец, настройте правильный день недели в пределах локальной недели.
Настройка этого WeekFields
экземпляра зависит от локали и может иметь разные настройки в зависимости от нее. В США и европейских странах, таких как Франция, может быть другой день в качестве начала недели.
Например, DateFormatterBuilder
Java 8, создайте экземпляр синтаксического анализатора с локалью и используйте эту локаль для Y
символа:
public final class DateTimeFormatterBuilder {
...
private void parsePattern(String pattern) {
...
} else if (cur == 'Y') {
appendInternal(new WeekBasedFieldPrinterParser(cur, count));
} else {
...
static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {
...
private DateTimePrinterParser printerParser(Locale locale) {
WeekFields weekDef = WeekFields.of(locale);
TemporalField field = null;
switch (chr) {
case 'Y':
field = weekDef.weekBasedYear();
if (count == 2) {
return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE, 0);
} else {
return new NumberPrinterParser(field, count, 19,
(count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD, -1);
}
case 'e':
case 'c':
field = weekDef.dayOfWeek();
break;
case 'w':
field = weekDef.weekOfWeekBasedYear();
break;
case 'W':
field = weekDef.weekOfMonth();
break;
default:
throw new IllegalStateException("unreachable");
}
return new NumberPrinterParser(field, (count == 2 ? 2 : 1), 2, SignStyle.NOT_NEGATIVE);
}
...
}
...
}
Вот пример
System.out.format("Conundrum : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'")));
System.out.format("Solution : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmms'S'")));
System.out.format("JVM Locale first day of week : %s%n",
WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());
System.out.format("US first day of week : %s%n",
WeekFields.of(Locale.US).getFirstDayOfWeek());
System.out.format("France first day of week : %s%n",
WeekFields.of(Locale.FRANCE).getFirstDayOfWeek());
System.out.format("JVM Locale min days in 1st week : %s%n",
WeekFields.of(Locale.getDefault()).getMinimalDaysInFirstWeek());
System.out.format("US min days in 1st week : %s%n",
WeekFields.of(Locale.US).getMinimalDaysInFirstWeek());
System.out.format("JVM Locale min days in 1st week : %s%n",
WeekFields.of(Locale.FRANCE).getMinimalDaysInFirstWeek());
System.out.format("JVM Locale week based year (big Y): %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.FRANCE).weekBasedYear()));
System.out.format("France week based year (big Y) : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.FRANCE).weekBasedYear()));
System.out.format("US week based year (big Y) : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.US).weekBasedYear()));
И в отношении локали и верхнего корпуса Y
, вы можете играть с опцией командной строки -Duser.language=
( fr
, en
, es
и т.д.), или принудительно локаль во время вызова:
System.out.format("English localized : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'", Locale.ENGLISH)));
System.out.format("French localized : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'", Locale.FRENCH)));