Y retorna 2012 enquanto y retorna 2011 em SimpleDateFormat

Gostaria de saber por que ‘Y’ retorna 2012, enquanto ‘y’ retorna 2011 em SimpleDateFormat :

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

Alguém pode explicar por quê?

semana ano e ano. De javadoc

Um ano da semana está em sincronia com um ciclo WEEK_OF_YEAR. Todas as semanas entre a primeira e a última semana (inclusive) têm o mesmo valor do ano da semana. Portanto, o primeiro e o último dia de um ano da semana podem ter valores de ano calendar diferentes.

Por exemplo, 1º de janeiro de 1998 é uma quinta-feira. Se getFirstDayOfWeek () for MONDAY e getMinimalDaysInFirstWeek () for 4 (configuração compatível com o padrão ISO 8601), a semana 1 de 1998 começará em 29 de dezembro de 1997 e terminará em 4 de janeiro de 1998. O ano da semana é 1998 nos últimos três dias do ano civil de 1997. Se, no entanto, getFirstDayOfWeek () for DOMINGO, a semana 1 de 1998 terá início em 4 de janeiro de 1998 e terminará em 10 de janeiro de 1998; os primeiros três dias de 1998 fazem parte da semana 53 de 1997 e o ano da semana é 1997.

Aqui está uma atualização do Java 8 com algum código, já que o GregorianCalendar provavelmente será descontinuado ou removido de futuras versões do JDK.

O novo código é tratado na class WeekFields e, especificamente, para o caso minúsculo em checkbox alta Y com o weekBasedYear() campo weekBasedYear() .

Retorna um campo para acessar o ano de um ano baseado em semana com base nesse WeekFields. Isso representa o conceito do ano em que as semanas começam em um dia fixo da semana, como segunda-feira e cada semana pertence exatamente a um ano. Este campo é normalmente usado com dayOfWeek () e weekOfWeekBasedYear ().

A semana um (1) é a semana que começa em getFirstDayOfWeek () onde há pelo menos getMinimalDaysInFirstWeek () dias no ano. Assim, a semana um pode começar antes do começo do ano. Se a primeira semana começar depois do início do ano, o período anterior será na última semana do ano anterior.

Este campo pode ser usado com qualquer sistema de calendar.

Na fase de resolução da análise, uma data pode ser criada a partir de um ano baseado em semana, semana do ano e dia da semana.

No modo estrito, todos os três campos são validados em relação ao intervalo de valores válidos. O campo da semana do ano é validado para garantir que o ano com base na semana resultante seja o ano com base na semana solicitado.

No modo inteligente, todos os três campos são validados em relação ao intervalo de valores válidos. O campo de ano da semana baseado em semana é validado de 1 a 53, o que significa que a data resultante pode estar no ano com base na semana seguinte ao especificado.

No modo leniente, o ano e o dia da semana são validados em relação ao intervalo de valores válidos. A data resultante é calculada equivalente à seguinte abordagem de três etapas. Primeiro, crie uma data no primeiro dia da primeira semana do ano com base na semana solicitada. Em seguida, tire o ano da semana da semana, subtraia um e adicione o valor em semanas à data. Por fim, ajuste o dia da semana correto dentro da semana localizada.

A configuração desta instância WeekFields depende da localidade e pode ter configurações diferentes, dependendo dela, os países dos EUA e da Europa, como a França, podem ter um dia diferente como início da semana.

Por exemplo, o DateFormatterBuilder do Java 8, instanciar o analisador com a localidade e usar essa localidade para o símbolo 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); } ... } ... } 

Aqui está um exemplo

 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())); 

E no que diz respeito à localidade e à maiúscula Y , você pode jogar com a opção de linha de comando -Duser.language= ( fr , en , es , etc.) ou forçar a localidade no momento da chamada:

 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))); 

Formato Y para obter o ano da semana se o ano da semana de suporte do calendar. ( getCalendar().isWeekDateSupported() )

Aprendi da maneira mais difícil o format:date biblioteca de tags JSTL format:date short com o formato solicitado usando YYYY nas capas. Que pode realmente rolar a data impressa à frente por ano.