Open loxs opened 6 years ago
This seems to have something to do with leap years (the library incorrectly thinks that 2026 is leap).
If we don't cross the boundaries of 2026-02-28, we get correct results:
utop # let d = Date.precise_sub (Date.make 2026 2 28) (Date.make 2025 3 31);;
val d : Date.Period.t = <abstr>
utop # let added = Date.add (Date.make 2025 3 31) d;;
val added : Period.date_field Date.date = <abstr>
utop # Printer.Date.to_string added;;
- : string = "2026-02-28"
But if we try with 2026-02-29 (should not even allow us to do it), we get this:
utop # let d = Date.precise_sub (Date.make 2026 2 29) (Date.make 2025 3 31);;
val d : Date.Period.t = <abstr>
utop # let added = Date.add (Date.make 2025 3 31) d;;
val added : Period.date_field Date.date = <abstr>
utop # Printer.Date.to_string added;;
- : string = "2026-03-01"
So it seems that precise_sub
allows for wrong leap years while later add
correctly figures out that 2026 is not leap.
I was wrong, doesn't have anything to do with leap years:
let test_precise_sub start ending =
Date.precise_sub ending start |> Date.add start |> Printer.Date.to_string
For this case it only happens for dates between 2025-07-10 and 2025-07-30:
utop # test_precise_sub (Date.make 2025 3 31) (Date.make 2026 7 9);;
- : string = "2026-07-09"
utop # test_precise_sub (Date.make 2025 3 31) (Date.make 2026 7 10);;
- : string = "2026-07-11"
utop # test_precise_sub (Date.make 2025 3 31) (Date.make 2026 7 30);;
- : string = "2026-07-31"
utop # test_precise_sub (Date.make 2025 3 31) (Date.make 2026 7 31);;
- : string = "2026-07-31"
utop # test_precise_sub (Date.make 2018 5 31) (Date.make 2018 7 2);;
- : string = "2018-07-03"
Seems to happen when jumping from the last day of an odd numbered month into July but not for all days of July:
utop # test_precise_sub (Date.make 2018 3 31) (Date.make 2018 7 20);;
- : string = "2018-07-21"
utop # test_precise_sub (Date.make 2018 3 31) (Date.make 2018 7 6);;
- : string = "2018-07-07"
utop # test_precise_sub (Date.make 2018 3 31) (Date.make 2018 7 2);;
- : string = "2018-07-02"
utop # test_precise_sub (Date.make 2018 3 31) (Date.make 2018 7 20);;
- : string = "2018-07-21"
utop # test_precise_sub (Date.make 2018 3 31) (Date.make 2018 7 6);;
- : string = "2018-07-07"
utop # test_precise_sub (Date.make 2018 3 31) (Date.make 2018 7 2);;
- : string = "2018-07-02"
So far I haven't been able to reproduce it with anything other than July
The smallest reproducible seems to be:
utop # test_precise_sub (Date.make 2018 5 31) (Date.make 2018 7 2);;
- : string = "2018-07-03"
Originally reported here by Stephen Dolan
I expected that if I use CalendarLib.Calendar.Precise.precise_sub to compute the difference between two dates, then I could add this difference to the earlier and get the later.
However, if I attempt this on [2025-03-31 17:53:04; 2026-07-19 12:15:23], then the result of add is 2026-07-20 12:15:23, not 2026-07-19 12:15:23.