analyse syntaxique Date / mise en forme avec TimeZone et SimpleDateFormat donnent des résultats différents autour de commutateur DST

StackOverflow https://stackoverflow.com/questions/2356672

  •  23-09-2019
  •  | 
  •  

Question

Je suis allé parturition plusieurs postes sur TimeZone et SimpleDateFormat sur Google et débordement de la pile, mais ne comprends toujours pas ce que je fais mal. Je travaille sur un code existant, et il y a une parseDate méthode qui donne des résultats erronés.

J'attachais échantillon JUnit que je suis en train d'utiliser n'enquêtons question.

Première méthode (testParseStrangeDate_IBM_IBM) utilise l'implémentation d'IBM pour formater la sortie de parseDate méthode . Deuxième sortie de formats avec la mise en œuvre du Soleil.

Utilisation de SimpleDateFormat Sun nous donne le temps différent d'une heure (ce qui pourrait être lié à la Journée d'épargne Lumière). Réglage de décalage horaire par défaut aux correctifs de mise en œuvre d'IBM parseDate méthode (simplement décommentez 3 lignes dans la méthode setupDefaultTZ).

Je suis sûr que ce n'est pas un bug, mais je suis en train de faire quelque chose de mal.

@Test
public void testParseStrangeDate_IBM_IBM() {
    setupDefaultTZ();

    Calendar date = parseDate("2010-03-14T02:25:00");
    com.ibm.icu.text.SimpleDateFormat dateFormat = new com.ibm.icu.text.SimpleDateFormat(
            "yyyy-MM-dd HH:mm:ss");

    // PASSES:
    assertEquals("2010-03-14 02:25:00", dateFormat.format(date.getTime()));
}

@Test
public void testParseStrangeDate_SUN_SUN() {
    setupDefaultTZ();

    Calendar date = parseDate("2010-03-14T02:25:00");
    java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat(
            "yyyy-MM-dd HH:mm:ss");

    // FAILS:
    assertEquals("2010-03-14 02:25:00", dateFormat.format(date.getTime()));
}

public static Calendar parseDate(String varDate) {
    Calendar cal = null;
    try {
        // DOES NOT MAKE ANY DIFFERENCE:
        // com.ibm.icu.text.SimpleDateFormat simpleDateFormat = new
        // com.ibm.icu.text.SimpleDateFormat(
        // "yyyy-MM-dd'T'HH:mm:ss");
        java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat(
                "yyyy-MM-dd'T'HH:mm:ss", Locale.US);
        Date date = simpleDateFormat.parse(varDate);
        cal = GregorianCalendar.getInstance();
        cal.setTimeInMillis(date.getTime());
        System.out.println("CAL: [" + cal + "]");
    } catch (ParseException pe) {
        pe.printStackTrace();
    }
    return cal;
}

private void setupDefaultTZ() {
    java.util.TimeZone timeZoneSun = java.util.TimeZone.getTimeZone("America/Chicago");
    java.util.TimeZone.setDefault(timeZoneSun);

    // UNCOMMENTING THIS ONE FIXES SUN PARSING ??
    // com.ibm.icu.util.TimeZone timeZoneIbm = com.ibm.icu.util.TimeZone
    // .getTimeZone("America/Chicago");
    // com.ibm.icu.util.TimeZone.setDefault(timeZoneIbm);

    Locale.setDefault(Locale.US);
}
Était-ce utile?

La solution

Le problème est que vous avez spécifié un temps qui n'existe pas. Les horloges avancent de telle sorte que deux heures devient 3h du matin -. 02h25 arrive jamais

Maintenant, il y a différentes options pour ce qui pourrait arriver ici. temps Noda Je crois que nous jetterais une exception (qui est le plan de toute façon); Je crois que Joda Time (Java API beaucoup mieux que Date / Calendrier / SimpleDateFormat - vous devriez envisager la migration vers si vous pouvez éventuellement) vous donnera 3h25, soit 25 minutes après la transition.

Que voulez-vous voulez pour se produire lorsque vous êtes donné une combinaison date / heure qui est impossible en raison de la transition DST? Dans cette situation, il est difficile de savoir ce que vous entendez par les résultats « mauvais ». Je dirais que votre test unitaire est un peu défectueux -. Il n'y a pas de temps possible qui devraient être formaté pour que le temps

Je pense que la raison pour laquelle le fuseau horaire IBM « fonctionne » est qu'il peut utiliser des données de fuseau horaire ancien, d'avant les Etats-Unis a modifié ses transitions DST. Essayez d'utiliser le 28 Mars qui est quand je pense que serait ont été autrement - vous trouverez probablement les tests échouent de la même manière avec la zone IBM, mais pas avec celui Sun :) (Comme la zone Sun ne considérera pas comme une transition DST).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top