Hinzufügen von Tagen mit java.util.Kalender gibt merkwürdige Ergebnisse
Verwendung von java.util.Kalender hinzufügen, um einen einzelnen Tag zu einem Datum, und " = SimpleDateFormat um das Ergebnis anzuzeigen, manchmal zu verlieren scheint am Tag (in der Regel im März) und manchmal überspringt einen Tag (im November).
Das Programm unten mit Ausgabe, illustriert das Problem. Bemerken, dass ich nur das hinzufügen eines Tages zu einer Zeit, dann überspringen ein paar Monate, und das hinzufügen von ein paar mehr Tage. Sie werden sehen, dass 2008-03-09 wird zweimal gedruckt, aber 2008-11-02 übersprungen. Das gleiche passiert in anderen Jahren, aber an verschiedenen Tagen. Ich hatte zu Experimentieren, um herauszufinden, die Tage, die das problem verursachen.
Wenn ich nicht setzen der Zeitzone zu UTC in der " = SimpleDateFormat dann das problem nicht auftreten. Ich lief dies auf eine Maschine der US Central Time Zone.
Dies sicherlich sieht aus wie ein bug in der Kalender-oder " = SimpleDateFormat, aber ich habe nicht in der Lage, es zu finden, dokumentiert irgendwo. Jemand eine Erklärung, was ist hier passiert?
Programm:
package mab;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class CalendarHiccup2 {
public static void main(String[] args) {
addDays("2008-03-08");
addDays("2009-03-07");
addDays("2010-03-13");
}
public static void addDays(String dateString) {
System.out.println("Got dateString: " + dateString);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Calendar calendar = Calendar.getInstance();
try {
calendar.setTime(sdf.parse(dateString));
Date day1 = calendar.getTime();
System.out.println(" day1 = " + sdf.format(day1));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day2 = calendar.getTime();
System.out.println(" day2 = " + sdf.format(day2));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day3 = calendar.getTime();
System.out.println(" day3 = " + sdf.format(day3));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day4 = calendar.getTime();
System.out.println(" day4 = " + sdf.format(day4));
//Skipping a few days ahead:
calendar.add(java.util.Calendar.DAY_OF_MONTH, 235);
Date day5 = calendar.getTime();
System.out.println(" day5 = " + sdf.format(day5));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day6 = calendar.getTime();
System.out.println(" day6 = " + sdf.format(day6));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day7 = calendar.getTime();
System.out.println(" day7 = " + sdf.format(day7));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day8 = calendar.getTime();
System.out.println(" day8 = " + sdf.format(day8));
} catch (Exception e) {
}
}
}
Die Ausgabe:
Got dateString: 2008-03-08
day1 = 2008-03-08
day2 = 2008-03-09
day3 = 2008-03-09
day4 = 2008-03-10
day5 = 2008-10-31
day6 = 2008-11-01
day7 = 2008-11-03
day8 = 2008-11-04
Got dateString: 2009-03-07
day1 = 2009-03-07
day2 = 2009-03-08
day3 = 2009-03-08
day4 = 2009-03-09
day5 = 2009-10-30
day6 = 2009-10-31
day7 = 2009-11-02
day8 = 2009-11-03
Got dateString: 2010-03-13
day1 = 2010-03-13
day2 = 2010-03-14
day3 = 2010-03-14
day4 = 2010-03-15
day5 = 2010-11-05
day6 = 2010-11-06
day7 = 2010-11-08
day8 = 2010-11-09
- Der trick, wenn Dinge wie diese passieren, ist überprüfen Sie Ihre Vermutungen: ich habe gerade ausgedruckt, den Kalender selbst w/o die SDF, und das problem war sofort offensichtlich, da der TZ der Kalender geändert.
- Danke. Durch "drucken der Kalender" ich nehme an, du meinst rufen Sie toString(). Ich habe ein paar weitere tests. Beim hinzufügen eines Kalender-Tages -, ein Kalender in my time zone (CST) wird 23 Stunden auf der "spring ahead" - Tag, und 25 Stunden auf die "fall-back" - Tag. Wenn das " = SimpleDateFormat ist auch CST, wird es drucken Sie den Tag richtig, aber wenn es die Weltzeit, 23 Stunden Hinzugefügt, nicht Recht bekommen Sie auf den nächsten Tag. Und im Herbst, die 25 Stunden Hinzugefügt überspringt eine UTC-Tag. Wenn der Kalender ist UTC, dann 24 Stunden wird immer Hinzugefügt. Der entscheidende Punkt ist, dass die Kalender-und die " = SimpleDateFormat sollte sich über die Zeit-zone.
- Sie werden nur Stimmen, die auf die Zeitzone, wenn Sie tatsächlich sagen, Sie verwenden die gleichen TZ, obwohl. (Willkommen in der Welt der Java-Zeit/Datum-handling.)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist verursacht durch die Sommerzeit und ist völlig korrekt.
Zeit (auf der Nordhalbkugel) ist eine erweiterte Stunden-Regel im März und zog wieder im November.
Sieht es eher wie ein day-light saving time Frage, welche Veränderungen im Mar und Nov. Können Sie versuchen Sie, die Zeit-element, um 00:00:00? Wenn Sie das tun,
und ändern Sie das format,
sehen Sie den Unterschied macht es in der Zeit Elemente.
Wenn Sie diese Art von Fragen haben Sie zum drucken der Kalender und Date-Instanzen, um herauszufinden, was Los ist.
Folgende:
Veränderungen der Zeit, die Ihr Kalender je nach JVM lokalen Zeit (und Zeitzone).
Calendar.getInstance();
erstellt einen Kalender in Ihre JVM lokale Zeit, wenn Siecalendar.setTime(sdf.parse("....."))
legt die Zeit in UTC (gegeben, wie Sie schuf die sdf!). Je nach DoY (und das Jahr!) dass Sie machen kann, passieren die Mitternacht und wenn Sie drucken Sie Ihre Datum mit JJJJ-MM-dd-format, die Sie sehen, der eine Tag Unterschied.Drucken Sie den vollen Kalender und Datum und du wirst herausfinden, was Los ist!!!
sdf.setTimeZone
ändert nicht die Zeit der Kalender, es ändert sich die Zeit der SDF, welche wird dann verwendet, um die Zeit der Kalender.Sommerzeit
Den Antwort von Tomasz Nurkiewicz ist richtig, das problem ist Sommerzeit (DST).
Siehe Wikipedia auf Central Time Zone
Joda-Time
Den Joda-Time Bibliothek macht diese Art von Arbeit sehr viel einfacher.
Einen DateTime in Joda-Time-kennt seine eigene Zeitzone. Verwenden UTC/GMT (keine Zeitverschiebung), übergeben Sie die eingebaute Konstante
DateTimeZone.UTC
.Drucken das Datum Teil eines Datums-Zeit, verwenden Sie eine DateTimeFormatter.
Dump in die Konsole...
Beim laufen...