{
  "id": "date",
  "version": "90118d1fa1da",
  "status": "published",
  "name": "Date Calculator",
  "question": "What date is it before or after a date?",
  "summary": "Adds or subtracts years, months, weeks, and days to a date, or counts the time between two dates in years, months, days, and working days.",
  "category": "days",
  "subcategory": "dates",
  "url": "https://www.acalculator.org/days/date-calculator",
  "markdown": "https://www.acalculator.org/days/date-calculator.md",
  "kind": "function",
  "method": "Add or subtract: move the start date by 12 × years + months calendar months, then by 7 × weeks + days days. Between: count the days from the start date up to the end date (the end date too when asked), without weekends and holidays for working days.",
  "assumptions": [
    "Years and months move first, then weeks and days. A day past the end of a shorter month moves to its last day: January 31 plus one month is February 28, or February 29 in a leap year.",
    "Between two dates, the start date is counted and the end date is counted only with “Count the end date”. When the end date is first, the count is negative.",
    "Dates are calendar days on the Gregorian calendar with no time of day, so daylight saving changes cannot add or lose a day. The dates you enter run from 1600 to 2400; a result of adding or subtracting can fall outside that range and still shows.",
    "Public holidays are the days off as observed. Holiday data covers the US from 1986, the UK (England and Wales) from 2019 to 2028, Canada (federal) from 2021, India (central government) from 2023 to 2027, and China from 2015 to 2035."
  ],
  "inputs": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
      "mode": {
        "title": "What do you want to do?",
        "description": "Add or subtract time from a date, or count the time between two dates.",
        "type": "string",
        "enum": [
          "add",
          "between"
        ]
      },
      "start": {
        "title": "Start date",
        "description": "The date to start from. Today, unless you change it.",
        "type": "string",
        "format": "date"
      },
      "op": {
        "title": "Add or subtract?",
        "description": "Whether to add the time to the start date or subtract it.",
        "type": "string",
        "enum": [
          "add",
          "subtract"
        ]
      },
      "years": {
        "title": "Years",
        "description": "The number of years to add or subtract.",
        "type": "integer",
        "minimum": 0,
        "maximum": 1000
      },
      "months": {
        "title": "Months",
        "description": "The number of months to add or subtract.",
        "type": "integer",
        "minimum": 0,
        "maximum": 1200
      },
      "weeks": {
        "title": "Weeks",
        "description": "The number of weeks to add or subtract.",
        "type": "integer",
        "minimum": 0,
        "maximum": 5200
      },
      "days": {
        "title": "Days",
        "description": "The number of days to add or subtract.",
        "type": "integer",
        "minimum": 0,
        "maximum": 36500
      },
      "end": {
        "title": "End date",
        "description": "The date to count to.",
        "type": "string",
        "format": "date"
      },
      "includeEnd": {
        "title": "Count the end date",
        "description": "Count the end date as one more day.",
        "type": "boolean"
      },
      "useWorkingDays": {
        "title": "Count working days only",
        "description": "Count only working days instead of every calendar day.",
        "type": "boolean"
      },
      "excludeSaturday": {
        "title": "Skip Saturdays",
        "description": "Leave Saturdays out of the count.",
        "type": "boolean"
      },
      "excludeSunday": {
        "title": "Skip Sundays",
        "description": "Leave Sundays out of the count.",
        "type": "boolean"
      },
      "excludeHolidays": {
        "title": "Skip public holidays",
        "description": "Leave the chosen country's public holidays out of the count.",
        "type": "boolean"
      },
      "country": {
        "title": "Country",
        "description": "The country whose public holidays are skipped.",
        "type": "string",
        "enum": [
          "us",
          "uk",
          "ca",
          "in",
          "cn"
        ]
      }
    }
  },
  "outputs": {
    "workDays": {
      "label": "Working days",
      "description": "Days from the start date to the end date without the skipped weekend days and public holidays. Negative when the end date is first.",
      "format": "integer"
    },
    "span": {
      "label": "Time between",
      "description": "The days counted, as whole years, months, and days from the earlier date. It has no sign: see Days for the direction.",
      "format": "duration"
    },
    "date": {
      "label": "End date",
      "description": "The start date plus or minus the years, months, weeks, and days; when counting between two dates, the end date.",
      "format": "date-long"
    },
    "totalDays": {
      "label": "Days",
      "description": "Calendar days from the start date to the end date (counted as set in count mode). Negative when the end date is first.",
      "format": "integer"
    },
    "weeks": {
      "label": "In weeks",
      "description": "The calendar days as whole weeks and days, with no sign.",
      "format": "duration"
    },
    "note": {
      "label": "Note",
      "description": "A note when the end date is before the start date.",
      "format": "text"
    }
  },
  "defaultAnswer": {
    "inputs": {
      "mode": "add",
      "start": "2026-09-29",
      "op": "add",
      "days": 90,
      "end": "2026-10-29",
      "includeEnd": false,
      "useWorkingDays": false,
      "excludeSaturday": true,
      "excludeSunday": true,
      "excludeHolidays": false,
      "country": "us"
    },
    "outputs": {
      "date": "2026-12-28",
      "totalDays": 90
    },
    "text": "From September 29, 2026 to Monday, December 28, 2026: 90 days."
  },
  "examples": [
    {
      "given": {
        "mode": "add",
        "start": "2026-09-27",
        "op": "add",
        "days": 90
      },
      "expect": {
        "date": "2026-12-26",
        "totalDays": 90
      },
      "source": "hand calculation in content.mdx; Python: date(2026,9,27) + timedelta(90) = 2026-12-26"
    },
    {
      "given": {
        "mode": "add",
        "start": "2026-09-27",
        "op": "add",
        "years": 1,
        "months": 2,
        "weeks": 3,
        "days": 4
      },
      "expect": {
        "date": "2027-12-22",
        "totalDays": 451
      },
      "source": "hand calculation in content.mdx: 14 months to 2027-11-27, then 25 days to 2027-12-22"
    },
    {
      "given": {
        "mode": "add",
        "start": "2024-01-31",
        "op": "add",
        "months": 1
      },
      "expect": {
        "date": "2024-02-29",
        "totalDays": 29
      },
      "source": "hand calculation in content.mdx: February 2024 has 29 days, so the 31st clamps to the 29th"
    },
    {
      "given": {
        "mode": "add",
        "start": "2026-03-31",
        "op": "subtract",
        "months": 1,
        "days": 1
      },
      "expect": {
        "date": "2026-02-27",
        "totalDays": -32
      },
      "source": "hand calculation in content.mdx: March 31 minus one month is February 28, minus one day is February 27"
    },
    {
      "given": {
        "mode": "between",
        "start": "2026-01-01",
        "end": "2026-12-31",
        "includeEnd": false,
        "useWorkingDays": false
      },
      "expect": {
        "totalDays": 364,
        "span": {
          "years": 0,
          "months": 11,
          "days": 30
        },
        "weeks": {
          "weeks": 52,
          "days": 0
        }
      },
      "source": "hand calculation in content.mdx; Python: (date(2026,12,31) - date(2026,1,1)).days = 364"
    },
    {
      "given": {
        "mode": "between",
        "start": "2026-01-01",
        "end": "2026-12-31",
        "includeEnd": true,
        "useWorkingDays": false
      },
      "expect": {
        "totalDays": 365,
        "span": {
          "years": 1,
          "months": 0,
          "days": 0
        }
      },
      "source": "hand calculation in content.mdx: 364 days plus the end date"
    },
    {
      "given": {
        "mode": "between",
        "start": "2026-01-01",
        "end": "2026-01-31",
        "includeEnd": false,
        "useWorkingDays": true,
        "excludeSaturday": true,
        "excludeSunday": true,
        "excludeHolidays": true,
        "country": "us"
      },
      "expect": {
        "workDays": 20,
        "totalDays": 30
      },
      "source": "OPM federal holidays 2026 (https://www.opm.gov/policy-data-oversight/pay-leave/federal-holidays/); hand calculation in content.mdx"
    },
    {
      "given": {
        "mode": "between",
        "start": "2026-12-31",
        "end": "2026-01-01",
        "includeEnd": false,
        "useWorkingDays": false
      },
      "expect": {
        "totalDays": -364,
        "span": {
          "years": 0,
          "months": 11,
          "days": 30
        },
        "note": "The end date is before the start date, so the count is negative."
      },
      "source": "hand calculation in content.mdx: the dates swap and the count is negative"
    }
  ],
  "sources": [
    "U.S. Naval Observatory, Leap Years: the Gregorian leap year rule. https://aa.usno.navy.mil/faq/leap_years",
    "U.S. Office of Personnel Management, Federal Holidays (2026: January 1 and January 19). https://www.opm.gov/policy-data-oversight/pay-leave/federal-holidays/",
    "5 U.S.C. 6103, federal holidays and the weekend rule. https://www.law.cornell.edu/uscode/text/5/6103",
    "GOV.UK, UK bank holidays (England and Wales). https://www.gov.uk/bank-holidays",
    "Canada Labour Code, section 166 (general holidays). https://laws-lois.justice.gc.ca/eng/acts/L-2/"
  ],
  "related": [
    "days-between-dates",
    "days-from-today",
    "birthday",
    "time-duration"
  ],
  "changelog": [
    {
      "date": "2026-09-28",
      "note": "The answer reads “From … to …: N days”; the range note says results may fall outside 1600 to 2400."
    }
  ]
}
