6762 votes

Pourquoi est soustrayant ces deux fois (en 1927), donnant un résultat étrange?

Si j'exécute le programme suivant, qui traite de deux chaînes date de référencement de temps d'une seconde d'intervalle et les compare:

public static void main(String[] args) throws ParseException {
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String str3 = "1927-12-31 23:54:07";  
    String str4 = "1927-12-31 23:54:08";  
    Date sDt3 = sf.parse(str3);  
    Date sDt4 = sf.parse(str4);  
    long ld3 = sDt3.getTime() /1000;  
    long ld4 = sDt4.getTime() /1000; 
    System.out.println(ld3);  
    System.out.println(ld4);  
    System.out.println(ld4-ld3);
}

La sortie est:

-1325491905
-1325491552
353

Pourquoi est - ld4-ld3 pas 1 (comme je m'attends à partir de la seconde de différence dans le temps), mais 353?

Si je change les dates pour le temps d'une seconde plus tard:

String str3 = "1927-12-31 23:54:08";  
String str4 = "1927-12-31 23:54:09";  

Ensuite, ld4-ld3 sera 1


Mise à JOUR

Version de Java:

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)

Le fuseau horaire(TimeZone.getDefault()):

sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]

Locale(Locale.getDefault()): zh_CN

10787voto

Jon Skeet Points 692016

C'est un temps de changement de zone le 31 décembre à Shanghai.

Voir cette page pour les détails de 1927 à Shanghai. Fondamentalement, à minuit, à la fin de 1927, les horloges revint 5 minutes et 52 secondes. Donc "1927-12-31 23:54:08" réellement arrivé deux fois, et il semble que Java est de l'analyser en tant que le plus tard possible instantanée pour que les locaux de la date/le temps - d'où la différence.

Juste un autre épisode de la souvent étrange et le merveilleux monde des fuseaux horaires.

EDIT: Arrêtez la presse! L'histoire change...

La question d'origine n'auraient plus à démontrer tout à fait le même comportement, si reconstruite avec la version 2013a de TZDB. Dans 2013a, le résultat serait 358 secondes, avec un temps de transition de 23:54:03 au lieu de 23:54:08.

J'ai seulement remarqué cela parce que je suis la collecte de ce genre de questions dans Noda Temps, sous la forme de tests unitaires... Le test a été changé, mais il va juste pour montrer, même pas des données historiques est sûr.

EDIT: l'Histoire a changé de nouveau...

Dans TZDB 2014p, l'heure du changement a déménagé à 1900-12-31, et c'est maintenant une simple 343 deuxième changement (si le temps entre t et t+1 est 344 secondes, si vous voyez ce que je veux dire).

EDIT: pour répondre À Ken Kin la question autour d'une transition à 1900... il ressemble à la Java le fuseau horaire de mise en œuvre de traite toutes les zones de temps que de simplement en leur temps standard pour quelque instant avant le début de 1900 UTC:

import java.util.TimeZone;

public class Test {
    public static void main(String[] args) throws Exception {
        long startOf1900Utc = -2208988800000L;
        for (String id : TimeZone.getAvailableIDs()) {
            TimeZone zone = TimeZone.getTimeZone(id);
            if (zone.getRawOffset() != zone.getOffset(startOf1900Utc - 1)) {
                System.out.println(id);
            }
        }
    }
}

Le code ci-dessus donne le résultat sur ma machine Windows. Donc, à tout moment de la zone qui a tout décalage autre que son niveau au début de 1900 comptera que comme une transition. TZDB a lui-même certains de données de revenir plus tôt, et ne pas compter sur la moindre idée d'un "fixe" (qui est ce que l' getRawOffset suppose être un concept valide) si d'autres bibliothèques n'ont pas besoin de présenter cette artificielle de transition.

1587voto

Michael Borgwardt Points 181658

Vous avez rencontré un heure locale discontinuité:

Lorsque le temps local était sur le point d'atteindre le dimanche, 1. En janvier 1928, 00:00:00 les horloges étaient retroussées, 0:05:52 heures de samedi, 31. En décembre 1927, 23:54:08, heure normale locale à la place

Ce n'est pas particulièrement étrange et s'est passé un peu partout, à un moment ou à un autre comme les fuseaux horaires qui ont été changés ou modifiés pour des raisons politiques ou mesures administratives.

653voto

Raedwald Points 8862

La morale de cette étrangeté est:

  • L'utilisation des dates et des heures au format UTC dans la mesure du possible.
  • Si vous ne pouvez pas afficher une date ou l'heure UTC, il faut toujours indiquer le fuseau horaire.
  • Si vous ne pouvez pas besoin d'un apport de date/heure en UTC, exigent explicitement indiqué fuseau horaire.

363voto

PatrickO Points 1341

Lors de l'incrémentation de temps vous devez les convertir en arrière à l'UTC, puis ajouter ou soustraire. Utilisation de l'heure locale uniquement pour l'affichage.

De cette façon vous serez en mesure de marcher à travers les périodes où les heures ou les minutes se produire deux fois.

Si vous avez converti à l'UTC, ajouter à chaque seconde, et de les convertir à l'heure locale pour l'affichage. Vous allez à 11:54:08 h LMT - 11:59:59 h LMT puis 11:54:08 h CST - 11:59 h 59 CST.

207voto

Jacob Points 17521

J'ai couru votre code, le résultat est:

-1325466353
-1325466352
1

Et:

-1325466352
-1325466351
1

sur:

$ java -version
java version "1.6.0_20"
OpenJDK Runtime Environment (IcedTea6 1.9.7) (fedora-52.1.9.7.fc14-i386)
OpenJDK Client VM (build 19.0-b09, mixed mode)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X