2016-09-12 2 views
0

beschädigt. Würdest du dies als einen Fehler in java.util.Calendar betrachten?Java-Kalender ist durch Einstellung von HOUR_OF_DAY

Ein Kalenderobjekt in der lokalen (PDT) Zeitzone wird instanziiert und mit dem Nulldatum (Epoch Start) versehen. Dieser Wert wird wie erwartet beibehalten, nachdem die Millisekunde, Sekunde und Minute des Kalenders auf Null gesetzt wurden. Sobald jedoch die Stunde des Tages auf Null gesetzt ist, wird die Zeit nicht Null. Es erwirbt den Wert -57600000ms = -16 Stunden. Dies kann ein Zeitzonenfehler sein, aber der Wert -16 Stunden entspricht nicht dem lokalen -7 Stunden (PDT) -Vergleich zum Zeitpunkt der Ausführung. Ohne Sommerzeit ist der Zeitversatz PST (-8 Stunden) und entspricht nicht -16 Stunden.

Wenn die Einstellung der Stunde die Zeitzonen-Offsets beeinflusst, sollten Sie auch die Minuteneinstellung erwarten, weil: (von https://en.wikipedia.org/wiki/Time_zone) Mehrere Stellen "halbstündige Abweichungen von der Standardzeit verwenden und einige" ... "verwenden Viertelstunden-Abweichungen. "

Der Code:

Date epochStart = new Date(0L); 
System.out.println("epochStart=" + epochStart.getTime()); 

Calendar calendar = Calendar.getInstance(); 
calendar.setTime(epochStart); 
System.out.println("epochStart in calendar=" + calendar.getTime().getTime()); 

calendar.set(Calendar.MILLISECOND, 0); 
System.out.println("ms cleared in calendar=" + calendar.getTime().getTime()); 

calendar.set(Calendar.SECOND, 0); 
System.out.println("second cleared in calendar=" + calendar.getTime().getTime()); 

calendar.set(Calendar.MINUTE, 0); 
System.out.println("minute cleared in calendar=" + calendar.getTime().getTime()); 

calendar.set(Calendar.HOUR_OF_DAY, 0); 
System.out.println("hourOfDay cleared in calendar=" + calendar.getTime().getTime()); 

Der Ausgang:

epochStart=0 
epochStart in calendar=0 
ms cleared in calendar=0 
second cleared in calendar=0 
minute cleared in calendar=0 
hourOfDay cleared in calendar=-57600000 

Ich habe Beschreibungen anderer Fehler in java.util.Calendar gefunden, aber ich glaube nicht, das bekannt ist.

- Danke für Ihre Zeit.

Antwort

1

Java ist in Ordnung und funktioniert wie erwartet.

Ein java.util.Date ist ein Zeitpunkt, intern dargestellt als Millisekunden seit dem Beginn der Epoche (1. Januar 1970 um 00:00:00 UTC).

java.util.Calender dient zum Bearbeiten von Zeitinformationen in einem zeitzonenabhängigen Format. Normalerweise ist die Zeitzone implizit durch das aktuelle Gebietsschema definiert. Der Aufruf calendar.setTime(xxx) nimmt den gelieferten Zeitpunkt und wandelt ihn in die Kalenderfelder (Jahr, Monat, Tag, Stunde, Minute, ...) entsprechend seiner Zeitzone um.

In Ihrem Fall wird der Beginn der Epoche in Dec 31, 1969, 16:00:00.000 PDT aufgeteilt. Das Löschen der Millisekunden-, Sekunden- und Minutenfelder hat keine Auswirkung, da diese Felder bereits Null sind.

Durch das Löschen des Stundenfelds wird jedoch der Zeitstempel auf geändert. In Ihrem Fall wird der Beginn der Epoche in Dec 31, 1969, 00:00:00.000 PDT aufgeteilt.

Der folgende Code zeigt Ihre Änderungen zusammen mit dem Konvertieren der Zeitstempel des Kalenders in UTC- und PDT-Datumszeichenfolgen.

import java.text.SimpleDateFormat; 
import java.util.*; 

public class CalendarTest { 

    public static void main(String[] args) { 
     TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles"); 
     SimpleDateFormat udf = new SimpleDateFormat("'UTC: 'yyyy-MM-dd HH:mm:ss.SSS Z"); 
     udf.setTimeZone(TimeZone.getTimeZone("UTC")); 
     SimpleDateFormat df = new SimpleDateFormat("'PDT: 'yyyy-MM-dd HH:mm:ss.SSS Z"); 
     df.setTimeZone(timeZone); 

     Date epochStart = new Date(0L); 
     System.out.println("epochStart=" + epochStart.getTime()); 
     System.out.println(udf.format(epochStart)); 
     System.out.println(df.format(epochStart)); 
     System.out.println(); 

     Calendar calendar = Calendar.getInstance(timeZone); 
     calendar.setTime(epochStart); 
     System.out.println("epochStart in calendar=" + calendar.getTime().getTime()); 
     System.out.println(udf.format(calendar.getTime())); 
     System.out.println(df.format(calendar.getTime())); 
     System.out.println(); 

     calendar.set(Calendar.MILLISECOND, 0); 
     System.out.println("ms cleared in calendar=" + calendar.getTime().getTime()); 
     System.out.println(udf.format(calendar.getTime())); 
     System.out.println(df.format(calendar.getTime())); 
     System.out.println(); 

     calendar.set(Calendar.SECOND, 0); 
     System.out.println("second cleared in calendar=" + calendar.getTime().getTime()); 
     System.out.println(udf.format(calendar.getTime())); 
     System.out.println(df.format(calendar.getTime())); 
     System.out.println(); 

     calendar.set(Calendar.MINUTE, 0); 
     System.out.println("minute cleared in calendar=" + calendar.getTime().getTime()); 
     System.out.println(udf.format(calendar.getTime())); 
     System.out.println(df.format(calendar.getTime())); 
     System.out.println(); 

     calendar.set(Calendar.HOUR_OF_DAY, 0); 
     System.out.println("hourOfDay cleared in calendar=" + calendar.getTime().getTime()); 
     System.out.println(udf.format(calendar.getTime())); 
     System.out.println(df.format(calendar.getTime())); 
     System.out.println(); 
    } 
} 
0

tl; dr

LocalDate.now(ZoneId.of("America/Montreal")) 
     .atStartOfDay(ZoneId.of("America/Montreal")) 

java.time

Sie mühsam Datum Zeitklassen alten Legacy verwenden nun durch die java.time Klassen verdrängte.

Scheint, dass Sie versuchen, den ersten Moment von heute zu bekommen. Nimm nicht an und schreibe die Zeit als 00:00:00 fest. In einigen Zeitzonen kann der Tag aufgrund von Anomalien wie Sommerzeit (DST) zu einem anderen Zeitpunkt beginnen. Lassen Sie java.time den ersten Moment bestimmen.

Ruft das aktuelle Datum und die aktuelle Uhrzeit ab. Dies erfordert eine Zeitzone. Für jeden Moment variieren sowohl das Datum als auch die Tageszeit von Zone um den Globus.

Nur das Datum extrahieren, ohne Uhrzeit und ohne Zeitzone.

LocalDate ld = zdt.toLocalDate(); 

zum ersten Moment des Tages fragen, agsin sogar eine Zeitzone angeben.

ZonedDateTime zdtStart = ld.atStartOfDay(z); 
Verwandte Themen