Time Utilities

Date Calculator

Calculate date differences, add/subtract days and count workdays.

→
Difference
7 days (1 weeks)

What is Date Calculator?

Date calculator performs date arithmetic, calculating differences between dates or adding/subtracting time periods.

Features

  • Date Difference: Days, weeks, months, years between dates
  • Add/Subtract: Add or subtract time from a date
  • Workday Calculation: Exclude weekends

Use Cases

  • Project planning
  • Age calculation
  • Deadline tracking

A date calculator answers two separate questions about the same pair of dates: how many days apart they are, and which date results from adding or subtracting a whole number of days. It parses plain YYYY-MM-DD values and also splits a range into weekday and weekend totals for schedules, leave requests and deadlines.

Subtraction for the gap, inclusive counting for weekdays

The two modes disagree by one day on identical input, on purpose. Date Diff converts both values to milliseconds, takes the absolute gap and floors the division by 86400000, so 2026-10-19 to 2026-10-25 gives 6 days: the start date is a boundary, not a member. Weekday mode instead steps through the calendar one setDate call at a time while current <= end, counting both endpoints and classifying each day by whether getDay() returns 0 or 6. That same week reports 5 weekdays plus 2 weekend days, 7 in total. Use the first number for elapsed spans such as age or days remaining; use the second wherever a day is billed, staffed or granted, because a Monday-to-Monday engagement really does occupy eight calendar days.

Years, months and weeks are 365/30/7 arithmetic

Once the day total exists, the breakdown divides by constants instead of walking real month lengths: floor(days / 365) years, then the remainder into / 30 months, then / 7 weeks, and finally days % 7 for the leftover days. That last term is taken from the full day total rather than from the unconsumed remainder, so the segments can overlap and sum past the actual count. From 2024-01-01 to 2025-01-01 the label reads 366 days (1 years 2 days): 366 over 365 leaves one year, and 366 modulo 7 leaves two days, even though the span is exactly one calendar year. Read years, months and weeks here as scale conversions, not calendar arithmetic, and reconcile against the plain day count.

UTC parsing versus local getters

A bare date string like 2026-10-22 is specified to parse as UTC midnight, but this tool formats output with getFullYear(), getMonth() and getDate() and derives weekday status from getDay(), all of which read the local calendar. At UTC+8 the round trip is invisible, because local midnight plus eight hours lands on the same date. West of UTC it is not: in America/New_York the same string resolves to the previous evening, so adding 0 days returns 2026-10-21, and 2026-10-19 is counted as a Sunday, shifting every weekday total by one day. Date Diff escapes this because both operands are parsed identically, leaving the millisecond gap intact. If your machine runs west of UTC, compare the returned date with the input before trusting a workday count.

Worked example

The same two dates in both counting modes

Input
Start 2026-10-19, End 2026-10-25
Output
Date Diff: 6 days (6 days)
Weekdays: Weekdays: 5, Weekends: 2, Total: 7 days

Both modes ran on identical inputs. Date Diff floors 518,400,000 ms / 86,400,000 and prints the total plus a breakdown, but years, months and weeks all floor to zero, so the parenthetical simply repeats the total. The weekday walk counts seven calendar days with both ends included. Labels are not pluralized, so the English output reads 6 days for any count.

Limits and pitfalls

  • Date difference takes the absolute value, so swapping start and end returns the same positive number; a negative offset such as "3 days earlier" cannot be expressed.
  • Year, month and week figures are fixed 365/30/7 conversions, so leap days accumulate and a 366-day leap year reports 1 years 2 days while the segments may sum past the day total.
  • Weekday classification looks only at whether getDay() returns 0 or 6, so a range spanning a public holiday or a weekend make-up shift still yields plain Monday-to-Friday arithmetic; adjust those days yourself.
  • Add and subtract move in whole local days via setDate: a fractional entry like 2.5 is truncated, and there is no hour, minute or time zone input at all.
  • Subtract mode rewrites the shared days field to a negative number, so switching back to Add keeps the minus sign; and because input is parsed as UTC midnight while output is read locally, users west of UTC see results one day early.

Related tools

When it goes wrong

I typed an old start year and the tab just froze — no result ever appeared.

CauseWeekday mode is a while loop with one setDate call per day, and neither date field carries min or max. 0001-01-01 to 9999-12-31 is 3,652,059 iterations on the main thread, and the computed result re-runs on every change to either field.

FixCut the range down to the years you actually need — three years is roughly 1,100 days — or read the total from Date Diff first and only switch to Weekdays when you really need the weekday/weekend split.

I meant “one month later”, added 31 days to 2026-03-31, and landed on 2026-05-01.

CausesetDate(date.getDate() + 31) is plain day arithmetic: 30 days after 31 March is already 30 April, so the 31st day falls in May. Nothing in the component clamps to a month end, because there is no month concept in the calculation.

