proposal: import/path: proposal title #73511
Labels
LibraryProposal
Issues describing a requested change to the Go standard library or x/ libraries, but not to a tool
Proposal
Milestone
Proposal Details
Summary
Go’s existing
time.Time.AddDate
method preserves RFC 3339-style normalization (rolling over invalid dates to the next valid date), which can produce unintuitive results when adding or subtracting months on end-of-month dates (e.g.,time.Date(2025, 3, 31, 0,0,0,0, time.UTC).AddDate(0, -1, 0)
yields March 2nd, not February 28th).#31145
#66632
By contrast, legal definitions—such as the UK’s Interpretation Act 1978 and analogous Australian statutes—define a calendar month addition to yield the last day of the shorter month when no corresponding day exists (i.e., Feb 28th in non-leap years).
Legislation.gov.uk
AustLII
legalclarity.org
To align Go’s standard library with this intuitive, legally grounded behavior, and to prevent latent off-by-days bugs, I would like to propose adding a new method to the time package:
Background and Motivation
Unintuitive Behavior of
AddDate
The current
time.Time.AddDate
method “normalizes its result in the same way that Date does,” meaning adding months moves by the number of days difference, not by “calendar months”Google Groups.
In practice, subtracting one month from March 31, 2025 yields March 2, 2025—because February has only 28 days, so Go subtracts 31 − 28 = 3 days from March 31, landing on March 2
time AddDate(0, -1, 0) does not work for March. #31145.
Such corner-case behavior can silently introduce bugs that go unnoticed until end-of-month dates occur, especially in financial, scheduling, and legal applications.
An example that caused this to come to my attention was when trying to get the integer value of the month one calendar month before time.Now(), I got 3 as a result when the day was march 31st (expecting 2 as a result, meaning february). This then offset some further calculations that relied on this month value.
Legal and Conventional Definitions
UK’s Interpretation Act 1978 defines a “month” to mean a calendar month, implying that adding one month to January 31 should yield February 28 (or 29), the last day of February
Legislation.gov.uk.
Australian legislation (e.g., Northern Territory’s Interpretation Act 1978) explicitly defines a “calendar month” as ending on the last day of the next month when no corresponding day exists, matching the intuitive legal standard
AustLII.
"Months with varying lengths require careful consideration. For example, a “calendar month” starting January 31 would end on February 28 (or February 29 in a leap year). This prevents disputes over deadlines and aligns with the common understanding of the term."
legalclarity.org.
Aligning Go’s API with these well-understood conventions will make date arithmetic more intuitive and reduce defects.
Proposal
Examples
Compatibility and Scope
This addition is backwards-compatible: existing
AddDate
method remains unchanged.It applies to API changes in the standard library, which are in scope for the proposal process.
It does not affect Go 1 compatibility guarantees, as it merely adds a method.
The text was updated successfully, but these errors were encountered: