-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
8u66, 9
-
generic
-
generic
FULL PRODUCT VERSION :
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux 4.3.3-1-default #1 SMP PREEMPT Wed Dec 16 08:03:35 UTC 2015 (db72752) x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Example:
OffsetDateTime ods = '2001-03-01';
OffsetDateTime due0 = ods.plusYears(14);
This yields the correct result of: '2015-03-01' as expected.
OffsetDateTime due1 = ods.plusYears(15);
This yields the incorrect result of: '2016-02-29'. I would expect this to be: '2016-03-01'.
However if the original date (ods) is a leap year then everything is correct.
i.e.
OffsetDateTime ods = '2000-03-01';
OffsetDateTime due0 = ods.plusYears(15);
This yields the correct result of: '2015-03-01' as expected.
OffsetDateTime due1 = ods.plusYears(16);
This yields the correct result of: '2016-03-01' as expected.
It seems to only affect dates which are 1st March.
Tracing into the java.time code a bit it seems the method LocalDate.resolvePreviousValid does not consider all cases. Specifically it deals with subsequently INVALID dates, e.g. starting on a 29th February in a Leap Year and adding years to a non leap year it correctly reduces max day to 28 February. But it does not do this in reverse, i.e. going from non-leap year to leap year. And it does not know in what context the "new date" was arrived at. Adding years should go to a "logical" end of month/ beginning of month. Not an absolute day of month.
REPRODUCIBILITY :
This bug can be reproduced always.
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux 4.3.3-1-default #1 SMP PREEMPT Wed Dec 16 08:03:35 UTC 2015 (db72752) x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Example:
OffsetDateTime ods = '2001-03-01';
OffsetDateTime due0 = ods.plusYears(14);
This yields the correct result of: '2015-03-01' as expected.
OffsetDateTime due1 = ods.plusYears(15);
This yields the incorrect result of: '2016-02-29'. I would expect this to be: '2016-03-01'.
However if the original date (ods) is a leap year then everything is correct.
i.e.
OffsetDateTime ods = '2000-03-01';
OffsetDateTime due0 = ods.plusYears(15);
This yields the correct result of: '2015-03-01' as expected.
OffsetDateTime due1 = ods.plusYears(16);
This yields the correct result of: '2016-03-01' as expected.
It seems to only affect dates which are 1st March.
Tracing into the java.time code a bit it seems the method LocalDate.resolvePreviousValid does not consider all cases. Specifically it deals with subsequently INVALID dates, e.g. starting on a 29th February in a Leap Year and adding years to a non leap year it correctly reduces max day to 28 February. But it does not do this in reverse, i.e. going from non-leap year to leap year. And it does not know in what context the "new date" was arrived at. Adding years should go to a "logical" end of month/ beginning of month. Not an absolute day of month.
REPRODUCIBILITY :
This bug can be reproduced always.