web-dev-qa-db-ja.com

Java.timeでは、月を追加した結果はどのように計算されますか?

JSR-310ではJava.time JDK 8のAPI、日付に月を追加した結果を計算するためのルールは何ですか。特に、1月31日のような日付に1か月を追加するとどうなりますか?

LocalDate initial = LocalDate.of(2012, 1, 31);  // 31st January 2012
LocalDate result = initial.plusMonths(1);
// what is the result?
22
JodaStephen

短い答え:

この例では、結果は2月の最終日2012-02-29になります。

説明:

「月を追加すると何日になるか」という質問は、解釈の余地があるかもしれません。これを回避するために、Java.time AP​​Iには 明確なルール があります。無効な日付でない限り、結果は入力と同じ月の日を持ちます。無効な日付の場合、結果はその月の最後の日になります。

したがって、1月31日と1か月を足したものは、2月31日になりますが、これは無効な日付であるため、結果は2月の最後の有効な日付になります。これは、うるう年かどうかに応じて2月28日または29日です。

// normal case
2011-01-15 plus 1 month = 2011-02-15  // 15 Jan -> 15 Feb

// special rule choosing the last valid day-of-month
2011-01-31 plus 1 month = 2011-02-28  // 31 Jan -> 28 Feb (2011 is normal year)
2012-01-31 plus 1 month = 2012-02-29  // 31 Jan -> 29 Feb (2012 is leap year)

// same rule applies for months other than February
2013-03-31 plus 1 month = 2013-04-30  // 31 Mar -> 30 Apr (only 30 days in April)

同じルールが、1か月を追加する場合でも、数か月を追加する場合でも適用され、常に結果の月に基づいています。すなわち。最初に月が追加され(必要に応じて年が調整され)、その後にのみ月の日が考慮されます。減算する場合にも同じルールが適用されます。

// multiple months works on the month of the result
2013-10-31 plus 4 months = 2014-02-28   // last day of February
2013-10-31 minus 4 months = 2013-06-30  // last day of June

日付に年を加算/減算する場合にも同じルールが適用されます。年が加算された後、その月の日付の有効性がチェックされます。

// years use the same rule
2012-02-29 plus 1 year = 2013-02-28  // 29th February invalid so adjusted to 28th

ビジネスロジックで月の追加に別のルールが必要な場合は、特別なロジックをパッケージ化するTemporalAdjusterまたはTemporalAmountを作成するのが最善の方法です。

25
JodaStephen