2009-11-11 17 views
13

Ich benutze die Joda time (1.6) Bibliotheken und es gibt immer wieder DateTime Objekte mit der falschen Zeitzone, British Summer Time statt GMT.Joda Zeit gibt falsche Zeitzone

Meine Windows-Workstation (mit JDK 1.6.0_16) denkt, es ist in GMT und wenn ich die Standardzeitzone von den JDK-Datum/Uhrzeit-Klassen bekomme, ist es korrekt (GMT). Ich bekomme das gleiche Verhalten auf unseren Linux-Servern. Ich dachte, es könnte ein Fehler in den Zeitzonen-Datenbankdateien in Joda sein, also habe ich das Jar mit der neuesten Datenbank neu erstellt, aber ohne Änderung.

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"    
    } 
} 

Debugging durch den statischen initialiser in org.joda.time.DateTimeZone ich sehe, dass die System.getProperty("user.timezone") Anruf "Europe/London" gibt wie erwartet.

+0

erweiterte Antwort zur Erklärung des realen Problems – jitter

Antwort

30

Ok, um zu der Wurzel davon zu kommen, müssen Sie sich damit vertraut machen, was British Summer Time eigentlich bedeutet und wann es an seinem Platz war. Um es kurz zu machen, übergibt man 0L an getName(), was 1970-01-01T00:00:00Z ist, also sucht den Namen der Zeitzone in diesem Moment. Was war die britische Sommerzeit?

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

1968 Uhren eine Stunde vorgestellt wurden vor GMT am 18. Februar und blieb so bis British Standard Zeit, in der Uhren in vor GMT das ganze Jahr gehalten wurden, kam in Kraft zwischen dem 27. Oktober 1968 bis 31. Oktober 1971

Wenn Sie stattdessen in der richtigen Menge an Millisekunden sinc passieren würde e 1970-01-01T00:00:00Z. z.B.

defaultTimeZone.getName(new GregorianCalendar().getTimeInMillis()) 

Sie würden auch die richtige Zeichenfolge erhalten. Im Grunde haben Sie nur die getName() Methode den falschen Parameter gefüttert, so endete mit einem unerwarteten Ergebnis.

Wenn Sie im Detail überprüfen möchten, überprüfen Sie die Dateien in org/joda/time/tz/src von Joda Quelle, um zu sehen, wie Joda Zeitzonen bestimmt.


Statt

defaultTimeZone.getName(0L) 

könnten Sie

defaultTimeZone.toTimeZone().getDisplayName() 

benutzen, die es für mich tut.

+6

Ehrfürchtig.Wer hätte das gedacht? Ich hatte buchstäblich gesagt: "Es ist unmöglich, dass der 1. Januar 1970 in der britischen Sommerzeit war". Mehr täusche mich. Dies erklärt auch das zugrunde liegende Problem, das zu der Frage führte, die "10: 00: 00.0000000 + 00: 00" mit ISODateTimeFormat.timeParser() zu einer DateTime in GMT + 1 führte. Das liegt daran, dass Joda keine unabhängige Vorstellung von Zeit und Datum hat, also analysiert diese Zeit relativ zum 1. Januar 1970, was, wie Sie sagten, GMT + 1 war! Verrückt. Vielen Dank. – matthewKizoom

+0

+1 für relevant und ein wenig Geschichtsstunde auch – I82Much

0

Es interessieren Sie können die statische initialiser für die DateTimeZone Klasse in 1,6 zu sehen:

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; 
    } 
} 

Meine Vermutung ist, dass Sie eine user.timezone Eigenschaft definiert (und auf BST) haben. Ansonsten sieht es so aus, als würde Joda eine eigene Zeitzoneninstanz basierend auf der JDK-Zeitzone erstellen. und ich würde erwarten, dass irgendwelche Bugs in diesem Bereich, insbesondere das Konvertieren einer GMT-Zone, inzwischen aufgegriffen worden wären.

+0

user.timezone gibt "Europa/London" (Ich habe dies auf die Frage hinzugefügt). – matthewKizoom