Skip to content

How should the overflow option behave with leap days and months in PlainMonthDay.from() ? #1237

@justingrant

Description

@justingrant

PlainMonthDay.from() accepts an overflow: 'constrain' | 'reject' option. How should this option behave when the input is a leap day or a day in a leap month? In the ISO calendar this is easy because there's only one leap day and it's always at the end of the same month. So the ISO calendar can use a fixed reference year, which currently is 1972 which was the first leap year after UNIX epoch.

However, non-ISO calendars:

  • Can have leap months (e.g. Hebrew, Chinese) which are not present every year
  • Can have variable-length months, most commonly because month start and endpoints are determined by the position of the moon at a particular place and/or measured in a particular way (e.g. Islamic, Chinese)

This means that the ISO reference year cannot be a constant, and it makes it harder to know how overflow should behave.

My assumption is that the correct overflow behavior in any calendar is this:

  • 'constrain' - try to find a year where this month/day exists. If one can be found, use it for computation of referenceISOYear. If one cannot be found:
    • If month is smaller than any month in any known year, then use the first month in years.
    • If month is larger than any month in any known year, then use the last month in the longest known year
    • If day is smaller than any valid day, then use the first day of the month
    • If day is larger than any day of the month calculated above, then use the largest day of this month in any known year.
  • 'reject' - try to find a year where this month/day exists. If one can be found, use it for computation of referenceISOYear. If one cannot be found, throw a RangeError.

In my non-ISO calendar PR, I'm implementing the logic above by starting from the current date and working backwards one calendar year at a time for up to 100 years to try to find a year where the month/day exists. AFAICT, all built-in calendars have cycle lengths less than 100 years so if a match is going to happen, it should happen within a century. (I'm actually optimizing a little by checking for definitely-invalid values like day: 0 or month: 14 before doing the up-to-100-year loop on maybe-valid month/day pairs, but that optimization shouldn't affect the spec above.)

If you disagree with this approach, LMK soon!

EDIT: How should the calendar react to an invalid leap-month monthCode, e.g. '4L' for any calendar other than Chinese/Dangi. Should it constrain down to the last day of monthCode: '4' per the constrain algorithm in the OP? Or throw a RangeError because that month code is never valid for that calendar?

Metadata

Metadata

Assignees

No one assigned

    Labels

    non-prod-polyfillTHIS POLYFILL IS NOT FOR PRODUCTION USE!

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions