Вопрос-ответ

Y returns 2012 while y returns 2011 in SimpleDateFormat

Y возвращает 2012, в то время как y возвращает 2011 в SimpleDateFormat

Интересно, почему 'Y' возвращает 2012, в то время как 'y' возвращает 2011 в SimpleDateFormat:

System.out.println(new SimpleDateFormat("Y").format(new Date())); // prints 2012
System.out.println(new SimpleDateFormat("y").format(new Date())); // prints 2011

Кто-нибудь может объяснить, почему?

Переведено автоматически
Ответ 1

год недели и year. Из javadoc


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


Например, 1 января 1998 года приходится на четверг. Если getFirstDayOfWeek() - ПОНЕДЕЛЬНИК, а getMinimalDaysInFirstWeek() - 4 (настройка, совместимая со стандартом ISO 8601), то первая неделя 1998 года начинается 29 декабря 1997 года и заканчивается 4 января 1998 года. Год недели равен 1998 для последних трех дней 1997 календарного года. Однако, если getFirstDayOfWeek() приходится на ВОСКРЕСЕНЬЕ, то 1-я неделя 1998 года начинается 4 января 1998 года и заканчивается 10 января 1998 года; тогда первые три дня 1998 года являются частью 53-й недели 1997 года, а год их недели - 1997.


Ответ 2

Вот обновление Java 8 с некоторым кодом, поскольку GregorianCalendar, вероятно, устареет или будет удален из будущих версий JDK.

Новый код обрабатывается в WeekFields классе, и специально для нижнего y / верхнего регистра Y с помощью weekBasedYear() средства доступа к полю.


Возвращает поле для доступа к году на основе недели-year на основе this WeekFields . Это представляет концепцию года, в которой недели начинаются в фиксированный день недели, например понедельник, и каждая неделя принадлежит ровно одному году. Это поле обычно используется с DayOfWeek() и weekOfWeekBasedYear() .


Первая неделя(1) - это неделя, начинающаяся с getFirstDayOfWeek(), где в году есть по крайней мере дни getMinimalDaysInFirstWeek(). Таким образом, первая неделя может начаться до начала года. Если первая неделя начинается после начала года, то предыдущий период приходится на последнюю неделю предыдущего года.


Это поле можно использовать с любой календарной системой.


На этапе разрешения синтаксического анализа дата может быть создана на основе года, недели в году и дня недели.


В строгом режиме все три поля проверяются на соответствие диапазону допустимых значений. Поле week-of-year проверяется, чтобы гарантировать, что результирующий недельный год соответствует запрошенному недельному году.


В интеллектуальном режиме все три поля проверяются на соответствие их диапазону допустимых значений. Поле week-of-week-based-year проверяется от 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)));
Ответ 3

Y чтобы получить неделю за год, если календарь поддерживает неделю за год. (getCalendar().isWeekDateSupported())

Ответ 4

Я на собственном опыте убедился, что библиотека тегов JSTL format:date с short в качестве запрошенного формата использует YYYY под обложкой. Который действительно может переносить напечатанную дату на год вперед.

java date