2016-09-12 12 views
0

質問:これはjava.util.Calendarのバグだと思いますか?HOUR_OF_DAYを設定するとJava Calendarが破損する

ローカル(PDT)タイムゾーンのCalendarオブジェクトがインスタンス化され、ゼロ(エポック開始)日付が割り当てられます。この値は、カレンダーのミリ秒、秒、および分を0に設定した後、予期したとおりに維持されます。ただし、時刻がゼロに設定されると、時間はゼロ以外になります。 は、値-57600000ms = -16時間を取得します。これはタイムゾーンバグかもしれませんが、-16時間の値は実行時に現地の-7時間(PDT)オフセットに対応していません。夏時間がなければ、時間オフセットはPST(-8時間)であり、-16時間にも対応していません。

タイムゾーンのオフセットに影響する時間を設定すると、分を設定する必要があります。(https://en.wikipedia.org/wiki/Time_zone)複数の場所では、標準時間からの30分のずれを使用し、いくつかの "..."四分の一時間偏差。

コード:

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()); 

出力:

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 

私はjava.util.Calendarの中で他のバグの記述を見つけたが、私はこれが知られているとは思いません。

- お時間をいただきありがとうございます。

答えて

1

Javaは正常で、正常に動作しています。

java.util.Dateは、エポックの開始(1970年1月1日00:00:00 UTC)から内部的にミリ秒で表される瞬間です。

java.util.Calenderは、タイムゾーンに依存する形式で時間情報を操作するためのものです。通常、タイムゾーンは現在のロケールを通じて暗黙的に定義されます。 calendar.setTime(xxx)を呼び出すと、指定された瞬間がタイムゾーンに従ってカレンダーフィールド(年、月、日、時、分、...)に変換されます。

あなたの場合、エポックの開始点はDec 31, 1969, 16:00:00.000 PDTに分割されています。ミリ秒、秒、および分のフィールドをクリアしても、これらのフィールドはすでにゼロであるため、何の効果もありません。

時間フィールドをクリアすると、タイムスタンプは に変更されます。あなたのケースでは、エポックの開始点はDec 31, 1969, 00:00:00.000 PDTに分割されます。

次のコードは、カレンダーのタイムスタンプをUTCおよびPDTの日付文字列に変換するとともに、操作を示しています。

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

あなたは今java.timeクラスに取って代わら面倒な古いレガシー日時クラスを使用しています。

あなたは今日の最初の瞬間を得ようとしているようです。想定しないで、時間を00:00:00としてハードコードしてください。一部のタイムゾーンでは、夏時間(DST)などの異常のために、別の時刻に開始されることがあります。 java.timeが最初の瞬間を決定します。

現在の日付と時刻を取得します。これには時間帯が必要です。どの瞬間でも、日付と時刻は地球の周りのゾーンによって異なります。

ZoneId z = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = ZonedDateTime.now(z); 

時間を除いてタイムゾーンなしの日付のみを抽出します。

LocalDate ld = zdt.toLocalDate(); 

時間帯を指定しても、その日の最初の瞬間を尋ねます。

ZonedDateTime zdtStart = ld.atStartOfDay(z); 
関連する問題