2009-11-11 11 views
13

Korzystam z bibliotek Joda time (1.6) i zachowuje on powracające obiekty DateTime ze złej strefy czasowej, brytyjski czas letni zamiast GMT.Czas Jody podaje niewłaściwą strefę czasową

Moja stacja robocza Windows (z JDK 1.6.0_16) myśli, że jest w GMT i jeśli otrzymam domyślną strefę czasową z klas daty/czasu JDK, jest ona poprawna (GMT). Podobne zachowanie występuje również na naszych serwerach Linux. Pomyślałem, że może to być błąd w plikach bazy danych strefy czasowej w Jodzie, więc przebudowałem słoik z najnowszą bazą danych, ale bez żadnych zmian.

import java.util.TimeZone; 
import org.joda.time.DateTime; 
import org.joda.time.DateTimeZone; 
import org.joda.time.LocalTime; 
import org.joda.time.format.DateTimeFormatter; 
import org.joda.time.format.ISODateTimeFormat; 

public class TimeZoneTest { 

    public static void main(String[] args) {     
     DateTimeFormatter timeParser = ISODateTimeFormat.timeParser(); 
     TimeZone timeZone = TimeZone.getDefault(); 
     System.out.println(timeZone.getID()); // "Europe/London" 
     System.out.println(timeZone.getDisplayName()); // "Greenwich Mean Time" 

     DateTimeZone defaultTimeZone = DateTimeZone.getDefault(); 
     System.out.println(defaultTimeZone.getID()); //"Europe/London" 
     System.out.println(defaultTimeZone.getName(0L)); //"British Summer Time" 

     DateTime currentTime = new DateTime(); 
     DateTimeZone currentZone = currentTime.getZone(); 
     System.out.println(currentZone.getID()); //"Europe/London" 
     System.out.println(currentZone.getName(0L)); //"British Summer Time"    
    } 
} 

debugowanie poprzez statyczną initialiser w org.joda.time.DateTimeZone widzę, że rozmowa System.getProperty("user.timezone") daje "Europe/London" jak oczekiwano.

+0

rozszerzona odpowiedź na wyjaśnienie prawdziwego problemu – jitter

Odpowiedz

30

Ok, aby dostać się do korzeni tego, musisz zapoznać się z tym, co oznacza czas letni w Wielkiej Brytanii i kiedy było na miejscu. Aby go skrócić, należy podać 0L do getName(), który jest 1970-01-01T00:00:00Z, więc DefaultTimeZone wyszukuje nazwę strefy czasowej w tym momencie. Jaki był brytyjski czas letni.

Od: http://www.nmm.ac.uk/explore/astronomy-and-time/time-facts/british-summer-time

W 1968 zegary zostały rozszerzone jedną godzinę wyprzedza GMT w dniu 18 lutego i tak pozostało aż do British Standard czasu, w którym zegary były trzymane w wyprzedzeniem GMT przez cały rok, weszła w siła między 27 października 1968 a 31 października 1971.

Jeśli zamiast tego przekazać w odpowiedniej ilości milisekund sinc e 1970-01-01T00:00:00Z. na przykład poprzez wykonanie

Dostaniesz również prawidłowy ciąg. Zasadniczo właśnie wprowadzono metodę getName() jako zły parametr, co zakończyło się nieoczekiwanym wynikiem.

Jeśli chcesz sprawdzić szczegóły sprawdź pliki w org/joda/time/tz/src źródła joda, aby zobaczyć, jak joda określa strefy czasowe.


Zamiast

defaultTimeZone.getName(0L) 

można użyć

defaultTimeZone.toTimeZone().getDisplayName() 

który zrobi to za mnie.

+6

Awesome.Kto by pomyślał. Dosłownie powiedziałem: "Nie ma mowy, aby 1 stycznia 1970 roku był w brytyjskim okresie letnim". Więcej mnie oszukuj. To również wyjaśnia podstawowy problem, który doprowadził do pytania, które było parsowanie "10: 00: 00.0000000 + 00: 00" z ISODateTimeFormat.timeParser() spowodowało DateTime w GMT + 1. Dzieje się tak dlatego, że Joda nie ma niezależnego pojęcia czasu i daty, więc tym razem jest analizowany w odniesieniu do 1 stycznia 1970, który, jak wskazałeś, był GMT + 1! Zwariowany. Dzięki. – matthewKizoom

+0

+1 za bycie odpowiednim i lekcję historii – I82Much

0

To może Cię zainteresują zobaczyć statyczną initialiser dla klasy DateTimeZone w 1.6:

static { 
    setProvider0(null); 
    setNameProvider0(null); 

    try { 
     try { 
      cDefault = forID(System.getProperty("user.timezone")); 
     } catch (RuntimeException ex) { 
      // ignored 
     } 
     if (cDefault == null) { 
      cDefault = forTimeZone(TimeZone.getDefault()); 
     } 
    } catch (IllegalArgumentException ex) { 
     // ignored 
    } 

    if (cDefault == null) { 
     cDefault = UTC; 
    } 
} 

Domyślam się, że masz user.timezone właściwość zdefiniowaną (i ustawiony na BST). W przeciwnym razie wygląda na to, że Joda powinna utworzyć własną instancję strefy czasowej na podstawie strefy czasowej JDK; i spodziewam się, że wszelkie błędy w tej dziedzinie, w szczególności konwersja strefy GMT, zostałyby już zebrane.

+0

użytkownik.timezone podaje "Europa/Londyn" (dodałem to do pytania). – matthewKizoom

Powiązane problemy