# Date Difference Calculator

> Work out how far apart two dates are — in days, weeks, whole months and years — and how many of those days are actually worked once weekends and public holidays come out. The span is broken down period by period and the table downloads as a spreadsheet.

Use it: https://tessalor.com/en/time/date-difference

This tool runs entirely in the browser. Nothing entered into it is uploaded.

## Formula

```
Every date becomes a day number: whole days counted from 1970-01-01
in the proleptic Gregorian calendar. No hour, no offset, no clock.

  n = daysFromCivil(year, month, day)

The span is one half-open interval, [start, end):

  days = n(end) - n(start),  plus 1 if the end date is counted

Weekday of a day number, 0 = Sunday:

  w = ((n mod 7) + 4 + 7) mod 7        1970-01-01 was a Thursday

Business days over a span of N days beginning on weekday w0, without
walking the range:

  whole   = floor(N / 7)
  left    = N - 7 x whole
  working = whole x (7 - weekendDays)
          + how many of w0, w0+1, ..., w0+left-1 (mod 7) are worked
          - listed holidays inside the span that fall on a worked day

Calendar difference, where addMonths clamps to the end of the target
month (31 January + 1 month = 28 February):

  m     = the largest k with addMonths(start, k) <= end
  days  = n(end) - n(addMonths(start, m))
  years = floor(m / 12),  months = m mod 12
```

## Assumptions

- Dates are treated as days on a calendar, never as instants. There is no time of day anywhere in the arithmetic, so no timezone applies and the answer is the same in Auckland as it is in Anchorage.
- Because there is no clock, a daylight-saving change cannot affect the count. A span across the March transition in Europe/London is 23 hours short of a whole number of 24-hour days, and dividing elapsed milliseconds by 86,400,000 would report one day fewer than the calendar shows.
- By default the end date is the finishing line rather than a counted day, so 1 June to 30 June is 29. Turning on "count the end date as a day" makes it 30, and every figure on the page moves together.
- The order of the two dates does not matter. The tool reports the distance between them and never a negative number.
- Whole months are counted by clamped addition, so 31 January to 28 February is one whole month and 31 January to 1 March is one month and one day. Month arithmetic defined this way is not reversible — a month forward and then a month back from 31 January lands on 28 January.
- A holiday falling on a weekend is not subtracted, because it was not a day that would have been worked. That is exactly why the United Kingdom observes Boxing Day on a Monday when 26 December is a Saturday, and why the substitute date is what the default list carries.
- Every line in the holiday box that has no date on it is ignored rather than refused, because throwing an error would blank the page while somebody is halfway through pasting a list. The holidays-skipped figure is the check on that, since it counts the lines that actually applied.
- The calendar is proleptic Gregorian throughout, including for dates before it was adopted. Britain switched in September 1752 and dropped eleven days doing it, so a span crossing that month is a day count and not what a contemporary diary would have said.

## Inputs

| Name | Label | Type | Default | Range |
| --- | --- | --- | --- | --- |
| `start` | From | date | 2026-01-01 |  |
| `end` | To | date | 2026-12-25 |  |
| `includeEnd` | Count the end date as a day | toggle | false |  |
| `weekend` | Weekend days | select | sat-sun |  |
| `holidays` | Public holidays to skip | textarea | 2026-01-01 New Year's Day
2026-04-03 Good Friday
2026-04-06 Easter Monday
2026-05-04 Early May bank holiday
2026-05-25 Spring bank holiday
2026-08-31 Summer bank holiday
2026-12-25 Christmas Day
2026-12-28 Boxing Day (substitute) |  |

## Outputs

- `totalDays` — Days between (integer), primary
- `businessDays` — Business days (integer)
- `nonWorkingDays` — Weekend days and holidays (integer)
- `weeks` — Weeks (number)
- `wholeMonths` — Whole months (integer)
- `calendarSpan` — In years, months and days (text)
- `holidaysApplied` — Holidays skipped (integer)

## Questions

### Does it count the first day, the last day, or both?

By default it counts neither end as a whole day: it measures the gap, so 1 June to 30 June is 29. That is what you want for a deadline, a notice period or interest. Turn on "count the end date as a day" for anything billed by the day — a hotel stay, a car hire, annual leave — and the same span reads 30.

### Are my dates sent anywhere?

No. The arithmetic runs in this browser tab and there is no server to send anything to. The holiday list, which is the only part that could identify a country or an employer, never leaves the page either.

### Does daylight saving time change the answer?

No, and that is deliberate. The tool works in whole calendar days rather than in hours, so the 23-hour day in spring and the 25-hour day in autumn never enter the arithmetic. A tool that subtracts two timestamps and divides by 24 hours gets those two weeks of the year wrong by a day.

### Why is 31 January to 28 February a whole month?

Because adding one month to 31 January lands on 28 February — there is no 31 February, so the date clamps to the end of the month. Defining the gap as the inverse of that addition is what keeps the two consistent. The alternative, subtracting the day numbers and borrowing, reports 28 days and then disagrees with its own month arithmetic.

### Which public holidays are in the box to start with?

The eight England and Wales bank holidays for 2026, as published by GOV.UK. Replace them with your own list — one date per line as YYYY-MM-DD — or write "none" to count every weekday. Scotland and Northern Ireland have different lists, which is why this is an editable box rather than a fixed assumption.

### Why does the breakdown switch from months to years?

To keep the table readable. One row per month is right for a project or a notice period, but two dates three centuries apart would be 3,600 rows, so the rows widen to years, then decades, then centuries as the span grows. Each row still counts only the part of its period that falls inside the range, so the column always sums to the headline figure.

## Sources

- [RFC 3339: Date and Time on the Internet — Timestamps](https://www.rfc-editor.org/info/rfc3339/) — IETF. Retrieved 2026-07-30.
- [ECMAScript Language Specification — Time Values and Time Range](https://tc39.es/ecma262/) — Ecma International, applies to ECMAScript 2027 draft, section 21.4.1.1. Retrieved 2026-07-30.
- [UK bank holidays](https://www.gov.uk/bank-holidays) — GOV.UK, applies to 2026. Retrieved 2026-07-30.
- [Time Zone Database](https://www.iana.org/time-zones) — IANA. Retrieved 2026-07-30.

## Variants

- [How many working days are there in 2026?](https://tessalor.com/en/time/date-difference/working-days-in-2026)
- [Do you count both the first and the last day?](https://tessalor.com/en/time/date-difference/counting-both-end-dates)

---

Estimate, not advice. See https://tessalor.com/en/disclaimer.
Machine-readable catalogue: https://tessalor.com/api/tools.json
