2009-11-11 5 views
13

J'utilise les bibliothèques Joda time (1.6) et il continue de renvoyer les objets DateTime avec le mauvais fuseau horaire, l'heure d'été britannique au lieu de GMT.Joda Time donne un mauvais fuseau horaire

Mon poste de travail Windows (exécutant JDK 1.6.0_16) pense qu'il est en GMT et si le fuseau horaire par défaut des classes date/heure du JDK est correct (GMT). J'ai le même comportement sur nos serveurs Linux. J'ai pensé que cela pourrait être une erreur dans les fichiers de base de données de fuseaux horaires dans Joda, donc j'ai reconstruit le pot avec la dernière base de données, mais sans changement.

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 par la statique dans org.joda.time.DateTimeZone initialiseur je vois que l'appel System.getProperty("user.timezone") donne "Europe/London" comme prévu.

+0

réponse étendue pour fournir une explication du problème réel – jitter

Répondre

30

Ok, pour aller à la racine de tout cela, vous devez vous familiariser avec ce que British Summer Time signifie réellement et quand il était en place. Pour faire court, vous passez 0L à getName() qui est 1970-01-01T00:00:00Z alors DefaultTimeZone recherche le nom du fuseau horaire à ce moment-là. Ce qui était l'heure d'été britannique.

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

En 1968, les horloges ont été avancée d'une heure avant GMT le 18 Février et sont restés jusqu'à ce que la norme britannique temps, au cours de laquelle les horloges ont été conservés dans avant GMT toute l'année, est entré en vigueur entre le 27 Octobre 1968 et le 31 Octobre 1971.

Si vous plutôt passer la bonne quantité de millisecondes sinc e 1970-01-01T00:00:00Z. par exemple. en faisant

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

Vous obtiendrez la chaîne correcte aussi. Fondamentalement, vous juste alimenté la méthode getName() le mauvais paramètre a donc fini avec un résultat inattendu.

Si vous voulez vérifier en détail vérifiez les fichiers dans org/joda/time/tz/src de joda source pour voir comment joda détermine les fuseaux horaires.


Au lieu de

defaultTimeZone.getName(0L) 

vous pouvez utiliser

defaultTimeZone.toTimeZone().getDisplayName() 

qui le fait pour moi.

+6

Génial.Qui aurait pensé. J'avais littéralement dit: "Il n'y a pas moyen que le 1er janvier 1970 soit à l'heure d'été britannique". Plus me tromper. Cela explique également le problème sous-jacent qui a conduit à la question qui consistait à analyser "10: 00: 00.0000000 + 00: 00" avec ISODateTimeFormat.timeParser() pour obtenir un DateTime en GMT + 1. C'est parce que Joda n'a pas de notion indépendante de Time and Date donc analyse cette fois par rapport au 1er janvier 1970 qui, comme vous l'avez souligné était GMT + 1! Fou. Merci. – matthewKizoom

+0

+1 pour être pertinent et une petite leçon d'histoire aussi – I82Much

0

Il peut vous intéresser de voir la statique pour la initialiseur classe DateTimeZone en 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; 
    } 
} 

Je suppose que vous avez une user.timezone propriété définie (et réglé sur BST). Sinon, il semble que Joda devrait créer sa propre instance de fuseau horaire basée sur le fuseau horaire JDK; et je m'attendrais à ce que des bugs dans ce domaine, en particulier la conversion d'une zone GMT, aient été détectés maintenant.

+0

user.timezone donne "Europe/London" (j'ai ajouté ceci à la question). – matthewKizoom