[ { "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" } ]