{"name":"datetime","intro":"A model has no clock and no calendar. `datetime` supplies both, and refuses the two inputs that silently produce wrong answers everywhere else: timezone abbreviations (`IST` is three different zones) and bare numeric dates (`03/04/2025` is two different days). Every returned instant carries its offset, zone and weekday so nothing has to be re-derived.","when_to_use":["Any time the current date or time matters — `now` is the only way to get it.","Converting between zones, which needs IANA names (`Asia/Kolkata`, not `IST`).","Parsing user-written dates, including relative phrases like `next friday 5pm`.","Deadlines and SLAs: `add`/`diff` with `business_days` and a holiday region.","Schedules: `recurrence` for RRULEs and phrases, `cron_next` for cron expressions.","Ages, fiscal periods, overlaps and timesheet totals."],"network":false,"related":"[`geo_offline`](/docs/tools/geo_offline) to turn a city name into an IANA zone before converting · [`numbers`](/docs/tools/numbers) for formatting the durations you get back.","docs_url":"/docs/tools/datetime","modes":[{"name":"now","purpose":"The current instant; the model has no clock without this. tz may be a list of zones (or [{tz, label}]) for several at once","description":"Returns the current instant with its ISO string, date, weekday, time, UTC offset, zone, unix timestamp, DST flag, ISO week and day of year. With no `tz` the answer is UTC and says so in `assumptions`. Pass a list as `tz` for several zones in one call: the result is then `utc` plus one full entry per zone under `zones`, each with the `label` you gave it, if any. This is the only mode whose output changes between calls; everything else can be pinned by passing explicit dates.","parameters":[{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"IANA zone name, a fixed `UTC+05:30` offset, or `local` — or a list of them, where an entry may be `{\"tz\": ..., \"label\": ...}`.","default":"`UTC`"}],"examples":[{"mode":"now","tz":"Asia/Kolkata"},{"mode":"now"},{"mode":"now","tz":"UTC+05:30"},{"mode":"now","tz":[{"tz":"Asia/Kolkata","label":"Acme India"},{"tz":"Asia/Dubai","label":"Acme FZ-LLC"},"Europe/Minsk"]},{"mode":"now","tz":[{"label":"Acme India"}]},{"mode":"now","tz":"IST"},{"mode":"now","tz":"Mars/Olympus"}]},{"name":"convert_tz","purpose":"Move one instant between time zones.","description":"Converts an instant from one zone to another, or to several at once by passing a list as `to_tz`. The response repeats the source instant and gives each target with its offset and a `day_shift` (−1, 0 or +1) so nobody has to work out whether the date moved. A bare date is refused: midnight in which zone? A wall time the clocks skipped (`2026-03-08 02:30` in New York) or repeated (`2026-11-01 01:30`) is answered with a warning naming which it is — the DST cases that are silently wrong everywhere else.","parameters":[{"name":"value","type":"string \\| integer \\| number","required":false,"doc":"The instant to convert. `now` or omitted uses the current instant.","default":"`now`"},{"name":"from_tz","type":"string","required":false,"doc":"Zone of `value` when it carries no offset.","default":null},{"name":"to_tz","type":"string \\| object \\| string \\| object[]","required":true,"doc":"Target zone, or a list of them; an entry may be `{\"tz\": ..., \"label\": ...}` and the label is echoed back.","default":null},{"name":"locale","type":"string","required":false,"doc":"Country code used to read numeric dates, e.g. `IN`.","default":null}],"examples":[{"mode":"convert_tz","value":"2025-03-09T09:30:00","from_tz":"America/New_York","to_tz":"Asia/Kolkata"},{"mode":"convert_tz","value":"2025-11-04T18:00:00","from_tz":"Europe/London","to_tz":["Asia/Kolkata","America/Los_Angeles","Australia/Sydney"]},{"mode":"convert_tz","value":"2025-06-01T10:00:00+05:30","to_tz":"UTC"},{"mode":"convert_tz","value":"2025-11-04T18:00:00","from_tz":"Europe/London","to_tz":[{"tz":"Asia/Kolkata","label":"Acme India"},{"tz":"America/New_York","label":"Acme US"}]},{"mode":"convert_tz","value":"2025-06-01","from_tz":"UTC","to_tz":"Asia/Tokyo"},{"mode":"convert_tz","value":"2025-06-01T10:00:00","to_tz":"Asia/Tokyo"},{"mode":"convert_tz","value":"2025-06-01T10:00:00","from_tz":"IST","to_tz":"UTC"}]},{"name":"parse","purpose":"Turn any written date into a normalised instant.","description":"Accepts ISO 8601, unix timestamps (seconds or milliseconds), written forms (`14 Aug 2025`, `Aug 14, 2025`) and relative phrases (`tomorrow`, `next friday 5pm`, `3 weeks ago`, `end of month`). Relative phrases resolve against `ref_date` when given, otherwise against now. Numeric dates like `03/04/2025` are refused unless `locale` says which order to read, and the refusal spells out both readings as ISO dates. A two-digit year uses a stated pivot — `49` and below is 20xx, `50` and above is 19xx — and the century chosen is recorded in `assumptions`, because for a date of birth guessing it silently is a hundred years wrong.","parameters":[{"name":"value","type":"string \\| integer \\| number","required":true,"doc":"The date to parse.","default":null},{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"Zone attached to a naive result.","default":null},{"name":"locale","type":"string","required":false,"doc":"Country code deciding DD/MM vs MM/DD, e.g. `IN`, `US`.","default":null},{"name":"ref_date","type":"string","required":false,"doc":"Anchor for relative phrases.","default":"now"}],"examples":[{"mode":"parse","value":"2025-03-04"},{"mode":"parse","value":"03/04/2025","locale":"IN"},{"mode":"parse","value":"03/04/2025","locale":"US"},{"mode":"parse","value":"next friday 5pm","ref_date":"2025-08-26T10:00:00","tz":"Asia/Kolkata"},{"mode":"parse","value":1755180000000},{"mode":"parse","value":"03/04/2025"},{"mode":"parse","value":"sometime next quarter-ish"},{"mode":"parse","value":"31/02/2025"},{"mode":"parse","value":"03/04/2025","locale":"XX"}]},{"name":"add","purpose":"Add or subtract a duration, including business days.","description":"Adds `amount` of `unit` to a date. Calendar units (`months`, `years`) clamp to the end of the month and warn when they do — 31 Jan + 1 month is 28 Feb, not 3 March. Elapsed units (`hours`, `minutes`, `seconds`) are computed through UTC so a DST transition cannot swallow an hour. `unit: business_days` walks the calendar, skipping weekends and — when `region` is given — public holidays, listing each one skipped.","parameters":[{"name":"value","type":"string \\| integer \\| number","required":false,"doc":"Starting date.","default":"`now`"},{"name":"amount","type":"number","required":true,"doc":"How much to add; negative subtracts. Up to 4 000 000 — beyond that no calendar date can hold the result.","default":null},{"name":"unit","type":"string","required":true,"doc":"`seconds`, `minutes`, `hours`, `days`, `weeks`, `fortnights`, `months`, `quarters`, `years`, `business_days`.","default":null},{"name":"region","type":"string","required":false,"doc":"ISO country code whose public holidays to skip, for `business_days`.","default":null},{"name":"subdiv","type":"string","required":false,"doc":"State/province code for regional holidays.","default":null},{"name":"weekend","type":"string[]","required":false,"doc":"Which weekdays count as weekend.","default":"`[saturday, sunday]`"},{"name":"extra_holidays","type":"array","required":false,"doc":"Extra non-working dates.","default":null},{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"Zone applied to `value`.","default":null},{"name":"locale","type":"string","required":false,"doc":"Country code for reading numeric dates.","default":null}],"examples":[{"mode":"add","value":"2025-01-31","amount":1,"unit":"months"},{"mode":"add","value":"2025-08-13","amount":3,"unit":"business_days","region":"IN"},{"mode":"add","value":"2025-03-09T00:30:00","tz":"America/New_York","amount":3,"unit":"hours"},{"mode":"add","value":"2025-08-26","amount":-2,"unit":"weeks"},{"mode":"add","value":"2025-08-26","amount":3,"unit":"fortnite"},{"mode":"add","value":"2025-08-26","amount":1.5,"unit":"months"}]},{"name":"diff","purpose":"The distance between two instants, every way at once.","description":"Returns the gap between `start` and `end` as a calendar breakdown (years/months/days/…), as totals in every unit, as whole months, and as a human string — plus a `sign` and a plain-English `direction`, so a negative result cannot be misread. Pass `unit: business_days` (with an optional `region`) to count working days instead.","parameters":[{"name":"start","type":"string","required":true,"doc":"Start instant.","default":null},{"name":"end","type":"string","required":false,"doc":"End instant.","default":"`now`"},{"name":"unit","type":"string","required":false,"doc":"Report one unit in `value`; `business_days` counts working days.","default":"`auto`"},{"name":"region","type":"string","required":false,"doc":"ISO country code for holidays, with `business_days`.","default":null},{"name":"weekend","type":"string[]","required":false,"doc":"Which weekdays are non-working.","default":"`[saturday, sunday]`"},{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"Zone applied to both sides.","default":null},{"name":"locale","type":"string","required":false,"doc":"Country code for reading numeric dates.","default":null}],"examples":[{"mode":"diff","start":"2025-01-01","end":"2025-03-15"},{"mode":"diff","start":"2025-01-01","end":"2025-03-15","unit":"business_days","region":"IN"},{"mode":"diff","start":"2025-03-15T18:00:00","end":"2025-03-15T09:30:00"},{"mode":"diff","start":"2025-01-01","end":"2025-02-01","unit":"moons"},{"mode":"diff","start":"01/02/2025","end":"2025-03-01"}]},{"name":"weekday","purpose":"Everything calendar-shaped about one date.","description":"Given a date, returns the weekday (name, ISO number and Monday-zero index), whether it is a weekend, the ISO week and ISO year, day of year, days in that month, leap-year flag, quarter, month name and week of month. One call instead of six derivations.","parameters":[{"name":"value","type":"string \\| integer \\| number","required":false,"doc":"The date.","default":"`today`"},{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"Zone applied to `value`.","default":null},{"name":"locale","type":"string","required":false,"doc":"Country code for reading numeric dates.","default":null}],"examples":[{"mode":"weekday","value":"2025-08-15"},{"mode":"weekday","value":"2024-02-29"},{"mode":"weekday","value":"31/02/2025"},{"mode":"weekday","value":"03/04/2025"}]},{"name":"nth_weekday","purpose":"The nth (or last) weekday of a month.","description":"Resolves rules like “fourth Thursday of November” or “last Friday of the quarter”. `n` may be an ordinal word (`first`, `last`) or a number; negative counts back from the end of the month. If the month has no such weekday, that is an error rather than a silently clamped date.","parameters":[{"name":"year","type":"integer","required":false,"doc":"Year. Taken from `value`, or today, when omitted.","default":null},{"name":"month","type":"integer \\| string","required":false,"doc":"Month number or name.","default":null},{"name":"weekday","type":"string","required":true,"doc":"Weekday name, abbreviation, or Monday-zero index.","default":null},{"name":"n","type":"integer","required":false,"doc":"Which one: 1..5, −1..−5, or `first`/`last`.","default":"1"},{"name":"value","type":"string \\| integer \\| number","required":false,"doc":"Date whose year/month to use when `year`/`month` are omitted.","default":null}],"examples":[{"mode":"nth_weekday","year":2025,"month":11,"weekday":"thursday","n":4},{"mode":"nth_weekday","year":2025,"month":2,"weekday":"friday","n":-1},{"mode":"nth_weekday","year":2025,"month":"September","weekday":"monday","n":"first"},{"mode":"nth_weekday","year":2025,"month":2,"weekday":"friday","n":5},{"mode":"nth_weekday","year":2025,"month":2,"weekday":"friday","n":0},{"mode":"nth_weekday","year":2025,"month":2,"weekday":"sunsday"}]},{"name":"business_days","purpose":"Count working days in a range, holidays included.","description":"Counts working days between two dates, both ends inclusive by default (matching Excel’s NETWORKDAYS). Weekends are configurable — pass `weekend: [friday, saturday]` for the Gulf working week — and a `region` (plus optional `subdiv`) pulls in that country’s public holidays. The response lists the holidays it skipped and, for short ranges, every working date, and reports `sign` and `direction` the way `diff` does when `end` is before `start` rather than swapping them silently. The range is capped at 3 660 days (about ten years).","parameters":[{"name":"start","type":"string","required":true,"doc":"Start of the range.","default":null},{"name":"end","type":"string","required":true,"doc":"End of the range.","default":null},{"name":"region","type":"string","required":false,"doc":"ISO country code whose public holidays to exclude.","default":null},{"name":"subdiv","type":"string","required":false,"doc":"State/province code for regional holidays.","default":null},{"name":"weekend","type":"string[]","required":false,"doc":"Non-working weekdays.","default":"`[saturday, sunday]`"},{"name":"extra_holidays","type":"array","required":false,"doc":"Extra non-working dates, e.g. a company shutdown.","default":null},{"name":"include_start","type":"boolean","required":false,"doc":"Count the start date.","default":"`true`"},{"name":"include_end","type":"boolean","required":false,"doc":"Count the end date.","default":"`true`"}],"examples":[{"mode":"business_days","start":"2026-08-01","end":"2126-08-01","region":"IN"},{"mode":"business_days","start":"2025-08-11","end":"2025-08-22","region":"IN"},{"mode":"business_days","start":"2025-08-11","end":"2025-08-22","weekend":["friday","saturday"],"region":"AE"},{"mode":"business_days","start":"2025-10-01","end":"2025-10-10","region":"IN","subdiv":"WB","extra_holidays":["2025-10-06"]},{"mode":"business_days","start":"2025-08-01","end":"2025-08-10","weekend":["funday"]},{"mode":"business_days","start":"2025-08-01","end":"2025-08-10","region":"XX"}]},{"name":"overlap","purpose":"Do two intervals overlap, and by how much?","description":"Compares two half-open intervals `[start, end)` and names their relation — `a contains b`, `a overlaps b`, `a meets b`, `a before b` and so on. When they overlap you get the overlapping window and its length; when they do not, you get the gap. Both intervals must agree about whether they carry a timezone.","parameters":[{"name":"a","type":"object","required":true,"doc":"First interval, `{start, end}`.","default":null},{"name":"b","type":"object","required":true,"doc":"Second interval, `{start, end}`.","default":null},{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"Zone applied to naive endpoints.","default":null},{"name":"locale","type":"string","required":false,"doc":"Country code for reading numeric dates.","default":null}],"examples":[{"mode":"overlap","a":{"start":"2025-08-26T09:00:00","end":"2025-08-26T10:30:00"},"b":{"start":"2025-08-26T10:00:00","end":"2025-08-26T11:00:00"}},{"mode":"overlap","a":{"start":"2025-08-26T09:00:00","end":"2025-08-26T10:00:00"},"b":{"start":"2025-08-26T14:00:00","end":"2025-08-26T15:00:00"}},{"mode":"overlap","a":{"start":"2025-08-26T09:00:00","end":"2025-08-26T18:00:00"},"b":{"start":"2025-08-26T11:00:00","end":"2025-08-26T12:00:00"}},{"mode":"overlap","a":"2025-08-26","b":{"start":"2025-08-26T09:00:00","end":"2025-08-26T10:00:00"}},{"mode":"overlap","a":{"start":"2025-08-26T12:00:00","end":"2025-08-26T09:00:00"},"b":{"start":"2025-08-26T09:00:00","end":"2025-08-26T10:00:00"}},{"mode":"overlap","a":{"start":"2025-08-26T09:00:00+05:30","end":"2025-08-26T10:00:00+05:30"},"b":{"start":"2025-08-26T09:30:00","end":"2025-08-26T10:30:00"}}]},{"name":"free_slots","purpose":"Common free slots for people in different time zones.","description":"Takes two or more participants, each with an IANA zone and one or more availability windows — a weekly pattern like `09:00`–`17:00` on `[mon, …, fri]`, or a one-off local range like `2026-09-01T09:00`–`2026-09-01T12:00` — lays every window on that person's own calendar through `zoneinfo`, intersects them all in UTC, and returns the slots that fit `duration`, earliest UTC first. Every slot is shown in each participant's local time and in UTC, `per_day` totals the overlap per UTC date. Two participants in the same zone are numbered apart (`Asia/Kolkata #1`, `#2`) rather than refused — two colleagues in one city with different hours is the ordinary case. A window that spans a DST change is expanded to its real length with a note in `assumptions`. No common time is still `ok: true` with `slots: []` and a warning naming the participants who never overlap.","parameters":[{"name":"participants","type":"object[]","required":true,"doc":"Two or more of `{tz, label?, windows: [{start, end, days?}]}`. A window with `HH:MM` ends repeats on `days` (every day when omitted); one with full timestamps is a single occurrence.","default":null},{"name":"duration","type":"integer","required":false,"doc":"Meeting length in minutes.","default":"`granularity`"},{"name":"granularity","type":"integer","required":false,"doc":"Step between candidate starts, in minutes.","default":"30"},{"name":"start","type":"string","required":false,"doc":"First UTC date to search.","default":"`today`"},{"name":"end","type":"string","required":false,"doc":"Last UTC date to search, inclusive; at most 92 days.","default":"`start` + 7 days"},{"name":"limit","type":"integer","required":false,"doc":"Maximum slots returned, 1..500; the rest are counted in `warnings`.","default":"20"}],"examples":[{"mode":"free_slots","participants":[{"tz":"Asia/Kolkata","label":"Kolkata","windows":[{"start":"09:00","end":"20:00","days":["mon","tue","wed","thu","fri"]}]},{"tz":"Europe/London","label":"London","windows":[{"start":"08:00","end":"16:00","days":["mon","tue","wed","thu","fri"]}]},{"tz":"America/New_York","label":"New York","windows":[{"start":"07:00","end":"11:00","days":["mon","tue","wed","thu","fri"]}]}],"start":"2026-09-07","end":"2026-09-08","duration":60,"limit":4},{"mode":"free_slots","participants":[{"tz":"Asia/Kolkata","label":"Asha","windows":[{"start":"2026-09-01T09:00","end":"2026-09-01T12:00"}]},{"tz":"Europe/London","label":"Ben","windows":[{"start":"2026-09-01T05:00","end":"2026-09-01T08:00"}]}],"start":"2026-09-01","end":"2026-09-01","duration":60},{"mode":"free_slots","participants":[{"tz":"Asia/Kolkata","label":"Kolkata","windows":[{"start":"09:00","end":"18:00","days":["mon","tue","wed","thu","fri"]}]},{"tz":"Europe/London","label":"London","windows":[{"start":"09:00","end":"17:00","days":["mon","tue","wed","thu","fri"]}]},{"tz":"America/New_York","label":"New York","windows":[{"start":"09:00","end":"17:00","days":["mon","tue","wed","thu","fri"]}]}],"start":"2026-09-07","end":"2026-09-11"},{"mode":"free_slots","participants":[{"tz":"America/New_York","label":"NY","windows":[{"start":"00:00","end":"05:00","days":["sun"]}]},{"tz":"Europe/London","label":"LDN","windows":[{"start":"05:00","end":"10:00","days":["sun"]}]}],"start":"2026-03-08","end":"2026-03-08","granularity":60},{"mode":"free_slots","participants":[{"tz":"IST","windows":[{"start":"09:00","end":"17:00"}]},{"tz":"Europe/London","windows":[{"start":"09:00","end":"17:00"}]}],"start":"2026-09-07"},{"mode":"free_slots","participants":[{"tz":"Asia/Kolkata","windows":[{"start":"09:00","end":"17:00"}]}],"start":"2026-09-07"},{"mode":"free_slots","participants":[{"tz":"Asia/Kolkata","windows":[{"start":"17:00","end":"09:00"}]},{"tz":"Europe/London","windows":[{"start":"09:00","end":"17:00"}]}],"start":"2026-09-07"}]},{"name":"duration_sum","purpose":"Total a list of intervals — timesheets, shifts, sessions.","description":"Adds up a list of `{start, end}` intervals and reports the total in seconds, minutes, hours, days, `HH:MM` and words, plus per-interval rows, the average, and the longest and shortest. Overlapping intervals are still summed — but each overlap is named in `warnings` so double-counting is never silent.","parameters":[{"name":"ranges","type":"object[]","required":true,"doc":"Intervals, each `{start, end}` with an optional `label`.","default":null},{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"Zone applied to naive endpoints.","default":null},{"name":"locale","type":"string","required":false,"doc":"Country code for reading numeric dates.","default":null}],"examples":[{"mode":"duration_sum","ranges":[{"label":"morning","start":"2025-08-26T09:15:00","end":"2025-08-26T12:00:00"},{"label":"afternoon","start":"2025-08-26T13:00:00","end":"2025-08-26T17:30:00"},{"label":"evening","start":"2025-08-26T20:00:00","end":"2025-08-26T21:45:00"}]},{"mode":"duration_sum","ranges":[{"start":"2025-08-26T09:00:00","end":"2025-08-26T11:00:00"},{"start":"2025-08-26T10:30:00","end":"2025-08-26T12:00:00"}]},{"mode":"duration_sum","ranges":[{"start":"2025-08-26T09:00:00"}]},{"mode":"duration_sum","ranges":[{"start":"2025-08-26T11:00:00","end":"2025-08-26T09:00:00"}]}]},{"name":"recurrence","purpose":"Expand a recurring schedule into dates.","description":"Takes an RFC 5545 RRULE, or a plain-English phrase it converts to one — `every weekday`, `every other tuesday`, `every 2nd tuesday`, `every 15th of month`, `month end` — and lists the occurrences from `start`. A sub-daily frequency (`SECONDLY`, `MINUTELY`, `HOURLY`) keeps its times — `dates_only` defaults to false for those, since four copies of the same date is not an answer. Bound it with `count` or `until`. Output stops at `limit` whatever `count` says — a `count` of 1 000 000 returns 100 — and then `truncated` is `true` and `warnings` says so. The RRULE actually used is echoed back.","parameters":[{"name":"rule","type":"string","required":true,"doc":"RRULE string or a recognised phrase.","default":null},{"name":"start","type":"string","required":false,"doc":"First candidate date (DTSTART).","default":"`today`"},{"name":"count","type":"integer","required":false,"doc":"Stop after this many occurrences.","default":null},{"name":"until","type":"string","required":false,"doc":"Stop at this date.","default":null},{"name":"limit","type":"integer","required":false,"doc":"Hard cap on returned occurrences, max 1000.","default":"100"},{"name":"dates_only","type":"boolean","required":false,"doc":"Return dates rather than full timestamps.","default":"`true`"}],"examples":[{"mode":"recurrence","rule":"FREQ=DAILY","start":"2026-08-27","count":1000000},{"mode":"recurrence","rule":"every 2nd tuesday","start":"2025-01-01","count":5},{"mode":"recurrence","rule":"FREQ=WEEKLY;BYDAY=MO,WE,FR","start":"2025-01-01","count":6},{"mode":"recurrence","rule":"month end","start":"2025-01-01","until":"2025-06-30"},{"mode":"recurrence","rule":"every blue moon","start":"2025-01-01"},{"mode":"recurrence","rule":"every day","start":"2025-01-01","limit":5000},{"mode":"recurrence","rule":"FREQ=FORTNIGHTLY","start":"2025-01-01","count":3}]},{"name":"cron_next","purpose":"The next fire times of a cron expression.","description":"Evaluates a standard five-field cron expression (`minute hour day month weekday`) and returns the next `n` times it fires, in the zone you name. `@daily`, `@weekly`, `@monthly`, `@hourly`, `@yearly` are understood. The day-of-month/day-of-week OR rule — the one everybody gets wrong — is applied and stated in `assumptions`.","parameters":[{"name":"expr","type":"string","required":true,"doc":"Cron expression or `@`-alias.","default":null},{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"Zone the schedule runs in.","default":"`UTC`"},{"name":"start","type":"string","required":false,"doc":"Start searching after this instant.","default":"now"},{"name":"n","type":"integer","required":false,"doc":"How many fire times to return, 1..500.","default":"5"}],"examples":[{"mode":"cron_next","expr":"0 9 * * 1-5","tz":"Asia/Kolkata","start":"2025-08-15T00:00:00","n":3},{"mode":"cron_next","expr":"@monthly","start":"2025-01-15T00:00:00","n":3},{"mode":"cron_next","expr":"*/15 9-10 * * *","start":"2025-08-15T09:00:00","n":4},{"mode":"cron_next","expr":"0 9 * *"},{"mode":"cron_next","expr":"99 9 * * *"}]},{"name":"age","purpose":"Age on a given date, and the next birthday.","description":"Years, months and days between a date of birth and a reference date, plus total days, total months, the next birthday, days until it and the age being turned. February 29 birthdays are moved to February 28 in non-leap years, and that choice is stated in `assumptions` rather than assumed.","parameters":[{"name":"dob","type":"string","required":true,"doc":"Date of birth.","default":null},{"name":"on","type":"string","required":false,"doc":"Date to compute the age on.","default":"`today`"},{"name":"locale","type":"string","required":false,"doc":"Country code for reading numeric dates.","default":null}],"examples":[{"mode":"age","dob":"2000-02-29","ref_date":"2026-02-28"},{"mode":"age","dob":"1990-02-14","on":"2025-08-26"},{"mode":"age","dob":"2000-02-29","on":"2025-03-01"},{"mode":"age","dob":"2025-08-26","on":"1990-01-01"}]},{"name":"fiscal","purpose":"Which fiscal year and quarter a date falls in.","description":"Maps a date onto a fiscal calendar. `region` selects a known convention — India and the UK start in April, Australia in July, the US federal year in October — or set `fy_start_month` directly. Returns the FY label, its start and end, the quarter with its bounds, the day of the fiscal year and the days remaining.","parameters":[{"name":"value","type":"string \\| integer \\| number","required":false,"doc":"The date to place.","default":"`today`"},{"name":"region","type":"string","required":false,"doc":"ISO country code selecting a known FY convention.","default":null},{"name":"fy_start_month","type":"integer","required":false,"doc":"First month of the fiscal year, 1..12.","default":"1 (calendar year)"},{"name":"tz","type":"string \\| string \\| object[]","required":false,"doc":"Zone applied to `value`.","default":null}],"examples":[{"mode":"fiscal","value":"2025-08-26","region":"IN"},{"mode":"fiscal","value":"2025-08-26","region":"US"},{"mode":"fiscal","value":"2025-08-26","fy_start_month":7},{"mode":"fiscal","value":"2025-08-26","fy_start_month":13},{"mode":"fiscal","value":"the third quarter"}]}]}