Zastanawiam się, dlaczego „Y” zwraca 2012, a „y” zwraca 2011 w SimpleDateFormat
:
System.out.println(new SimpleDateFormat("Y").format(new Date())); // prints 2012
System.out.println(new SimpleDateFormat("y").format(new Date())); // prints 2011
Czy ktoś może wyjaśnić, dlaczego?
java
date
simpledateformat
Eng. Fouad
źródło
źródło
Odpowiedzi:
tydzień i rok. Z javadoc
źródło
$ date Wed Dec 30 00:42:51 UTC 2015
$ date +%G 2015
$ date +%Y 2015
Niektóre programy są zdezorientowane:strftime
oblicza dzisiaj (29.12.2015) tydzień 53, a rok 2015.Oto aktualizacja Java 8 z pewnym kodem, ponieważ GregorianCalendar prawdopodobnie zostanie wycofany lub usunięty z przyszłych wersji JDK.
Nowy kod jest obsługiwany w
WeekFields
klasie, a szczególnie w przypadku małychy
/ dużych literY
zweekBasedYear()
akcesorium pola.Konfiguracja tej
WeekFields
instancji zależy od lokalizacji i może mieć różne ustawienia w zależności od niej, kraje USA i Europy, takie jak Francja, mogą mieć inny dzień jako początek tygodnia.Na przykład
DateFormatterBuilder
Java 8, utwórz instancję parsera z ustawieniami narodowymi i użyj tych ustawień narodowych dlaY
symbolu: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); } ... } ... }
Oto przykład
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()));
A w odniesieniu do lokalizacji i wielkimi literami
Y
, można grać z opcją wiersza poleceń-Duser.language=
(fr
,en
,es
, itd), lub wymusić ustawienia regionalne w czasie wywołania: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)));
źródło
Format,
Y
aby uzyskać rok tygodnia, jeśli kalendarz obsługuje rok tygodnia. (getCalendar().isWeekDateSupported()
)źródło
Dowiedziałem się w przykry sposób z biblioteki znaczników JSTL
format:date
zshort
jak wymaganym formacie wykorzystuje YYYY pod kołdrą. Który rzeczywiście może przesunąć wydrukowaną datę do przodu o rok.źródło
Konwertuję datę w tę iz powrotem - można się spodziewać tego samego roku, kiedy to zrobisz.
Zwróć uwagę, jak się rozwija!
To jest złe: YYYY!
Możesz go uruchomić tutaj .
import java.util.Date; import java.text.SimpleDateFormat; import java.text.ParseException; import static java.lang.System.out; class Playground { public static Date convertYYYYMMDDStr(String s) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date result = null; try { result = sdf.parse(s); } catch(ParseException e) { e.printStackTrace(); } return result; } public static String formatDateToStrWithSDF(Date d, SimpleDateFormat s) { return s.format(d); } public static void main(String[ ] args) { // DON'T DO. Use yyyy instead of YYYY SimpleDateFormat sdfdmy = new SimpleDateFormat("dd-MM-YYYY"); String jan1st2020sb = "2020-01-01"; Date jan1st2020d = convertYYYYMMDDStr(jan1st2020sb); String jan1st2020sa = formatDateToStrWithSDF(jan1st2020d, sdfdmy); out.println(jan1st2020sb); out.println(jan1st2020d); out.println(jan1st2020sa); String dec31st2020sb = "2020-12-31"; Date dec31st2020d = convertYYYYMMDDStr(dec31st2020sb); String dec31st2020sa = formatDateToStrWithSDF(dec31st2020d, sdfdmy); out.println(dec31st2020sb); out.println(dec31st2020d); out.println(dec31st2020sa); } }
To dobrze: yyyy
źródło