Warum ergibt die Differenz zwischen dem 30. März und dem 1. März 2020 fälschlicherweise 28 statt 29 Tage?

TimeUnit.DAYS.convert(
   Math.abs(
      new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("30-03-2020 00:00:00").getTime() - 
      new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("1-03-2020 00:00:00").getTime()
   ),
   TimeUnit.MILLISECONDS)

Das Ergebnis ist 28, obwohl es 29 sein sollte. Könnte die Zeitzone/der Standort das Problem sein?

Kommentare zu der Frage (6)
Lösung

Das Problem ist, dass wegen der Sommerzeitumstellung (am Sonntag, 8. März 2020) 28 Tage und 23 Stunden zwischen diesen Daten liegen. TimeUnit.DAYS.convert(...)` kürzt das Ergebnis auf 28 Tage ab.

Um das Problem zu sehen (ich bin in der US Eastern Zeitzone):

SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
long diff = fmt.parse("30-03-2020 00:00:00").getTime() -
            fmt.parse("1-03-2020 00:00:00").getTime();

System.out.println(diff);
System.out.println("Days: " + TimeUnit.DAYS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Hours: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Days: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS) / 24.0);

Output

``lang-nein 2502000000 Tage: 28 Stunden: 695 Tage: 28.958333333333332


Um dies zu beheben, verwenden Sie eine Zeitzone ohne Sommerzeit, z.B. **UTC**:

SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); fmt.setTimeZone(TimeZone.getTimeZone("UTC")); long diff = fmt.parse("30-03-2020 00:00:00").getTime() - fmt.parse("1-03-2020 00:00:00").getTime();



*Output*

``lang-nein
2505600000
Tage: 29
Stunden: 696
Tage: 29.0
Kommentare (15)

Die Ursache für dieses Problem wurde bereits in Andreas's Antwort erwähnt.

Die Frage ist, was genau Sie zählen wollen. Die Tatsache, dass Sie angeben, dass die tatsächliche Differenz 29 statt 28 sein sollte, und fragen, ob "Standort/Zonenzeit ein Problem sein könnte", zeigt, was Sie eigentlich zählen wollen. Offensichtlich wollen Sie jeden Zeitzonenunterschied loswerden.

Ich nehme an, Sie wollen nur die Tage berechnen, ohne Zeit und Zeitzone.

Java 8

Im folgenden Beispiel, wie die Anzahl der Tage dazwischen korrekt berechnet werden könnte, verwende ich eine Klasse, die genau das darstellt - ein Datum ohne Zeit und Zeitzone - LocalDate.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MM-yyyy HH:mm:ss");
LocalDate start = LocalDate.parse("1-03-2020 00:00:00", formatter);
LocalDate end = LocalDate.parse("30-03-2020 00:00:00", formatter);

long daysBetween = ChronoUnit.DAYS.between(start, end);

Beachten Sie, dass ChronoUnit, DateTimeFormatter und LocalDate mindestens Java 8 benötigen, was Ihnen laut [tag:java-7] nicht zur Verfügung steht. Aber vielleicht ist es für zukünftige Leser verfügbar.

Wie von Ole V.V. erwähnt, gibt es auch den ThreeTen Backport, der die Java 8 Date and Time API Funktionalität auf Java 6 und 7 zurückportiert.

Kommentare (2)