{
  "category": "Date and time functions",
  "display_name": "DATEDIF",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.DATEDIF",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Recorded: 10 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 10 recorded answers",
    "workbook_corpus": {
      "cells": 10,
      "matched": 10
    }
  },
  "implementations": [
    {
      "commit": "9e1884369a678158dd82d3d74188daf986995e87",
      "flavour": "excel-compatibility-candidate",
      "language": "Rust",
      "name": "CalcFunc",
      "own_code": [
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/dates.rs#L271-L280",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/ported/date_kernels.rs#L366-L376",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/ported/date_kernels.rs#L378-L385",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/ported/date_kernels.rs#L387-L436"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/dates::environment",
        "catalogue/dates::system",
        "catalogue/dates::to_1900",
        "catalogue/dates::date_arg",
        "locale::days_from_civil",
        "locale::excel_serial_from_ymd",
        "ported/date_kernels::days_from_civil",
        "ported/date_kernels::civil_from_days",
        "ported/date_kernels::ymd_1900",
        "ported/date_kernels::is_leap",
        "ported/date_kernels::days_in_month",
        "ported/date_kernels::whole",
        "ported/date_kernels::ymd_of"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/dates.rs#L271-L280",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 10 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.DATEDIF.json",
  "name": "DATEDIF",
  "notes": [],
  "schema": "efh.function-reference/v1",
  "section_order": [
    "what-it-does",
    "try-it",
    "quirks",
    "how-to-implement",
    "version-differences",
    "alternatives"
  ],
  "sections": {
    "alternatives": "\n### Relationships\n\n- **[DAYS](FUNC.DAYS.md)** and the `−` operator — the direct competitors for `\"D\"`, both of which\n  tolerate a negative interval where `DATEDIF` errors, and one of which Microsoft's own page\n  recommends over `DATEDIF`.\n- **[YEARFRAC](FUNC.YEARFRAC.md)** — the *fractional* interval in years, on a selectable day-count\n  basis. `YEARFRAC` answers \"how much of a year\", `DATEDIF(\"Y\")` answers \"how many whole years\";\n  they are frequently substituted for one another and are not interchangeable.\n- **[EDATE](FUNC.EDATE.md)** — the inverse operation for months: `DATEDIF(a, EDATE(a, n), \"M\")`\n  should be `n` for any `n ≥ 0`, which is the obvious metamorphic relation for this function and,\n  as far as this Handbook records, has never been run.\n- **[DAYS360](FUNC.DAYS360.md)** — also an interval, but on the accounting 30/360 convention.\n\n\n",
    "how-to-implement": "\n### Notes for implementers\n\n\n1. **Implement the three interval units and the three remainder units as separate ideas.** The\n   remainder units are not \"the interval units modulo something\"; they are defined by discarding\n   components of the *operands*, before any subtraction.\n2. **`\"MD\"` needs a documented borrowing rule, and the documentation does not supply one.** Whatever\n   an implementation does, it should say so, and it should not claim to match Excel until someone\n   has looked. This is the single largest unknown in the function.\n3. **Enforce the `start > end` error before anything else.** It is the one documented error and it\n   changes the shape of the whole contract.\n4. **Decide and record the `unit` matching rule** — case sensitivity, surrounding whitespace,\n   whether a non-text argument coerces. None of it is documented.\n5. **Do not implement `\"Y\"` as a year subtraction with a correction.** Compute it as \"the largest\n   `n` such that `start` advanced by `n` years is not after `end`\", which is correct by\n   construction and makes the leap-day cases fall out rather than needing patches.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns a `Number`: an integer count in the requested unit.\n\n- **`\"Y\"` is complete years, and that is why it works for ages.** `DATEDIF(birth, today, \"Y\")` is\n  correct on the day before a birthday and correct on the birthday, where `YEAR(today) −\n  YEAR(birth)` is wrong on one of them.\n- **`\"D\"` is a plain day count**, and Microsoft's page says so explicitly, adding: \"If you want to\n  find the number of days between two dates, simply subtract the later date from the earlier date.\"\n  That is an unusually candid piece of documentation — the vendor telling you the function is\n  unnecessary for its simplest unit. (The sentence as published says to subtract \"the later date\n  from the earlier date\", which would give a negative count; the intent is plainly the other way\n  round. Quoted here as written, per the Handbook's practice of not silently repairing sources.)\n- **`\"MD\"` is flagged by Microsoft as unreliable** and should be treated as such.\n- **Leap-day arguments** are where `\"YM\"` and `\"YD\"` are most likely to surprise, because\n  discarding the year from 29 February leaves a date that does not exist in most years.\n- **Equal dates** give 0 in every unit.\n- **Time components** — the page does not state whether fractional serials are truncated before the\n  comparison. Unverified here.\n\n\n\n### Errors\n\n\nAs documented on the Microsoft page:\n\n- `#NUM!` \"if the start_date is greater than the end_date\". This is a strict, documented asymmetry:\n  `DATEDIF` refuses negative intervals where plain subtraction and [DAYS](FUNC.DAYS.md) simply go\n  negative. Any wrapper that feeds unsorted date pairs to `DATEDIF` will surface `#NUM!` for half\n  of them.\n\n`#VALUE!` for an unrecognized `unit` code is the behaviour readers expect and is **not stated on\nthat page**; it is not asserted here. Ordinary coercion failures and error propagation follow the\nengine rules in [coercion and lifting](../model/02-coercion-and-lifting.md).\n\n\n",
    "sources": "\n- Microsoft 365 support, **DATEDIF function** —\n  <https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c>.\n  Source of the syntax, the six-unit table quoted verbatim above, the Lotus 1-2-3 rationale, the\n  \"we don't recommend using the 'MD' argument\" warning, the `#NUM!` condition, and the suggestion\n  to subtract dates directly instead.\n- [FUNC.DATE](FUNC.DATE.md) — the serial-number model this function measures on.\n- Handbook call-model chapter [02 coercion and lifting](../model/02-coercion-and-lifting.md).\n- `data/functions/FUNC.DATEDIF.json`, `data/presence/FUNC.DATEDIF.json`,\n  `data/battery/FUNC.DATEDIF.json`.\n\n",
    "version-differences": "No comparison between specific Excel builds is recorded here yet. This does not establish that all builds behave alike.",
    "what-it-does": "\n`DATEDIF` measures the interval between two dates in a calendar unit named by a text code. It is\nthe only function in this category whose *unit* is an argument rather than baked into the name,\nand it is the only one Microsoft explicitly describes as retained for compatibility: \"Excel\nprovides the DATEDIF function in order to support older workbooks from Lotus 1-2-3.\"\n\nIts status is genuinely unusual and worth stating plainly, because readers meet the function\nthrough folklore before they meet it through documentation:\n\n- It **is** documented. Microsoft publishes a support page for it, cited below, with a syntax line,\n  a unit table, a caveat and an error condition.\n- It is widely reported to be absent from Excel's in-product function surface — formula\n  autocomplete, the function wizard, argument tooltips — which is why readers meet it as \"hidden\"\n  or \"undocumented\". This Handbook has not verified the in-product behaviour in any Excel build,\n  so it is recorded here as a widely-reported property and not as a finding. What can be said from\n  the record is narrower and sufficient: the function is **documented but unadvertised**.\n- Microsoft's page **discourages one of its own unit codes**: \"We don't recommend using the 'MD'\n  argument, as there are known limitations with it.\"\n\nThe six documented units, verbatim from that page:\n\n| `unit` | Returns |\n|---|---|\n| `\"Y\"` | \"The number of complete years in the period.\" |\n| `\"M\"` | \"The number of complete months in the period.\" |\n| `\"D\"` | \"The number of days in the period.\" |\n| `\"MD\"` | \"The difference between the days in start_date and end_date. The months and years of the dates are ignored.\" |\n| `\"YM\"` | \"The difference between the months in start_date and end_date. The days and years of the dates are ignored\" |\n| `\"YD\"` | \"The difference between the days of start_date and end_date. The years of the dates are ignored.\" |\n\nTwo different kinds of thing are in that table, and the mixture is the source of the surprise:\n\n- **`\"Y\"`, `\"M\"`, `\"D\"` are interval counts** — how much whole time has elapsed. `\"Y\"` is the\n  \"complete years\" that make it the standard age formula, and it is *not* `YEAR(end) − YEAR(start)`.\n- **`\"MD\"`, `\"YM\"`, `\"YD\"` are component remainders** — what is left over after the larger units are\n  removed. They exist so that `Y`/`YM`/`MD` can be composed into \"3 years, 2 months and 17 days\".\n\nThe remainder units are where the function's reputation comes from. `\"MD\"` compares two\nday-of-month numbers with the months and years discarded; when the end day-of-month is smaller than\nthe start day-of-month, the subtraction has to borrow from a month whose length depends on which\nmonth you decide to borrow from — and there is no canonical answer. Microsoft's own page reports\nthe consequence rather than the mechanism: `\"MD\"` can produce negative values, zero, or inaccurate\nresults. This Handbook records that as documented vendor guidance, not as a measured\ncharacterization; nobody has determined here *which* inputs misbehave or why.\n\n\n\n### Arguments\n\n\n`DATEDIF(start_date, end_date, unit)` — all three required. Note the argument order: start first,\nunlike [DAYS](FUNC.DAYS.md), which takes the end date first.\n\n**start_date** — the beginning of the period, as a date serial. Microsoft's page treats it as a\nserial like the rest of the category.\n\n**end_date** — the end of the period. Must not be earlier than `start_date`; see Errors.\n\n**unit** — text, one of the six codes above. The codes are conventionally written uppercase; the\ndocumentation gives them uppercase and does not state whether matching is case-insensitive, which\nis a small but real open question for an implementer.\n\nThe misunderstood argument is `unit`, in two ways. Readers reach for `\"M\"` expecting a month\n*difference* and get complete months elapsed; and readers reach for `\"YD\"` expecting \"days into the\nyear\" and get something defined by discarding the years from both dates, which is not the same\nthing when the two dates sit either side of 29 February.\n\n\n"
  },
  "signature": {
    "display": "DATEDIF(start_date, end_date, unit)",
    "parameters": [
      {
        "description": null,
        "name": "start_date",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "end_date",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "unit",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 3,
        "min": 3
      },
      "category": "Date and time functions",
      "classification": {
        "arg_preparation_profile": "ValuesOnlyPreAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "None",
        "host_interaction_class": "None",
        "kernel_signature_class": "Custom",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "Whole days, months or years between two dates",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Calculates the number of days, months, or years between two dates. This function is useful in formulas where you need to calculate an age.",
        "microsoft_url": "https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "DATEDIF"
        },
        {
          "locale": "bg-BG",
          "name": "DATEDIF"
        },
        {
          "locale": "cs-CZ",
          "name": "DATEDIF"
        },
        {
          "locale": "da-DK",
          "name": "DATO.FORSKEL"
        },
        {
          "locale": "de-DE",
          "name": "DATEDIF"
        },
        {
          "locale": "el-GR",
          "name": "DATEDIF"
        },
        {
          "locale": "en-AU",
          "name": "DATEDIF"
        },
        {
          "locale": "en-GB",
          "name": "DATEDIF"
        },
        {
          "locale": "en-US",
          "name": "DATEDIF"
        },
        {
          "locale": "es-ES",
          "name": "SIFECHA"
        },
        {
          "locale": "et-EE",
          "name": "DATEDIF"
        },
        {
          "locale": "fi-FI",
          "name": "PVMERO"
        },
        {
          "locale": "fr-FR",
          "name": "DATEDIF*"
        },
        {
          "locale": "he-IL",
          "name": "DATEDIF"
        },
        {
          "locale": "hr-HR",
          "name": "DATEDIF"
        },
        {
          "locale": "hu-HU",
          "name": "DÁTUMTÓLIG"
        },
        {
          "locale": "id-ID",
          "name": "DATEDIF"
        },
        {
          "locale": "it-IT",
          "name": "DATEDIF"
        },
        {
          "locale": "ja-JP",
          "name": "DATEDIF"
        },
        {
          "locale": "ko-KR",
          "name": "DATEDIF"
        },
        {
          "locale": "lt-LT",
          "name": "DATEDIF"
        },
        {
          "locale": "lv-LV",
          "name": "DATEDIF"
        },
        {
          "locale": "nb-NO",
          "name": "DATEDIF"
        },
        {
          "locale": "nl-NL",
          "name": "DATUMVERSCHIL"
        },
        {
          "locale": "pl-PL",
          "name": "DATA.RÓŻNICA"
        },
        {
          "locale": "pt-BR",
          "name": "DATEDIF"
        },
        {
          "locale": "pt-PT",
          "name": "DATADIF"
        },
        {
          "locale": "ro-RO",
          "name": "DATEDIF"
        },
        {
          "locale": "ru-RU",
          "name": "РАЗНДАТ"
        },
        {
          "locale": "sk-SK",
          "name": "DATEDIF"
        },
        {
          "locale": "sl-SI",
          "name": "DATEDIF"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "DATEDIF"
        },
        {
          "locale": "sv-SE",
          "name": "DATEDIF"
        },
        {
          "locale": "th-TH",
          "name": "DATEDIF"
        },
        {
          "locale": "tr-TR",
          "name": "TARİHFARKI işlevi"
        },
        {
          "locale": "uk-UA",
          "name": "DATEDIF"
        },
        {
          "locale": "vi-VN",
          "name": "DATEDIF"
        },
        {
          "locale": "zh-CN",
          "name": "DATEDIF"
        },
        {
          "locale": "zh-HK",
          "name": "DATEDIF"
        },
        {
          "locale": "zh-TW",
          "name": "DATEDIF"
        }
      ],
      "signature": {
        "display": "DATEDIF(start_date, end_date, unit)",
        "parameters": [
          {
            "description": null,
            "name": "start_date",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "end_date",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "unit",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "DATEDIF",
      "version_marker": null,
      "xlcall": {
        "code": "351",
        "symbol": "xlfDatedif"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c"
  },
  "try_it": {
    "formula": "=DATEDIF(DATE(2024,1,1),DATE(2026,11,6),\"Y\")"
  },
  "url": "https://handbook.dnacalc.com/functions/DATEDIF.html",
  "variants": [],
  "versions": []
}