2016-06-16 15 views
2

私はTimeUnitクラスの奇妙な動作に気がついたので、この最小限の例を作成して再現しました。TimeUnitクラスが壊れていますか?

long differenceInDays; 

Calendar c1 = Calendar.getInstance(); 
Calendar c2 = Calendar.getInstance(); 

c1.setTimeInMillis(1466062306000l); // Thu Jun 16 2016 09:31:46 GMT+0200 
c2.setTimeInMillis(1466028000000l); // Thu Jun 16 2016 00:00:00 GMT+0200 

differenceInDays = TimeUnit.DAYS.convert(c2.getTimeInMillis() - c1.getTimeInMillis(), TimeUnit.MILLISECONDS); 
System.out.println(differenceInDays); // obviously zero 

c2.add(Calendar.DATE, +1); 
differenceInDays = TimeUnit.DAYS.convert(c2.getTimeInMillis() - c1.getTimeInMillis(), TimeUnit.MILLISECONDS); 
System.out.println(differenceInDays); // why zero and not one? 

c2.add(Calendar.DATE, +1); 
differenceInDays = TimeUnit.DAYS.convert(c2.getTimeInMillis() - c1.getTimeInMillis(), TimeUnit.MILLISECONDS); 
System.out.println(differenceInDays); // suddenly a 1, but not a 2 like expected 

最初に差異が計算されるのは、日付間に1日が含まれないため、0であることは明らかです。

しかし、2日目は1日追加されるので、違いはまだ0のままですか?

出力:

私はこの問題は、日光私は同じ年以内に計算を行うため、関連する時間やうるう年を保存、でも月であるとは思いません。

Hereは、チェックするミリ秒単位の計算機です。

答えて

10

あなたは、簡単な数学で、ここで何が起こっているかをよりよく見ることができます。

c1 = 1466062306000 
c2 = 1466028000000 

d = 86400000    // one day 

c2 - c1 = -34306000   // negative, but less than one day in magnitude 
c2 - c1 + d = 52094000  // less than one day 
c2 - c1 + d + d = 138494000 // more than one day, less than two days 

次のようにこれを処理するための正しい方法は、あなたは、Java 8を使用していると仮定すると、次のとおりです。

// Decide what time zone you want to work in 
ZoneId tz = ZoneId.of("Europe/Berlin"); 

// If you wanted the local time zone of the system, 
// Use this instead: 
// ZoneId tz = ZoneId.systemDefault(); 

// Get instants from the timestamps 
Instant i1 = Instant.ofEpochMilli(1466062306000l); 
Instant i2 = Instant.ofEpochMilli(1466028000000l); 

// Get the calendar date in the specified time zone for each value 
LocalDate d1 = i1.atZone(tz).toLocalDate(); 
LocalDate d2 = i2.atZone(tz).toLocalDate(); 

// Get the difference in days 
long daysBetween = ChronoUnit.DAYS.between(d2, d1); 

入力がタイムスタンプではなくCalendarのオブジェクトであれば、Legacy Date-Time Codeガイダンスに記載されているようにCalendar.toInstant()を提案します。

Java 7以前を使用している場合は、Joda Timeライブラリと同様の機能があります。

これらのいずれかを使用したくない場合でも、古い(ハード)方法を実行してから、this exampleを参照してください。

関連する問題