2016-12-14 8 views
2

私は入力として2つの日付を取るAPIを呼び出しています。APIは、2つの日付の差が60分を超えているかどうかをチェックしてから例外をスローします。私の入力日付はstartDate = 11-06-2016T00:57: 01とendDate = 11-06-2016T01:56:01の2つの日付がjava.util.Dateオブジェクトに保存されます。 問題は、2つの日付の差が59分で60分未満ですが、APIが例外をスローします。これはDayLightSaving.Onであるため、11月6日に午前2時にDayLightSavingが終了しますPDT時間帯が終了すると)、時間は1時間後に再び移動し、その時間は再び午前1時になりますが、PST時間帯になります。これは11月6日に、PDTに1回、PSTゾーンに2回。 このAPIがNOV 7で呼び出されると、タイムゾーンはPSTになります。指定されたタイムゾーンなしで2つの日付が渡されると、PDTゾーンでstartDateが使用され、PSTゾーンで終了します.PDTとPST自体に違いがあるこれは59分に追加され、差異が発生し、例外がスローされます。 入力日付がPDTからPSTへの移行期間にある場合のこのケースの処理方法? PST時間帯に呼び出されたとき入力日付がPDTからPSTへの移行期間にある日付の処理方法は?

サンプルコード

SimpleDateFormat formatter1 = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss"); 
String start="11-06-2016 00:57:01"; 
String end ="11-06-2016 01:56:01"; 
Date startdate = formatter1.parse(start); 
Date enddate = formatter1.parse(end); 
System.out.println("startDate is :" + startdate); 
System.out.println("endDate is :" +enddate); 
long dateRange = enddate.getTime() - startdate.getTime(); 
//if the difference between the two dates is > than 60 min i.e 3600000 ms, then throw exception. 
System.out.println(dateRange); 
if (dateRange > (60 * 60 * 1000)){ 
    throw new Exception("Date time range cannot be greater than 60 minutes.(calculated using millisecond difference)"); 
} 

出力

[Date Range is = 7140000 
Exception in thread "main" java.lang.Exception: Date time range cannot be greater than 60 minutes.(calculated using millisecond difference). 
    at Datetest.main(Datetest.java:28)][1] 

上記スニペットは例外をスローします。

+0

ISOの日付形式を使用している場合、日付と時刻が 'T 'で区切られている場合は、正しい' yyyy-MM-dd'の順序を使用する必要があります。 – Andreas

+0

あなたが知っていたとおり、太平洋標準時の時は、01:56:01 _twice_ 11/6/2016でした。したがって、「このケースを処理する方法」を尋ねる前に、時刻01:56:01をどのように解釈するかを指定する必要があります。それだけではあいまいです。この時代はどこから来ていますか、それが曖昧さを解決できるようにPSTかPDTのどちらの情報をプログラムに伝えるのでしょうか? – ajb

答えて

1

SimpleDateFormatも基礎となるCalendarどちらも、夏時間と標準時間との重なり時間の時間のタイムゾーンなしの日時文字列を解析するときに何が起こるかを指定します。

あなたは、それが夏時間よりも標準よりも好ましいと思われる、後の時間を返すことに気付きました。しかし、その動作は定義されていないので、...

新しいjava.timeクラスは正確に何が起こるか、そしてオーバーラップのもう1つの時間を選択する方法を指定します。

新しいAPIでは、日時文字列にタイムゾーンが設定されていないため、まずLocalDateTimeを解析し、タイムゾーンを適用してZonedDateTimeを取得します。あり、ほとんどの場合、

atZone()のJavadocを参照してください

ZonedDateTime zdtEnd2 = zdtEnd.plusHours(1); 
// zdtEnd2 is now: 2016-11-06T01:56:01-08:00[America/Los_Angeles] 

行動が明確に定義される:

LocalDateTime ldtEnd = LocalDateTime.parse("2016-11-06T01:56:01"); 
ZonedDateTime zdtEnd = ldtEnd.atZone(ZoneId.of("America/Los_Angeles")); 
// zdtEnd is now: 2016-11-06T01:56:01-07:00[America/Los_Angeles] 

は、重複を表示するには、時間を追加してみてくださいすることができますローカル日時に対して有効なオフセットは1つだけです。 クロックが設定されているオーバーラップの場合、2つの有効なオフセットがあります。この方法では、通常「夏」に対応するより前のオフセットを使用します。

クロックが前方にジャンプするギャップの場合、有効なオフセットはありません。代わりに、現地日時はギャップの長さで後で調整されます。典型的な1時間の夏時間の変更の場合、ローカル日時は1時間後に通常「夏」に対応するオフセットに移動されます。後でこの方法の結果、オーバーラップ期間コールZonedDateTime.withLaterOffsetAtOverlap()をオフセットを得るために

。ギャップまたはオーバーラップがあるときに例外をスローするには、ZonedDateTime.ofStrict(LocalDateTime, ZoneOffset, ZoneId)を使用します。

あなたが見ることができるように、それは常にSimpleDateFormatの観察された行動の反対で重複し、中早い時間を返します。 の後での時間を重複させたい場合は、withLaterOffsetAtOverlap()に電話してください。

あなたが文書化され、デフォルトに依存したくない場合、あなたは常に明示的に指定できます。その時はではないので

ZoneId PT = ZoneId.of("America/Los_Angeles"); 

LocalDateTime ldtStart = LocalDateTime.parse("2016-11-06T00:57:01"); 
ZonedDateTime zdtStartEarly = ldtStart.atZone(PT).withEarlierOffsetAtOverlap(); 
ZonedDateTime zdtStartLater = ldtStart.atZone(PT).withLaterOffsetAtOverlap(); 
System.out.println(zdtStartEarly); // 2016-11-06T00:57:01-07:00[America/Los_Angeles] 
System.out.println(zdtStartLater); // 2016-11-06T00:57:01-07:00[America/Los_Angeles] 

LocalDateTime ldtEnd = LocalDateTime.parse("2016-11-06T01:56:01"); 
ZonedDateTime zdtEndEarly = ldtEnd.atZone(PT).withEarlierOffsetAtOverlap(); 
ZonedDateTime zdtEndLater = ldtEnd.atZone(PT).withLaterOffsetAtOverlap(); 
System.out.println(zdtEndEarly); // 2016-11-06T01:56:01-07:00[America/Los_Angeles] 
System.out.println(zdtEndLater); // 2016-11-06T01:56:01-08:00[America/Los_Angeles] 

あなたが見ることができるように、00:57時間のために、それは、違いはありませんオーバーラップ時間。

0

ここでできることは、タイムゾーンオフセットを使用して2つの日付の違いを得ることです。

private int getDSTdifferenceDateAdjustment(Date startDate, Date endDate, TimeZone timeZone) 
{ 
    if (startDate == null || endDate == null) return 0; 
    int baseOffset = timeZone.getOffset(startDate.getTime()); 
    int newOffSet = timeZone.getOffset(endDate.getTime()); 

    return (newOffSet - baseOffset); 
} 

以下のようなものは、あなたの方法でこのような何か

int dstDifference = getDSTdifferenceDateAdjustment(startdate, enddate, TimeZone.getDefault()); 
// The dstDifference will get in the negative, so we are adding to the dateRange variable 
dateRange += dstDifference; 

、このいずれかを試してみても、DSTは来年起動時にチェックしてもらいます。ほとんどの場合、これは、これらすべてのケースで動作します

関連する問題