Date calculator with DST and month-end handling

Find the difference between two date-times, or add and subtract years, months, weeks, days, hours, minutes and seconds in a time zone. The page shows what a day is worth across a daylight saving change, and what happens at the end of a month. Nothing you type leaves your browser.

The tool

Skipped local time
Repeated local time

Difference between two date-times

Add or subtract

Direction

How to use

To find a difference

  1. Choose the Zone for the calendar. Both date-times are read as local times in this zone.
  2. Type Start and End as YYYY-MM-DD hh:mm:ss.
  3. Read three answers: the calendar difference in years, months, days and a time remainder; the exact elapsed time (an ISO 8601 duration of hours, minutes and seconds); and the number of calendar days between the two local dates.

To add or subtract

  1. Type the Start and choose Add or Subtract.
  2. Fill in any of years, months, weeks, days (these move the date on the calendar and keep the wall-clock time) and hours, minutes, seconds (these move the instant by that much elapsed time).
  3. If the answer falls in a clock gap or overlap, the settings for Skipped local time and Repeated local time decide, as in the time zone converter.
  4. The result shows the local time with its offset, the UTC instant and a note when the day was clamped to the end of a month or a clock change was involved.

Worked examples

Every result printed here is recomputed by an automated test from the same engine as the tool. The calendar part is checked against Python's datetime on thousands of random dates, and the zone arithmetic against JavaScript's Date.

One day is not 24 hours

America/New_York

Input: 2026-03-07 12:00:00 + 1 day

Output: 2026-03-08T12:00:00-04:00

America/New_York

Input: 2026-03-07 12:00:00 + 24 hours

Output: 2026-03-08T13:00:00-04:00

America/New_York

Input: 2026-10-31 12:00:00 + 1 day

Output: 2026-11-01T12:00:00-05:00

America/New_York

Input: 2026-10-31 12:00:00 + 24 hours

Output: 2026-11-01T11:00:00-05:00

New York skipped an hour on 8 March 2026 and repeats one on 1 November 2026. One calendar day lands on noon both times; 24 hours lands at 13:00 in March and 11:00 in November.

Australia/Sydney

Input: 2026-10-03 12:00:00 + 1 week

Output: 2026-10-10T12:00:00+11:00

Sydney's clocks go forward on 4 October 2026, so a week after noon on 3 October (+10:00) is noon on 10 October at +11:00.

The answer lands in a gap or an overlap

America/New_York, skipped time: Later

Input: 2026-03-07 02:30:00 + 1 day

Output: 2026-03-08T03:30:00-04:00

America/New_York, repeated time: Earlier

Input: 2026-10-31 01:30:00 + 1 day

Output: 2026-11-01T01:30:00-04:00

Month ends

UTC

Input: 2026-01-31 09:00:00 + 1 month

Output: 2026-02-28T09:00:00+00:00 (day clamped to month end)

UTC

Input: 2028-01-31 09:00:00 + 1 month

Output: 2028-02-29T09:00:00+00:00 (day clamped to month end)

UTC

Input: 2026-01-31 09:00:00 + 1 month + 1 day

Output: 2026-03-01T09:00:00+00:00 (day clamped to month end)

UTC

Input: 2026-03-31 09:00:00 - 1 month

Output: 2026-02-28T09:00:00+00:00 (day clamped to month end)

UTC

Input: 2028-02-29 09:00:00 + 1 year

Output: 2029-02-28T09:00:00+00:00 (day clamped to month end)

Differences

America/New_York

Input: 2026-03-07 12:00:00 to 2026-03-08 12:00:00

Result: calendar 1 d; elapsed PT23H; calendar days 1

America/New_York

Input: 2026-10-31 12:00:00 to 2026-11-01 12:00:00

Result: calendar 1 d; elapsed PT25H; calendar days 1

"Calendar 1 d" and "elapsed 23 hours" are both true for the same pair of times: the calendar difference counts days on the wall clock, the elapsed time counts real seconds.

UTC

