Aqui está uma atualização do Java 8 com algum código, já que GregorianCalendar provavelmente será descontinuado ou removido de versões futuras do JDK.
O novo código é tratado na WeekFields
classe e especificamente para maiúsculas y
/ minúsculas Y
com o weekBasedYear()
acessador de campo.
Retorna um campo para acessar o ano de um ano baseado na semana com base neste 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 a exatamente 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 primeira semana pode começar antes do início do ano. Se a primeira semana começar após o início do ano, o período anterior será na última semana do ano anterior.
Este campo pode ser usado com qualquer sistema de calendário.
Na fase de resolução da análise, uma data pode ser criada a partir de um ano com base na semana, semana do ano e dia da semana.
No modo estrito, todos os três campos são validados em relação a sua faixa de valores válidos. O campo semana do ano é validado para garantir que o ano baseado na semana resultante seja o ano baseado na semana solicitado.
No modo inteligente, todos os três campos são validados em relação a sua faixa de valores válidos. O campo do ano com base na 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 tolerante, o ano e o dia da semana são validados em relação ao intervalo de valores válidos. A data resultante é calculada de forma equivalente à seguinte abordagem de três estágios. Primeiro, crie uma data no primeiro dia da primeira semana no ano com base na semana solicitado. Em seguida, pegue o ano baseado na semana da semana, subtraia um e adicione a quantidade em semanas à data. Finalmente, ajuste o dia da semana correto dentro da semana localizada.
A configuração desta WeekFields
instância depende da localidade e pode ter configurações diferentes dependendo dela, os EUA e países europeus como a França podem ter um dia diferente como início da semana.
Por exemplo, o DateFormatterBuilder
do Java 8, instancie o analisador com a localidade e use esta localidade para o Y
símbolo:
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);
}
...
}
...
}
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 do local e maiúsculas Y
, você pode jogar com a opção de linha de comando -Duser.language=
( fr
, en
, es
, etc.), ou forçar o local em tempo de invocação:
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)));