Ответ 2
Здесь обновление Java 8 с некоторым кодом, поскольку GregorianCalendar, вероятно, будет устаревать или удаляться из будущих версий JDK.
Новый код обрабатывается в классе WeekFields
и, в частности, для нижнего регистра y
/upper case y
с weekBasedYear()
.
Возвращает поле для доступа к году недели, основанного на этом WeekFields. Это представляет собой концепцию года, в котором начинаются недели в фиксированный день недели, например, в понедельник и каждую неделю ровно один год. Это поле обычно используется с dayOfWeek() и weekOfWeekBasedYear().
Неделя 1 (1) - это неделя, начинающаяся с getFirstDayOfWeek(), где есть как минимум getMinimalDaysInFirstWeek() дней в году. Таким образом, неделю может начаться до начала года. Если на первой неделе начинается после начала года, тогда период, предшествующий на прошлой неделе предыдущего года.
Это поле может использоваться с любой системой календаря.
В разрешающей фазе синтаксического анализа дата может быть создана из неделю-неделя, неделя-неделя и день недели.
В строгом режиме все три поля проверяются на соответствие их диапазону допустимые значения. Поле недели за год проверяется, чтобы убедиться, что в соответствии с недельным годом запрашивается неделя.
В интеллектуальном режиме все три поля проверяются в соответствии с их диапазоном допустимые значения. Поле недели недели недели проверяется от 1 до 53, что означает, что итоговая дата может быть следующей недельный год к указанному.
В мягком режиме год и день недели проверяются на диапазон допустимых значений. Полученная дата рассчитывается эквивалентно следующий трехэтапный подход. Сначала создайте дату на первом день первой недели в запрошенном недельном году. Затем возьмите неделю-неделя-год, вычитайте один и добавьте сумму за несколько недель до Дата. Наконец, приспосабливайтесь к правильному дню недели в пределах локализованная неделя.
Настройка этого экземпляра WeekFields
зависит от языкового стандарта и может иметь разные настройки в зависимости от этого, страны США и Европы, такие как Франция, могут иметь другой день в начале недели.
Например, DateFormatterBuilder
для Java 8, создайте парсер с локалием и используйте этот язык для символа y
:
public final class DateTimeFormatterBuilder {
...
private void parsePattern(String pattern) {
...
} else if (cur == 'Y') {
// Fields defined by Locale
appendInternal(new WeekBasedFieldPrinterParser(cur, count));
} else {
...
static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {
...
/**
* Gets the printerParser to use based on the field and the locale.
*
* @param locale the locale to use, not null
* @return the formatter, not null
* @throws IllegalArgumentException if the formatter cannot be found
*/
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)));