Input: 2026-01-31 12:00:00 to 2026-02-28 12:00:00

Result: calendar 1 mo; elapsed PT672H; calendar days 28

UTC

Input: 2026-01-31 12:00:00 to 2026-03-01 12:00:00

Result: calendar 1 mo 1 d; elapsed PT696H; calendar days 29

31 January to 28 February is "1 month" because 31 January plus one month clamps to 28 February; the elapsed time is 28 days. The page shows the calendar days (28) alongside so you can see both.

UTC

Input: 2025-10-03 00:00:00 to 2026-10-03 00:00:00

Result: calendar 1 y; elapsed PT8760H; calendar days 365

UTC

Input: 2024-01-01 00:00:00 to 2025-01-01 00:00:00

Result: calendar 1 y; elapsed PT8784H; calendar days 366

UTC

Input: 2000-02-29 00:00:00 to 2026-10-01 00:00:00

Result: calendar 26 y 7 mo 2 d; elapsed PT233064H; calendar days 9711

The last line is a long span from a leap-day date to a fixed date, 00:00 UTC on 1 October 2026 (chosen so the numbers never go out of date): 26 years, 7 months and 2 days. The calendar-days figure (9711) counts the leap days in between, and the elapsed time (233,064 hours) is exactly 9711 days of 24 hours because UTC has no daylight saving.

What goes wrong

Adding 86400 seconds when you meant a day

A scheduler that adds 86400 seconds to "tomorrow at noon" will be an hour off twice a year in zones with daylight saving. The first four examples show it: the elapsed time between the two noons is 23 or 25 hours.

Treating a month as 30 days

The elapsed time between 31 January and 28 February (the "one month" in the examples) is 28 days; for 31 January to 1 March it is 29. A month is whatever the calendar says it is, and the answer depends on which month you start in.

Expecting add and subtract to undo each other

31 January + 1 month = 28 February, but 28 February - 1 month = 28 January. Clamping loses information, so the round trip does not always return to the start.

Counting days with a time of day still attached

"How many days between these two moments?" has at least three honest answers: calendar days between the two local dates, the exact elapsed time divided into 24-hour periods, and the calendar difference in years, months and days. The result panel shows the calendar difference, the exact elapsed time and the calendar days, because they can differ by one.

Forgetting that two zones have two calendars

The same instant can be on different dates in two zones. Differences here are computed in one zone; convert first if your two times come from different zones.

Limits & gotchas

  • The rules are this tool's choices, following the two-timeline model that Java's ZonedDateTime documents (date units on the local time-line, time units on the instant time-line). There is no single standard for adding months, so another library can give a different answer in some cases, for example around month ends or in a gap.
  • The calendar split of a difference is not unique. The tool uses the largest whole months (shown as years and months), then days, that can be added to the start without passing the end, with month-end clamping. A different convention (for instance counting backwards from the end) can give another split.
  • Zone data comes from your browser, so a very recent rule change may be missing, and dates far in the future use the rules your browser's copy of the database has for them.
  • Proleptic Gregorian calendar only. There are no Julian-calendar dates, no business-day or holiday calendars, and no week-number arithmetic.
  • Range. Results must fall within the range of a JavaScript Date (about the years -271821 to +275760), and the day-of-month in the inputs must exist.
  • Leap seconds are not part of the arithmetic: a day is always 86400 seconds of elapsed time apart from clock changes.

FAQ

Why does "1 day later" not always mean 24 hours later?

Because a calendar day in a zone with daylight saving can be 23 or 25 hours long. Adding one day keeps the wall-clock time (noon stays noon); adding 24 hours moves the instant by exactly 86400 seconds. Java's ZonedDateTime documents the same split: plusDays works on the local time-line and plusHours on the instant time-line. Across New York's change on 8 March 2026, noon plus one day is noon, and noon plus 24 hours is 13:00.

What is 31 January plus one month?

