2016-01-09 30 views
10

Rozpoczęło się to od prostego błędu: miałem YYYY zamiast yyyy w ciągu mojego formatu dla obiektu SimpleDateFormat. Ale jestem całkowicie zaskoczony wynikami moich testów z niepoprawnym łańcuchem formatu.Jak działa "tydzień tygodnia" Java?

ten kod:

@Test 
public void whatTheHell() { 
     try { 
       SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/YYYY"); 

       Date d1 = sdf.parse("01/07/2016"); 
       Date d2 = sdf.parse("02/08/2016"); 
       Date d3 = sdf.parse("11/29/2027"); 

       System.out.println(d1.toString()); 
       System.out.println(d2.toString()); 
       System.out.println(d3.toString()); 
     } catch (ParseException pe) { 
       fail("ParseException: " + pe.getMessage()); 
     } 
} 

produkuje ten wyjściowe:

Sun Dec 27 00:00:00 PST 2015 
Sun Dec 27 00:00:00 PST 2015 
Sun Dec 27 00:00:00 PST 2026 

Czytałem dokumentację na parametrze 'Y' tutaj: https://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html, ale ja nadal nie widzę logiki to działa tutaj. W szczególności ostatnia instancja: mogę trochę posortować, jak daty w styczniu (& może być w lutym) można przetłumaczyć na grudzień poprzedniego roku, ale przeniesienie daty 29 listopada wstecz o 11 miesięcy mnie zaskakuje. A co jest wyjątkowego w dniu 27 grudnia?

Czy ktoś może wyjaśnić?

WIĘCEJ INFORMACJI

@Jan zasugerował, że opierając się na metodzie toString() może być problem, więc zdefiniowany format daty, aby wydrukować YYYY MM dd '-' yyyy MM dd w tym samym kodzie, jak powyżej. Oto dodatkowe wyjście:

2016 12 27 - 2015 12 27 
2016 12 27 - 2015 12 27 
2027 12 27 - 2026 12 27 
+1

powołując się na toString(), aby uczynić coś przydatny jest również optymistyczny. Możesz użyć innego DateFormat dla danych wyjściowych. Jak jeden obejmujący zarówno yyyy i YYYY? – Jan

+0

Zobacz [tutaj] (http: // stackoverflow.com/questions/8686331/y-zwraca-2012-while-y-zwraca-2011-in-simpledateformat) dla wyjaśnienia roku VS tydzień roku – theo

+0

@theo Dzięki, ale to wyjaśnia tylko zmiany, jeśli data jest pierwsza lub ostatnia Tydzień w roku, co jest możliwe tylko w przypadku pierwszego z moich trzech przykładów. –

Odpowiedz

3

To proste: 27 grudnia 2015 jest dzień 1 tydzień 1 tydzień roku 2016 (oraz 27 grudnia 2026 jest dzień 1 tydzień 1 tydzień roku 2027). Można to sprawdzić poprzez dodanie następującej linii:

SimpleDateFormat odf = new SimpleDateFormat("YYYY-ww-u"); 
System.out.println(odf.format(d1)); 
System.out.println(odf.format(d2)); 
System.out.println(odf.format(d3)); 

Jeśli SimpleDateFormat wyprowadza data może korzystać ze wszystkich pól: rok, miesiąc, dzień, dzień tygodnia, tydzień miesiąca, tydzień w roku, tydzień, rok itp .

Na parsowania, SimpleDateFormat oczekuje dopasowanie zestawu wartości: albo dzień, miesiąc, rok lub dzień tygodnia, tydzień w roku, tydzień roku. Ponieważ tydzień roku dostarczane, ale nie dostarczy dzień tygodnia i tydzień w roku, aby wartości te zostały przyjęte jako 1.


Rzeczywiste wartości zależą od regionu:

  • który tygodniem roku jest tydzień 1
  • który dzień jest pierwszym dniem tygodnia

(patrz https://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html#week_and_year)

W moim systemie (przy użyciu locale de-CH, ze "EEE MMM DD hh: mm: ss zzz yyyy - YYYY-WW-u" jako format) uzyskać

Mo Jan 04 00:00:00 MEZ 2016 - 2016-01-1 
Mo Jan 04 00:00:00 MEZ 2016 - 2016-01-1 
Mo Jan 04 00:00:00 MEZ 2027 - 2027-01-1
+0

inaczej poprawne, ale "i z roku 2027" jest z pewnością źle. Napraw tę część odpowiedzi. Nie ma sensu, aby rok 2015 był zgodny z rokiem 2027. – eis

+0

Nie do końca: wynik dla "u" we wszystkich tych przypadkach wynosi 7, a nie 1. Ale w przeciwnym razie jest poprawny: parsowanie faktycznie całkowicie ignoruje podane wartości dla 'MM' i' dd'. Nie mogę znaleźć żadnej dokumentacji tego zachowania. –

+0

@DaveMulligan dzięki za opinię. Rzeczywiste wartości zależą od ustawień regionalnych systemu, więc poprawiłem moją odpowiedź. –