Ecco un aggiornamento di Java 8 con del codice, poiché GregorianCalendar sarà probabilmente deprecato o rimosso dalle future versioni di JDK.
Il nuovo codice viene gestito nella WeekFields
classe e specificamente per le lettere minuscole y
/ maiuscole Y
con la funzione di accesso al weekBasedYear()
campo.
Restituisce un campo per accedere all'anno di un anno basato sulla settimana in base a questo WeekFields. Questo rappresenta il concetto dell'anno in cui le settimane iniziano in un giorno della settimana fisso, come il lunedì e ogni settimana appartiene esattamente a un anno. Questo campo viene in genere utilizzato con dayOfWeek () e weekOfWeekBasedYear ().
La prima settimana (1) è la settimana che inizia su getFirstDayOfWeek () dove ci sono almeno getMinimalDaysInFirstWeek () giorni nell'anno. Pertanto, la prima settimana può iniziare prima dell'inizio dell'anno. Se la prima settimana inizia dopo l'inizio dell'anno, il periodo precedente è nell'ultima settimana dell'anno precedente.
Questo campo può essere utilizzato con qualsiasi sistema di calendario.
Nella fase di risoluzione dell'analisi, è possibile creare una data da un anno basato sulla settimana, una settimana dell'anno e un giorno della settimana.
In modalità rigorosa, tutti e tre i campi vengono convalidati rispetto al loro intervallo di valori validi. Il campo della settimana dell'anno viene convalidato per garantire che l'anno basato sulla settimana risultante sia l'anno basato sulla settimana richiesto.
In modalità intelligente, tutti e tre i campi vengono convalidati rispetto al loro intervallo di valori validi. Il campo dell'anno basato sulla settimana viene convalidato da 1 a 53, il che significa che la data risultante può essere nell'anno basato sulla settimana successivo a quello specificato.
In modalità clemente, l'anno e il giorno della settimana vengono convalidati rispetto all'intervallo di valori validi. La data risultante è calcolata equivalente al seguente approccio in tre fasi. Innanzitutto, crea una data nel primo giorno della prima settimana nell'anno basato sulla settimana richiesto. Quindi prendi l'anno basato sulla settimana della settimana, sottrai uno e aggiungi l'importo in settimane alla data. Infine, regola il giorno della settimana corretto all'interno della settimana localizzata.
La configurazione di questa WeekFields
istanza dipende dalle impostazioni locali e potrebbe avere impostazioni diverse a seconda di essa, gli Stati Uniti e i paesi europei come la Francia potrebbero avere un giorno diverso come inizio della settimana.
Ad esempio, DateFormatterBuilder
di Java 8, istanzia il parser con la locale e usa questa locale per il Y
simbolo:
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);
}
...
}
...
}
Ecco qualche esempio
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 per quanto riguarda la localizzazione e la maiuscola Y
, è possibile giocare sia con l'opzione della riga di comando -Duser.language=
( fr
, en
, es
, etc.), o forzare il locale in fase di invocazione:
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)));