There is no 31 February, so the tool clamps to the last day of the month: 28 February 2026 (29 February in a leap year such as 2028). Adding a month and a day to 31 January gives 1 March, because the month is added first and the day after. Other tools may do it differently, so write down which rule you rely on when you compare results.

How does the difference between two dates get split into years, months and days?

The tool finds the largest number of whole months (shown as years and months), then days, that you can add to the start without passing the end, using the same month-end clamping as the add function, and shows the remainder in hours, minutes and seconds. It also shows the exact elapsed time and the number of calendar days between the two local dates. There is no single agreed answer for the months-and-days split, which is why the page shows all three.

Do both date-times use the same time zone?

Yes: the start and end of a difference are read as local times in the one zone you choose, and the elapsed time is the real time between them in that zone, so a daylight saving change between them is counted. To compare times in two different zones, convert one with the time zone converter first, or write both as UTC.

What happens when the answer falls in a daylight saving gap or overlap?

You choose: the "skipped local time" and "repeated local time" settings (later, earlier, or reject) apply to the result of an addition. The defaults are the same as JavaScript's Date: a skipped time moves forward by the length of the gap, and a repeated time uses the earlier instant.

Sources

  • Oracle: Java SE 21: java.time.ZonedDateTime Used for: For a local date-time that falls in a gap, the zoned date-time is shifted forward by the length of the gap, ending in the later offset; for an overlap the previous offset is retained if there is one, otherwise the earlier offset is used. plusDays works on the local time-line (adding days to the local date-time and converting back), whereas plusHours works on the instant time-line, so adding one hour is always a duration of one hour. Java is not installed on the machine used to build this site, so Java behaviour here is described from the documentation, not executed.
  • MDN Web Docs: Date Used for: The supported range (April 20, 271821 BC to September 13, 275760 AD, plus or minus 100,000,000 days); that Date ignores leap seconds; Number.MAX_SAFE_INTEGER is 9,007,199,254,740,991; the date-time string format (a simplification of ISO 8601, 24:00:00 allowed, expanded years of + or - followed by six digits, -000000 disallowed); and that setting a local time inside a DST transition follows the Temporal "compatible" disambiguation: if the local time corresponds to two instants the earlier one is chosen, and if it does not exist the result goes forward by the gap duration (with the New York 2024 example).
  • MDN Web Docs: Temporal.ZonedDateTime.from() Used for: The disambiguation option for a local time that is skipped or repeated: "compatible" (default), "earlier", "later" or "reject".
  • Python Software Foundation: datetime: Basic date and time types Used for: datetime.fold: "Used to disambiguate wall times during a repeated interval"; the values 0 and 1 mean the earlier and later of the two moments.
  • IANA: Theory and pragmatics of the tz code and data Used for: The database records the history and the predicted future of civil time scales; names have the form Area/Location (for example Asia/Calcutta was renamed Asia/Kolkata, with the old name kept as a link); the abbreviation list shows that one abbreviation can mean different things (IST appears for India, for Irish time and for Israel).
  • The Open Group: POSIX.1-2024 Base Definitions, 4.19 Seconds Since the Epoch Used for: Seconds since the Epoch "approximates" the seconds elapsed since the Epoch; the formula that relates a UTC date to it for years from 1970 and non-negative values; "If the year is <1970 or the value is negative, the relationship is undefined"; "each and every day shall be accounted for by exactly 86400 seconds" (so leap seconds are not counted); the relationship to actual UTC is unspecified.
  • Ecma International / TC39: ECMAScript Language Specification: Time Values and Time Range; Date.parse; time zone offset helper operations Used for: A time value is milliseconds since 1970-01-01T00:00:00Z with every day exactly 86,400,000 ms (leap seconds are ignored); the range is +-8.64e15 ms (+-100,000,000 days); for a local time that is skipped or repeated, the offset in use before the transition is applied; a skipped local time yields no instant in the time-zone-to-epoch operation.

Every document above was opened and read on 2026-10-03. Documentation changes; if a page here disagrees with the current docs, trust the docs and tell us.