1927: Der Moment, als die Zeit rückwärts lief
\n\nStellen Sie sich vor: Sie schreiben in Java ein einfaches Skript, um die Differenz zwischen zwei Daten in Millisekunden zu berechnen. Sie nehmen das Jahr 1927, subtrahieren einen Wert vom anderen – und erhalten nicht 3600 Sekunden (eine Stunde), sondern eine seltsame Zahl. Sie überprüfen den Code, googeln und finden die legendäre Frage auf StackOverflow mit tausenden Aufrufen. Und Sie verstehen: Sie sind nicht allein.
\n\nDieser Bug ist ein echtes historisches Artefakt, das Anfänger bis heute erschreckt. In diesem Artikel analysieren wir, warum die Subtraktion von epoch-milli-Zeiten im Jahr 1927 ein seltsames Ergebnis liefert, zeigen es an echten Java-Codebeispielen und geben Ihnen vor allem praktische Methoden, um diese Falle zu vermeiden. Wenn Sie mit historischen Daten arbeiten oder einfach zuverlässigen Code schreiben möchten, sind diese Informationen für Sie.
\n\nDas Kernproblem: Die Magie des 31. Dezember 1927
\n\nKommen wir direkt zum Code. Hier ist ein klassisches Beispiel, das den Kopf verdreht:
\n\nimport java.util.TimeZone;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\npublic class StrangeDateDifference {\n public static void main(String[] args) throws Exception {\n TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");\n SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");\n sdf.setTimeZone(tz);\n\n Date date1 = sdf.parse("1927-12-31 23:54:07");\n Date date2 = sdf.parse("1927-12-31 23:54:08");\n\n long diff = date2.getTime() - date1.getTime();\n System.out.println("Differenz in Millisekunden: " + diff);\n // Erwartet 1000, aber erhält...\n }\n}\n\nSie führen es aus – und statt 1000 Millisekunden (1 Sekunde) sehen Sie 353? Oder sogar eine negative Zahl? Herzlichen Glückwunsch, Sie sind auf den Fehler bei der Subtraktion von Daten aus dem Jahr 1927 gestoßen.
\n\nDie Ursache liegt nicht in einem Java-Bug (obwohl es auch einen gibt, aber dazu später). Der Grund ist eine historische Änderung der Zeitzone. Am 31. Dezember 1927 geschah in Shanghai (Asia/Shanghai) etwas Seltsames: Um 23:54:08 wurde die Ortszeit um 5 Minuten und 52 Sekunden zurückgestellt. Tatsächlich dauerte eine Sekunde nicht 1000 ms, sondern nur 353 ms. Java verarbeitet diese historische Tatsache korrekt, aber für den Entwickler wirkt es wie Magie.
\n\nDie häufigsten Fehler, die Entwickler machen
\n\n1. Blindes Vertrauen in alte APIs (java.util.Date und SimpleDateFormat)
\n\nDer erste und häufigste Fehler ist die Verwendung der veralteten Klassen java.util.Date und SimpleDateFormat. Sie sind nicht nur unpraktisch, sondern enthalten auch versteckte Überraschungen, insbesondere bei der Arbeit mit historischen Daten.
Wie man es vermeidet: Verwenden Sie java.time (Java 8+). Zum Beispiel:
import java.time.LocalDateTime;\nimport java.time.ZoneId;\nimport java.time.ZonedDateTime;\nimport java.time.format.DateTimeFormatter;\n\npublic class SafeDateDifference {\n public static void main(String[] args) {\n DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");\n ZoneId zone = ZoneId.of("Asia/Shanghai");\n\n LocalDateTime ldt1 = LocalDateTime.parse("1927-12-31 23:54:07", formatter);\n LocalDateTime ldt2 = LocalDateTime.parse("1927-12-31 23:54:08", formatter);\n\n ZonedDateTime zdt1 = ldt1.atZone(zone);\n ZonedDateTime zdt2 = ldt2.atZone(zone);\n\n long diff = zdt2.toInstant().toEpochMilli() - zdt1.toInstant().toEpochMilli();\n System.out.println("Differenz in Millisekunden: " + diff);\n // Sie erhalten trotzdem eine seltsame Zahl, wissen aber wenigstens, warum!\n }\n}\n\n2. Ignorieren historischer Änderungen von Zeitzonen
\n\nViele denken, Zeitzonen seien einfach eine feste Verschiebung gegenüber UTC. Tatsächlich haben sie sich in den letzten 100 Jahren dutzende Male geändert.