2015-10-05 34 views
9

2つの日付の間の年を計算すると、最初の日付から2番目の日付が計算されます(これは私が作業しているものの単純化された例です)。LocalDatePeriodは、わずかに異なります。うるう年からの計算年数

例えば、

LocalDate date = LocalDate.of(1996, 2, 29); 
LocalDate plusYear = date.plusYears(1); 
System.out.println(Period.between(date, plusYear).getYears()); 

一方
LocalDate date = LocalDate.of(1996, 3, 29); 
LocalDate plusYear = date.plusYears(1); 
System.out.println(Period.between(date, plusYear).getYears()); 

明示的に第二ケースは1を返しながら、0よう年戻りPeriod最初の年を加えたにもかかわらず。

これでうまくいく方法はありますか?

+0

私はあなたのプロダクションコードが実際に1年を追加していないと考えています。実際に何を達成しようとしていますか?実際の入力と期待される出力を与えてください。 – dotvav

+3

@dotvav:与えられた例は私には明らかです...私はそれに間違っているとは思わない。 –

+0

もしあなたが実際にゼロの代わりに1年の差を求めたいならば、任意の月または日の部分を考慮しない年の数字を減算するだけです。 –

答えて

3

この質問は、哲学的性質を持ち、時間の測定や日付形式の規則などの問題はほとんどありません。

LocalDateは、ISO 8601の日付交換基準の実装です。 Java Docは、このクラスが時間を表すのではなく、標準の日付表記のみを提供していることを明示しています。

APIは、表記自体にのみ、簡単な操作を提供し、すべての計算は、、または、または指定した日付のをインクリメントすることによって行われます。

つまり、LocalDate.plusYears()を呼び出すと、1年以内の正確な時間ではなく、それぞれ365日という概念的年が追加されます。

は、LocalDateで表される日付に追加できる最小単位です。

の日付は時間的なものではありませんが、期間です。

00h 00m 00s(...)で始まり、23h 59m 59s(...)で終了します。

LocalDateは、しかし、単にのタプルとしてタイム計測と人間の時間単位のあいまいさの問題(時間、およびすべての異なる長さを持つことができます)とモデルの日付表記を回避します:時代の初めから計算

(years, months within a year, days within a month)

この解釈では、は、日付に影響を与える最小単位です。次の例として

LocalDate date = LocalDate.of(1996, 2, 29); 
LocalDate plusSecond = date.plus(1, ChronoUnit.SECONDS); 

戻り、示すこと

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds 

...(精度を駆動するために以下の単位)の秒数をLocalDateを使用して追加、あなたあなたの質問に記載されている制限を克服できませんでした。

実装を見ると、年を加算した後にLocalDate.plusYears()が見つかり、resolvePreviousValid()が呼び出されます。この方法は、うるう年をチェックし、次のようにフィールドを変更します。つまり

day = Math.min(day, IsoChronology.INSTANCE.isLeapYear((long)year)?29:28);

を、それが効果的に1日控除して、それを修正します。

Year.length()を使用して、指定した年の日数を返し、うるう年の場合はを返します。だから、あなたができる:

LocalDate date = LocalDate.of(1996, 2, 29); 
LocalDate plusYear = date.plus(365, ChronoUnit.DAYS); 
System.out.println(plusYear); 
Period between = Period.between(date, plusYear); 
System.out.println(between.getYears() + "y " + 
        between.getMonths() + "m " + 
        between.getDays() + "d"); 

戻り、その後

1997-02-28 
0y 11m 30d 

:あなたはまだ奇妙次に実行されます

LocalDate plusYear = date.plus(Year.of(date.getYear()).length(), ChronoUnit.DAYS); 

を(簡潔にするために一日数に置き換えYear.length()を呼び出します)

LocalDate date = LocalDate.of(1996, 3, 29); 
LocalDate plusYear = date.plus(365, ChronoUnit.DAYS); 
System.out.println(plusYear); 
Period between = Period.between(date, plusYear); 
System.out.println(between.getYears() + "y " + 
        between.getMonths() + "m " + 
        between.getDays() + "d"); 

戻り

1997-03-29 
1y 0m 0d 

し、最終的に:

LocalDate date = LocalDate.of(1996, 2, 29); 
LocalDate plusYear = date.plus(366, ChronoUnit.DAYS); 
System.out.println(plusYear); 
Period between = Period.between(date, plusYear); 
System.out.println(between.getYears() + "y " + 
        between.getMonths() + "m " + 
        between.getDays() + "d"); 

リターン:

1997-03-01 
1y 0m 1d 

代わり日の日付を移動するから期間を増加させたことに注意してください11月30日1年1日(2日増えました!)