2016-01-22 22 views
5

Javaで現在の日付から一定の日数を引いた値を計算することに問題があります。今日からの過去の日付を計算するJavaが将来行われる予定です

は私が持っている:

Date pastDate = new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 25)); 

これは戻っている火2月16日9時04分18秒EST 2016それが実際に返す必要があるときに火12月28日午後04時06分11秒EST 2015(25日に過去)。

何非常に奇妙なのは25日の下で、任意の数のために完全に正常に動作していることである:24日のように

Date pastDate = new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 24)); 

過去に予測可能火12月29日午前16時06分11秒EST 2015を返します。

ご協力いただければ幸いです。

+2

[新しいデータタイムチュートリアル](http://docs.oracle.com/javase/tutorial/datetime/index.html)を参照することをお勧めします。 – user1803551

答えて

10

24日の場合、製品は可能な限り最大値intの値、Integer.MAX_VALUE、つまり2,147,483,647のままです。 24日の製品は2,073,600,000です。 25日の製品は2,160,000,000です。結果はオーバーフローし、負の数になり、将来の日付になります。

Integer.MAX_VALUEを超えるようなオーバーフローを避けるために、このような値の場合は、最初の値にはlongリテラルを使用してください(またはlongにキャストしてください)。 1000Lに追加Lに注意してください。なぜならdesired constructor for Date takes a long

(1000L * 60 * 60 * 24 * 25) 

これが正常に動作します。

日付演算は、Calendarを使用すると、明示的にaddの負の日数を使用して、よりきれいに処理されます。

また、Java 8以降では、Instant and its minus methodを使用して時刻を減算できます。

Instant.now().minus(24, ChronoUnit.DAYS); 
+0

ああ、どのような風変りなエラー。ありがとう、私は次回に心に留めておきます。今すぐ完璧に動作します:)。 – StackPWRequirmentsAreCrazy

+0

数秒または数ナノ秒に基づいて算術演算を行っている場合、うるう秒で問題が発生する可能性があります。うるう秒のために、毎日の秒数が同じではありません。 –

2

独自の日時計算をロールしないでください。日時制作は驚くほどトリッキーなビジネスです。あなたはすでに、共通のint -versus-longのエラーをミリ秒の計算で実行しました。まともな日時ライブラリを使用してください。幸いにもJavaには業界最高のライブラリが付属しています。

java.time

the correct Answer by rgettmanで述べたように、あなたが後でのJava 8とに組み込まれた新しいjava.timeフレームワークを使用する必要があります。最も古いバージョンのJavaにバンドルされていた古い日時クラスは非常に面倒です。

java.timeの基本... Instantは、タイムラインのUTCでの瞬間です。タイムゾーン(ZoneId)を適用してZonedDateTimeを取得します。

タイムゾーンは、日付の決定に非常に重要です。日付は、いつでも世界中で同じではないためです。新しい日は東の方が早く起きます。

Instant instant = Instant.now(); // In UTC. 
ZoneId zoneId = ZoneId.of("Asia/Kolkata"); 
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant , zoneId); 
ZonedDateTime zdtTwentyFiveDaysAgo = zdt.minusDays(25); 

現在の時刻ではなく、25日前のその日時の最初の瞬間が必要な場合があります。最初の瞬間は、夏時間(DST)やその他の異常のために常に00:00:00.0ではありません。したがって、java.timeは時刻を決定します。最初の瞬間を得るには、LocalDateを経由してからZonedDateTimeに戻る必要があります。

ZonedDateTime zdtTwentyFiveDaysAgoStart = zdtTwentyFiveDaysAgo.toLocalDate().atStartOfDay(zoneId); 
関連する問題