[
{
"name": "today is today",
"args": [
"today",
"2026-09-28"
],
"expect": "2026-09-28"
},
{
"name": "tod is short for today",
"args": [
"tod",
"2026-09-28"
],
"expect": "2026-09-28"
},
{
"name": "capitals and surrounding spaces are ignored",
"args": [
" TOMORROW \t",
"2026-09-28"
],
"expect": "2026-09-29"
},
{
"name": "tmrw is tomorrow",
"args": [
"tmrw",
"2026-09-28"
],
"expect": "2026-09-29"
},
{
"name": "tmr is tomorrow",
"args": [
"Tmr",
"2026-09-28"
],
"expect": "2026-09-29"
},
{
"name": "yesterday crosses back over a month end",
"args": [
"yesterday",
"2026-03-01"
],
"expect": "2026-02-28"
},
{
"name": "a weekday name is the next one: friday on a Monday",
"args": [
"friday",
"2026-09-28"
],
"expect": "2026-10-02"
},
{
"name": "the same weekday is a week away, never today: friday on a Friday",
"args": [
"Friday",
"2026-10-02"
],
"expect": "2026-10-09"
},
{
"name": "a 3-letter weekday on that same weekday: mon on a Monday",
"args": [
"mon",
"2026-09-28"
],
"expect": "2026-10-05"
},
{
"name": "thurs is Thursday",
"args": [
"thurs",
"2026-09-28"
],
"expect": "2026-10-01"
},
{
"name": "tues is Tuesday, and on a Monday that is tomorrow",
"args": [
"tues",
"2026-09-28"
],
"expect": "2026-09-29"
},
{
"name": "sunday from a Saturday is the next day",
"args": [
"sun",
"2026-10-03"
],
"expect": "2026-10-04"
},
{
"name": "next week is Monday of next ISO week",
"args": [
"next week",
"2026-09-28"
],
"expect": "2026-10-05"
},
{
"name": "next week on a Sunday is the very next day",
"args": [
"next week",
"2026-10-04"
],
"expect": "2026-10-05"
},
{
"name": "next friday on a Monday is in next week, not this week's Friday",
"args": [
"next friday",
"2026-09-28"
],
"expect": "2026-10-09"
},
{
"name": "next sunday on a Sunday is 7 days on",
"args": [
"next sunday",
"2026-10-04"
],
"expect": "2026-10-11"
},
{
"name": "next month is the 1st of next month",
"args": [
"next month",
"2026-09-28"
],
"expect": "2026-10-01"
},
{
"name": "next month from New Year's Eve is the 1st of January",
"args": [
"next month",
"2026-12-31"
],
"expect": "2027-01-01"
},
{
"name": "next year is 1 January of next year",
"args": [
"next year",
"2026-09-28"
],
"expect": "2027-01-01"
},
{
"name": "weekend on a Monday is the coming Saturday",
"args": [
"weekend",
"2026-09-28"
],
"expect": "2026-10-03"
},
{
"name": "this weekend on a Saturday is today",
"args": [
"this weekend",
"2026-10-03"
],
"expect": "2026-10-03"
},
{
"name": "weekend on a Sunday is today, not next Saturday",
"args": [
"weekend",
"2026-10-04"
],
"expect": "2026-10-04"
},
{
"name": "in 3 days",
"args": [
"in 3 days",
"2026-09-28"
],
"expect": "2026-10-01"
},
{
"name": "in a week",
"args": [
"in a week",
"2026-09-28"
],
"expect": "2026-10-05"
},
{
"name": "in two weeks",
"args": [
"in two weeks",
"2026-09-28"
],
"expect": "2026-10-12"
},
{
"name": "in 1 day, singular",
"args": [
"in 1 day",
"2026-09-28"
],
"expect": "2026-09-29"
},
{
"name": "in 1 month from 31 January clamps to 28 February",
"args": [
"in 1 month",
"2026-01-31"
],
"expect": "2026-02-28"
},
{
"name": "in 1 month from 31 January 2028 is 29 February (leap year)",
"args": [
"in 1 month",
"2028-01-31"
],
"expect": "2028-02-29"
},
{
"name": "in a year from 29 February clamps to 28 February",
"args": [
"in a year",
"2028-02-29"
],
"expect": "2029-02-28"
},
{
"name": "in 2 months from 31 December is 28 February",
"args": [
"in 2 months",
"2026-12-31"
],
"expect": "2027-02-28"
},
{
"name": "in 999 days is the largest count",
"args": [
"in 999 days",
"2026-09-28"
],
"expect": "2029-06-23"
},
{
"name": "in 1000 days is too many: not a date phrase",
"args": [
"in 1000 days",
"2026-09-28"
],
"expect": null
},
{
"name": "in 0 days is not a date phrase",
"args": [
"in 0 days",
"2026-09-28"
],
"expect": null
},
{
"name": "a leading zero is not a count",
"args": [
"in 03 days",
"2026-09-28"
],
"expect": null
},
{
"name": "an unknown unit is not a date phrase",
"args": [
"in 3 lightyears",
"2026-09-28"
],
"expect": null
},
{
"name": "an ISO date is itself",
"args": [
"2026-10-01",
"2026-09-28"
],
"expect": "2026-10-01"
},
{
"name": "29 February in a leap year is a real date",
"args": [
"2028-02-29",
"2026-09-28"
],
"expect": "2028-02-29"
},
{
"name": "30 February is not a date, and not an error",
"args": [
"2026-02-30",
"2026-09-28"
],
"expect": null
},
{
"name": "an ISO date in the past is allowed",
"args": [
"2020-01-01",
"2026-09-28"
],
"expect": "2020-01-01"
},
{
"name": "due before a weekday",
"args": [
"due friday",
"2026-09-28"
],
"expect": "2026-10-02"
},
{
"name": "on before an ISO date",
"args": [
"on 2026-10-01",
"2026-09-28"
],
"expect": "2026-10-01"
},
{
"name": "due before in N days, with tabs and runs of spaces",
"args": [
"Due\tin 2 days",
"2026-09-28"
],
"expect": "2026-09-30"
},
{
"name": "on on its own is not a date phrase",
"args": [
"on",
"2026-09-28"
],
"expect": null
},
{
"name": "the whole text must be the phrase",
"args": [
"friday week",
"2026-09-28"
],
"expect": null
},
{
"name": "words around a phrase are not ignored",
"args": [
"pay rent tomorrow",
"2026-09-28"
],
"expect": null
},
{
"name": "next on its own is not a date phrase",
"args": [
"next",
"2026-09-28"
],
"expect": null
},
{
"name": "empty text is not a date phrase",
"args": [
"",
"2026-09-28"
],
"expect": null
},
{
"name": "whitespace only is not a date phrase",
"args": [
" \t ",
"2026-09-28"
],
"expect": null
},
{
"name": "full-width letters are not ASCII and not a keyword",
"args": [
"today",
"2026-09-28"
],
"expect": null
},
{
"name": "an object key is not a weekday",
"args": [
"constructor",
"2026-09-28"
],
"expect": null
},
{
"name": "today in day/month/year order is refused, even for a phrase that ignores it",
"args": [
"2026-10-01",
"28/09/2026"
],
"expectError": "is not an ISO date"
},
{
"name": "today that never existed is refused",
"args": [
"today",
"2026-02-30"
],
"expectError": "is not a real calendar date"
},
{
"name": "tomorrow after 9999-12-31 is out of range",
"args": [
"tomorrow",
"9999-12-31"
],
"expectError": "outside the supported range"
}
]