FixEnter the real length of the month instead: 30 days gets 2026-04-30. If the paperwork says “one month” rather than “30 days”, express it with month arithmetic elsewhere rather than with a day count here.

I pasted 2026/10/22 and the date field went blank.

Causeinput type="date" stores only the RFC 3339 full-date form, so the browser rejects “2026/10/22” and “10/22/2026” before Vue sees them, handing the model an empty string. The catch around new Date() never fires either: new Date('') produces an Invalid Date instead of throwing, so no “Invalid date format” message can appear.

FixRetype it as 2026-10-22, or click the day in the native picker. There is no Calculate button — the result recomputes the moment both fields hold a valid value.

Start and end are the same day and the answer reads “0 days (0 days)”.

CauseA zero gap leaves years, months and weeks all at 0, so the fallback if (days > 0 || parts.length === 0) pushes “0 days” into the parenthetical, which then repeats the total instead of staying empty.

FixRead it as correct: identical dates. If you expected a gap, check that the other field was not emptied by the slash-format paste above — an empty operand shows the placeholder “Select dates” rather than any number.

The prefilled end date is only six days away, though the pair is supposed to be a week.

CauseOn load the second field is Date.now() + 7 × 24 × 60 × 60 × 1000, formatted with local getters. When a daylight-saving fall-back sits inside those seven days and you open the page between 00:00 and 01:00 local, that absolute week reads back as 23:30 on the sixth day.

FixType the end date instead of trusting the prefilled pair. The result is computed from the two strings, each parsed as UTC midnight, so the printed gap is not affected by the offset shift.

Four different date jobs, and the one that belongs somewhere else

What you have to settleHow this page settles itWhen you must leave
A move of 30 days, not “the same day next month”Base 2026-01-31 plus 30 days prints 2026-03-02: setDate advances whole days only, so February is walked straight through, and the form has no month field to clamp anything.When the clause says “one month”, use month arithmetic: dayjs('2026-01-31').add(1, 'month') and date-fns addMonths both return 2026-02-28. Days as the unit, stay here; months or years as the unit, take the library.
A gap measured in hoursBoth operands come from type="date" inputs, so the finest resolution available is one day. A 09:00 handover on one date and an 08:00 handover the next reads 1 days, never 23 hours.Convert to epochs first: the timestamp converter takes a datetime-local value down to the second and returns seconds and milliseconds. Subtract there, divide by 3600 if the SLA is written in hours.
Workdays that skip public holidays, or a Mon–Sat rotaOnly getDay() returning 0 or 6 is a weekend; every other day is billable. 2026-10-01 to 2026-10-07 comes out as 5 weekdays and 2 weekend days, because Thursday, Friday, Monday, Tuesday and Wednesday are all workdays here — a holiday schedule cannot be entered.Spreadsheet: NETWORKDAYS.INTL(start, end, '0000011', holidays) takes a weekend mask plus a holiday range. Script: numpy.busday_count(start, end, holidays=[...]). Both let Thursday the 1st drop out of the count; this page never will.
An age, or a “the end is before the start” warningThe gap is wrapped in Math.abs, so a reversed pair returns the same positive number without a word of warning, and there is no state to detect an end date that precedes the start. The output is also whole days only, with no hour total to sanity-check against.The age calculator refuses a reversed pair with an explicit error and builds years, months and days from the 365.25 / 30.44 constants, plus a total hour count. Ask “how old”, use that page; ask “how many days”, use this one.
A label for the date: ISO week, quarter, day of yearThe output is the day total and its 365/30/7 split, nothing more. No week number, no quarter, and no weekday name for either endpoint.The week number calculator returns 2026-W53 together with that week’s Monday and Sunday; the timestamp converter prints the full ISO 8601 string. Neither yields a day gap, so a release-window question often needs two pages open.
Three hundred dated pairs in one goOne pair per calculation. There is no list, range or CSV input, so a quarter of contract end dates means three hundred manual entries and three hundred copied strings.One line of Python does the column: (date(2026,3,2) - date(2026,1,31)).days returns 30. Keep this page for the single result you want to eyeball.

Frequently Asked Questions

Does the day difference include both endpoints?
Default is the subtraction difference (end − start): January 1 to January 2 is 1 day. For schedules that count both ends (project timelines, leave requests), add one day to the result yourself — the tool reports the plain difference.
How does adding business days work?
Business-day mode skips Saturdays and Sundays only; it has no holiday calendar, so subtract public holidays yourself when a range crosses them. It also counts days inside the range (both ends included), unlike the difference mode.
Why do long spans sometimes differ by one day?
Almost always a boundary convention: whether the start day, the end day, or both are counted. The tool displays which convention it applies; when reconciling with someone, align the convention before comparing numbers.

Content reviewed: