Try the Date Calculator

Why 31 January Plus One Month Has No Right Answer

Adding one month to 31 January has no correct answer, and "add one day" isn't "add 24 hours". The date arithmetic edge cases that break calendars and billing systems.

September 8, 2026 7 min read
Share: Facebook WhatsApp LinkedIn Email
Why 31 January Plus One Month Has No Right Answer

The Meeting That Moved Itself

You schedule a call for 3pm London time with a colleague in New York. Your calendar shows 10am for them. Correct — five hours behind.

Three weeks later the recurring meeting shows 9am for them. Nobody changed anything.

The UK moved its clocks and the US hadn't yet. For roughly two weeks in spring and one week in autumn, the London–New York offset is four hours instead of five, because the two regions change on different dates. Your recurring meeting quietly drifted for everyone in one of the two cities.

This is one of several ways date arithmetic produces results that look like bugs and aren't.

Offsets Aren't Fixed

The first thing to internalise: a timezone is not an offset. A timezone is a set of rules that determines what the offset is at a given moment.

Europe/London is a timezone. +00:00 and +01:00 are the offsets it takes at different times of year. Storing "London time" as a fixed +00:00 is wrong for roughly half the year.

Transition dates differ by region:

  • EU and UK: clocks change on the last Sunday in March and the last Sunday in October
  • US and Canada: second Sunday in March and first Sunday in November
  • Southern hemisphere: opposite season entirely — Australia and New Zealand change in October and April
  • Many countries: no daylight saving at all

The gaps between these dates create windows where the usual offset between two cities is different. London to New York is normally 5 hours; for about two weeks each spring it's 4. Sydney to London swings between 9, 10 and 11 hours across the year.

Any calculation that hard-codes an offset will be wrong during those windows.

The Two Broken Hours

Twice a year, local time does something that breaks naive arithmetic.

Spring forward — the hour that doesn't exist. When clocks jump from 01:00 to 02:00, the entire 01:00–01:59 range never occurs. A timestamp of 01:30 on that date is not a valid local time. Ask a date library to construct it and behaviour varies: some throw an exception, some shift forward an hour, some shift backward.

Autumn back — the hour that happens twice. When clocks fall from 02:00 to 01:00, the 01:00–01:59 range occurs twice with different offsets. A timestamp of 01:30 is ambiguous — there are two moments it could refer to. Libraries typically pick one by convention, and different libraries pick differently.

Consequences show up in unexpected places. A job scheduled at 01:30 daily either skips a day or runs twice a year. A shift worker's hours calculation shows a 23-hour or 25-hour day. An "add 24 hours" operation lands at a different wall-clock time than it started.

"Add one day" and "add 24 hours" are different operations. Most of the year they agree. On transition days they don't, and which one you want depends entirely on what you're modelling. A daily reminder should keep the same wall-clock time (add one day). A 24-hour expiry timer should be exactly 24 hours (add duration).

Month Arithmetic Has No Right Answer

Adding a month to 31 January produces a date that doesn't exist. Every library has to choose a behaviour, and the choices differ:

  • Clamp to the last valid day: 31 January + 1 month = 28 February (or 29 in a leap year)
  • Overflow into the next month: 31 January + 1 month = 3 March
  • Throw an error

Clamping is the most common, and it introduces a subtle asymmetry: the operation isn't reversible.

31 Jan + 1 month = 28 Feb
28 Feb − 1 month = 28 Jan   ← not 31 Jan

It's also not associative:

31 Jan + 1 month + 1 month = 28 Feb + 1 month = 28 Mar
31 Jan + 2 months           = 31 Mar

Adding two months one at a time gives a different answer than adding two months at once. This is not a bug in the library — there's no definition that avoids it. It's a consequence of months having different lengths.

The practical implications are real. A subscription started on 31 January, billed monthly with clamping, drifts to the 28th and stays there. Financial and legal systems usually specify explicit rules — "the last business day of each month", "the same day or the last day if that day doesn't exist" — precisely because the naive operation is underdetermined.

Leap Years and the Rule Most People Get Wrong

The Gregorian rule:

  • Divisible by 4 → leap year
  • Except divisible by 100 → not a leap year
  • Except divisible by 400 → leap year after all

So 1900 was not a leap year. 2000 was. 2100 will not be.

The 1900 exception caused a lasting artefact: early spreadsheet software treated 1900 as a leap year, and the bug was preserved for compatibility. Spreadsheet date serial numbers before 1 March 1900 are consequently off by one relative to the correct calendar. If you're importing historical date data from spreadsheets, this is worth checking.

Leap seconds are separate and less predictable. They're inserted irregularly to keep atomic time aligned with the Earth's rotation, announced only months in advance. Most application-level date libraries ignore them entirely; if your work involves precise scientific timing, they matter.

Doing the Arithmetic

The Date Calculator handles the common operations:

  1. Enter a start date.
  2. Either enter an end date to find the interval, or specify a duration to add or subtract.
  3. Read the result in days, or in years, months and days.

Two things to be deliberate about:

Inclusive versus exclusive counting. From 1 March to 8 March is 7 days if you count the difference, and 8 days if you count both endpoints. Contracts, notice periods and legal deadlines often specify one or the other explicitly. Check which convention applies before relying on a number.

Years-months-days breakdowns are order-dependent. Converting an interval into "2 years, 3 months, 12 days" requires deciding whether to subtract years first or days first, and different orderings give different breakdowns for the same interval. It's a presentation format, not a canonical value — the day count is the unambiguous number.

Rules for Storing and Handling Dates

A short set of practices that prevents most of these problems:

Store timestamps in UTC. Convert to local time only for display. This single rule eliminates a large class of bugs.

Store the IANA timezone name, not an offset. Europe/Berlin, not +01:00. The name lets you compute the correct offset for any moment; the offset alone doesn't.

Store recurring events as local time plus timezone. A weekly 9am meeting in Berlin should be stored as "09:00, Europe/Berlin, weekly", not as a UTC time. Otherwise it shifts by an hour when Germany changes clocks.

Distinguish dates from timestamps. A birthday is a date with no time and no timezone. Storing it as a UTC timestamp means it displays as the previous day for anyone west of Greenwich.

Keep the timezone database updated. Governments change daylight saving rules with limited notice. The IANA database is updated several times a year, and stale data produces wrong answers for affected regions.

Never write your own date arithmetic. Every edge case above is already handled correctly by mature libraries, and none of them are obvious in advance.

FAQ

Why does my recurring meeting shift by an hour? Because it was stored as a fixed UTC time rather than as a local time plus a timezone. When the region changes clocks, the UTC time no longer corresponds to the intended local time.

What does adding one month to 31 January give? Depends on the library. Most clamp to the last day of February. Some overflow into March. Check your library's documented behaviour rather than assuming.

Is 2100 a leap year? No. It's divisible by 100 but not by 400.

Why is "add one day" not the same as "add 24 hours"? On daylight saving transition days a local day is 23 or 25 hours long. Which operation you want depends on whether you're preserving wall-clock time or elapsed duration.

How should I store a date of birth? As a plain date with no time component and no timezone. Adding either introduces errors when the value crosses a timezone boundary.

What happens to a job scheduled at 01:30 during a DST transition? In spring it may not run, since that hour doesn't exist. In autumn it may run twice. Schedule anything sensitive outside the 01:00–03:00 window.

The Takeaway

Almost every date bug traces back to treating the calendar as arithmetic when it's really a set of political and astronomical conventions. Store UTC, keep the timezone name alongside it, and be explicit about whether you mean wall-clock time or elapsed duration — that covers most of it.

Calculate intervals and add or subtract dates free with the Date Calculator at sadiqbd.com — no sign-up, instant results.

Ask AI about this article
Share: Facebook WhatsApp LinkedIn Email

Date Calculator

Free, instant results — no sign-up required.

Open Date Calculator →
Similar Tools
RD Calculator Compound Interest Percentage Calculator RD Goal Calculator EMI Calculator Retirement Calculator SIP Calculator Tax Calculator
Day-Count Conventions: How Banks Calculate Days for Interest and Why Fiscal Years Differ
Calculators
Day-Count Conventions: How Banks Calculate Days for Interest and Why Fiscal Years Differ
Week Numbering: Why January 1st Can Be "Week 1," "Week 52," or Something Else Entirely
Calculators
Week Numbering: Why January 1st Can Be "Week 1," "Week 52," or Something Else Entirely
Business Day Calculations: Why "30 Business Days" Is Approximately 6 Weeks — and Why the Exact Count Depends on Which Jurisdiction You're In
Calculators
Business Day Calculations: Why "30 Business Days" Is Approximately 6 Weeks — and Why the Exact Count Depends on Which Jurisdiction You're In
Why Legal Deadlines Are Harder to Calculate Than They Appear — Service Dates, Day Counting Rules, and Limitation Periods
Calculators
Why Legal Deadlines Are Harder to Calculate Than They Appear — Service Dates, Day Counting Rules, and Limitation Periods