2010-04-08 3 views
4

J'utilise java.text.SimpleDateFormat pour analyser des représentations de chaînes de valeurs de date/heure dans un document XML. Je vois tous les temps qui ont une valeur de 12 heures décalée de 12 heures dans le futur, je. e. 20 heures passées passées à midi signifient 20 minutes après minuit le jour suivant.Pourquoi 12h20 analyser à 0:20 le jour suivant?

J'ai écrit un test unitaire qui semble confirmer que l'erreur est faite lors de l'analyse (j'ai vérifié les valeurs de retour de getTime() avec la commande shell linux date). Maintenant, je me demande:

  • Y at-il un bogue dans la méthode parse()?
  • Y at-il un problème avec la chaîne d'entrée?
  • Est-ce que j'utilise la mauvaise chaîne de format pour l'entrée?

Les données d'entrée proviennent du service Yahoo de YWeather. Voici le test et sa sortie:

public class YWeatherReaderTest 
{ 
    public static final String[] rgDateSamples = { 
     "Thu, 08 Apr 2010 12:20 PM CEST", 
     "Thu, 08 Apr 2010 12:20 AM CEST" 
    }; 

    public void dateParsing() throws ParseException 
    { 
     DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy K:m a z", 
                Locale.US); 
     for (String dtsSrc : YWeatherReaderTest.rgDateSamples) { 
      Date dt = formatter.parse(dtsSrc); 
      String dtsDst = formatter.format(dt); 
      System.out.println(dtsSrc); 
      System.out.println(dtsDst); 
      System.out.println(); 
     } 
    } 
} 
 
Thu, 08 Apr 2010 12:20 PM CEST 
Fri, 09 Apr 2010 0:20 AM CEST 

Thu, 08 Apr 2010 12:20 AM CEST 
Thu, 08 Apr 2010 0:20 PM CEST 

La deuxième ligne de sortie de la deuxième itération est un peu bizarre, parce que 00h20 est pas PM. La valeur en millisecondes de l'objet Date correspond cependant au (mauvais) temps de 20 minutes après midi.

+0

Ceci est un autre bel exemple de « SELECT ISN » t cassé ". Même si je n'ai jamais rencontré de bogue dans une bibliothèque standard mature et largement utilisée, j'accuse parfois la bibliothèque si je ne trouve pas le problème. Et jusqu'à présent, j'ai toujours eu tort. –

Répondre

3

Le spécificateur K dans SimpleDateFormat est documented d'utiliser les heures à partir de 0. Je ne sais pas ce qui est censé se produire si vous demandez d'analyser un hors-gamme comme valeur 12 ... il est probablement agir comme si vous entrez 00:20 PM, puis ajoutez 12 heures supplémentaires.

Si vous souhaitez utiliser 12 pendant la première heure, essayez plutôt le spécificateur h.

Pourquoi l'horreur du système d'horloge de 12 heures ne disparaîtra-t-elle pas déjà?

+0

Oui, pourquoi pas? Quoi qu'il en soit, cela a aidé. –

3

Si vous utilisez K dans la chaîne de format, cela va de 0 à 11 (donc 12h20 devrait être 00h20). Vous pouvez essayer d'utiliser h à la place, cela va de 1 à 12, ce que vous attendiez.

http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html

+0

Merci. Votre réponse est essentiellement la même que celle de Bobince, mais la sienne est (très) légèrement plus précise, alors j'ai accepté celle-là et j'ai voté pour la vôtre. J'espère que c'est OK. –

1

Si vous utilisez K .... etc etc ... (lire la réponse de bobince)

Pour forcer le comportement attendu (et lancer une exception d'analyse lors de l'utilisation 12) définie sur false propriété clémente de l'analyseur :

.... 
DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy K:m a z", 
               Locale.US); 
formatter.setLenient(false); 
for (String dtsSrc : YWeatherReaderTest.rgDateSamples) { 
.... 

sortie:

java YWeatherReaderTest 
Exception in thread "main" java.text.ParseException: Unparseable date: "Thu, 08 Apr 2010 12:20 PM CEST" 
at java.text.DateFormat.parse(DateFormat.java:335) 
at YWeatherReaderTest.dateParsing(YWeatherReaderTest.java:17) 
at YWeatherReaderTest.main(YWeatherReaderTest.java:25) 
+0

C'est bon à savoir. –

0

en tant que marque de côté: Je suggère fortement de passer à temps Joda.

Les fonctions de java.util.date ont tendance à deviner (ce qui dans votre cas n'était pas ce que vous attendiez). Joda Time jette une exception si ce n'est pas en fonction des spécifications.

Ceci est proche de ce que vous avez:

String s = "Thu, 08 Apr 2010 12:20 PM"; 
String format = "EEE, dd MMM yyyy h:m a"; 
DateTimeFormatter fmt = DateTimeFormat.forPattern(format).withLocale(Locale.US); 
System.out.println(fmt.parseDateTime(s)); 

Bien que le temps Joda semble ne pas soutenir encore l'analyse syntaxique du fuseau horaire (voir http://joda-time.sourceforge.net/api-release/org/joda/time/format/DateTimeFormat.html)

Questions connexes