Skip to content

RegularYearMonthDayCalculator.AddMonths does not check for overflows. #1227

@chtoucas

Description

@chtoucas

Hello, I think that the method LocalDate.PlusMonths() can produce dates that are out of range. For instance,

new LocalDate(9999, 12, 31).PlusMonths(1)

does not overflow.

Also, I find it a bit disturbing that PlusYears, PlusMonths and PlusDays exhibit different behaviors:

  • PlusYears() throws an exception of type ArgumentOutOfRangeException
  • PlusMonths() throws an exception of type OverflowException or produces an invalid date
  • PlusDays() overflow (by C#) or throws an exception of type OverflowException

In details (I hope you don't mind if I write it in F#):

// Adding `Int32.MaxValue`.
let date1 = new LocalDate(2018, 11, 30)
// `YearsPeriodField.Add` throws an exception of type `ArgumentOutOfRangeException`.
date1.PlusYears(Int32.MaxValue) |> ignore
// `RegularYearMonthDayCalculator.AddMonths` throws an exception of type `OverflowException`.
date1.PlusMonths(Int32.MaxValue) |> ignore
// `FixedLengthDatePeriodField.Add` throws an exception of type `OverflowException`,
// but it is so because the following unchecked addition fails :
//   `int daysToAdd = value * unitDays`
date1.PlusDays(Int32.MaxValue) |> ignore

// Adding 1 (day, month or year) to 9999-12-31.
let date2 = new LocalDate(9999, 12, 31)
// `YearsPeriodField.Add` throws an exception to type `ArgumentOutOfRangeException`.
date2.PlusYears(1) |> ignore
// No exception raised, the result is simply *invalid*.
// `RegularYearMonthDayCalculator.AddMonths` does not check for overflows.
printfn "%O" <| date2.PlusMonths(1)
// `FixedLengthDatePeriodField.Add` throws an exception of type `OverflowException`,
// verification done by NodaTime in the case: `daysToAdd < 300 && daysToAdd > -300`.
date2.PlusDays(1) |> ignore

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions