2013-05-07 15 views
9
package check; 

import java.util.Calendar; 

public class Test { 
    public static void main(String[] args) { 
     // length of a day 
     long DAY_MILLIS = 1000 * 60 * 60 * 24; 

     Calendar cal = Calendar.getInstance(); 

     cal.set(1900, 0, 1, 0, 0, 0); 
     System.out.println(cal.getTime()); 

     cal.setTimeInMillis(cal.getTimeInMillis() + DAY_MILLIS); 
     System.out.println(cal.getTime()); 
    } 
} 

I to wynikiem jest:30 minut w obliczeniu daty Java w roku 1900 tylko

Mon Jan 01 00:00:00 KST 1900 
Mon Jan 01 23:30:00 KST 1900 // Where is 30 minutes here? 

Najbardziej zabawny i ważną wskazówką jest to, że ten problem występuje, gdy jest tylko 1900 roku.

+1

może być związane z [tej kwestii] (http://stackoverflow.com/q/6841333/732016)? – wchargin

+0

Zdecydowanie pokrewne. Ten sam podstawowy problem ... czas jest skomplikowany. –

+0

Próbowałem tego i otrzymuję 'Wt Jan 02 00:00:00 EST 1900'.Coś związanego ze strefami czasowymi? –

Odpowiedz

3

Wynika to z historycznych zmian przesunięcia GMT. Zobacz przykład tutaj: http://www.timeanddate.com/worldclock/timezone.html?n=101&syear=1900. Te zmiany są różne w różnych strefach czasowych. Na przykład w moim strefy czasowej (EET) wynik testu jest inna:

Mon Jan 01 00:00:00 EET 1900 
Mon Jan 01 23:39:52 EET 1900 

ponieważ (według Java) zegary były zwrócone do przodu 0:20:08 godzin w dniu 1 stycznia 1900 w EET. TimeZone ma metody określania przesunięcia dla konkretnej daty, TimeZone.getOffset (długa data) API

Ta metoda zwraca historycznie poprawną wartość przesunięcia, jeśli podstawowa podklasa implementacji TimeZone obsługuje historyczny harmonogram czasu letniego i zmiany przesunięcia GMT.

Należy pamiętać, że jeśli ustawisz Kalendarz na GMT i wydrukuje wynik w GMT, nie będzie żadnego błędu.

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    df.setTimeZone(TimeZone.getTimeZone("GMT")); 
    Calendar cal = Calendar.getInstance(); 
    cal.setTimeZone(TimeZone.getTimeZone("GMT")); 
    cal.set(1900, 0, 1, 0, 0, 0); 
    System.out.println(df.format(cal.getTime())); 
    cal.setTimeInMillis(cal.getTimeInMillis() + 1000 * 60 * 60 * 24); 
    System.out.println(df.format(cal.getTime())); 

wyjście

1900-01-01 00:00:00 
1900-01-02 00:00:00 
3

Takie nieprawidłowości w datach przetwarzania są częste. Zobacz np. Jon Skeet's most famous answer. Szukam rzeczywistej bazy danych tych trzasków; zaktualizuje odpowiedź po znalezieniu.

Ta odpowiedź jest dość niekompletna, ale może wystarczyć, aby odblokować; Zostawię to, ale zachęcam do zaakceptowania bardziej kompletnego, jeśli zostanie opublikowany.

+0

Wow, epicka, zabawna odpowiedź Skeeta. –

0
public static void main(String[] args) { 
     // length of a day 
     long DAY_MILLIS = 1000 * 60 * 60 * 24; 

     Calendar cal = Calendar.getInstance(); 

     cal.set(1900, 0, 1, 0, 0, 0); 
     System.out.println(cal.getTime()); 
     System.out.println(cal.getTimeInMillis()); 
     System.out.println(DAY_MILLIS); 
     System.out.println(cal.getTimeInMillis() + DAY_MILLIS); 
     cal.setTimeInMillis(cal.getTimeInMillis() + DAY_MILLIS); 
     System.out.println(cal.getTime()); 
    } 

Pon 01 styczeń 00:00:00 CST 1900

-2209017599564

-2208931199564

Wto 02 stycznia 00:05:52 CST 1900

Wygląda na to, że .getTimeInMillis() zwraca wartość różniącą się od oczekiwanej.

getTimeInMillis

publiczne długie getTimeInMillis()

zwraca wartość czas ten kalendarz w milisekundach.

Powraca: aktualny czas jako UTC milisekund od epoki.