2016-09-14 53 views
1

Scalaでjava.timeを使用すると、私は奇妙な動作を経験しました。私はこのような2つの日付間の月数を計算したいと思います:Java日付のバグ2日付間の月の計算

import java.time._ 

Period.between(LocalDate.parse("2015-03-31"), LocalDate.parse("2015-04-30")) 
// java.time.Period = P30D 
// I would expect java.time.Period = P1M 

Period.between(LocalDate.parse("2015-03-31"), LocalDate.parse("2015-05-01")) 
// java.time.Period = P1M1D 

これはバグですか、それとも間違っていますか?

import org.joda.time.DateTime 
import org.joda.time.Months 

Months.monthsBetween(new DateTime().withDate(2015, 3, 31), new DateTime().withDate(2015, 4, 30)) 
//org.joda.time.Months = P1M 

java.time.LocalDateそれに数ヶ月を追加正常に動作します:

java.time.LocalDate.parse("2015-03-31").plusMonths(1) 
// java.time.LocalDate = 2015-04-30 
+1

明らかに仕様が破られていますか? –

+0

@MarkoTopolnik:もしそうなら、私は分かりませんが、1ヶ月の日数が異なることが予想されます。 – cperriard

+0

仕様を破るとバグです。そうでなければ、それはあなたの(合理的な)期待を破っただけです。 –

答えて

5

これはバグではなく、期待どおりに動作しています(JDK-8152384およびJDK-8037392も「問題ではありません」)。 Joda TimeとJava Time APIは、これに関して異なる動作をします。スティーブンColebourne from the previous bug reportを引用:

OPは日が、元の月の長さではなく、月、年の差が適用されると、結果1に基づいて計算されているルールをしたいように見えます。 OPは間違っていません。それは、java.timeでの計算をどのように選択するかではありません。実際

Period.betweenから:

期間は、両方が同じ符号を有することを確実にするために調整し、次いで、完全ヶ月を除去する残りの日数を計算することによって計算されます。 [...]終了日が開始日よりも大きいか等しい場合、1ヶ月は完了したとみなされます。月の31日、4月の30日、無完全月の間

が経過しました。このように、2つの日付の間の日数を含む期間があります。これは30です。4月の完全な月が経過するには、終了日に1日を追加し、6月1日にする必要があります。

Jodaは、月の期間を計算する方法が異なります。 Months.monthsBetweenから:

このメソッドは、結果が終了日を過ぎるまで、開始日に月を追加して計算します。このように、「長い」月の終わりから「短い月」の終わりまでの期間は1ヶ月としてカウントされます。

Jodaは、2つの日付間の月数を計算するときに、月の可変数を明示的に考慮します。 Java Timeはそうではありません。

+0

リンクありがとうございました。期間(startDate、endDate)と期間(endDate、startDate)の結果が大きく異なる可能性があるという事実は直観的ではなく、正直言って少し怖いです。 –

1

私はPeriod.betweenが戻っていると信じて

org.joda.timeは、私はそれを期待通りに動作します最初の例ではP30Dです.2番目のパラメータは排他的です。これは、私はそれは少し予想外ですが、あなたのアカウントにjavadocを取る場合、それは正しい結果であることに同意https://docs.oracle.com/javase/8/docs/api/java/time/Period.html#between-java.time.LocalDate-java.time.LocalDate-

public static Period between(LocalDate startDateInclusive, LocalDate endDateExclusive)

+0

私はこれを知っています。しかし、なぜPeriod.between(LocalDate.parse( "2015-04-30")、LocalDate.parse( "2015-05-30"))がP1Mを返すのですか?それは1ヶ月離れているので、 – cperriard

+0

@cperriardです。あなたはなぜ同じ日であると予想されますか? –

+0

@ PeterLawrey 4月は30日しかないので、 'java.time.LocalDate.parse(" 2015-03-31 ")。plusMonths(1)'は2015-04-30を返します。 – cperriard

2

に応じています。 javadocから

開始日は含まれていますが、終了日は含まれていません。 期間は、完全な月を削除し、残りの日数を計算して、両方が同じ符号を持つように調整して計算されます()。月の数は、12ヶ月の年に基づいて年と月に分割されます。 終了日が開始日であるより大きいか等しい場合、月が考慮されます。たとえば、2010年1月15日から2011年3月18日までは1年2ヶ月3日です。

"完全な月"とは違います。 この場合、4月1日から5月1日(排他的)は完全な月とみなされますが、3月31日から4月30日までは排他的です。

+0

Javadocにリンクしてください。私もこれを見ようとしましたが、明らかに正しい場所を見ていませんでした。 –

関連する問題