Reference · Dates
date.valid
date.valid(any, str | null=) -> boolWhat it does
Whether a value is text the date module accepts: a date "YYYY-MM-DD" that is a real
day, or a date-time "YYYY-MM-DDTHH:MM:SS" with an offset (Z, +01:00). With
"date" as the second argument only a date counts, with "date-time" only a date-time.
Any other value, null and numbers included, gives false; nothing here is an error.
Check text from a page with it before the arithmetic functions, which stop with a
runtime error on anything else; or give the field the type date, which refuses bad
text and date-times in a record, an annotation and a query.
Examples
print(date.valid("2026-10-27"), date.valid("2026-10-27T14:30:00Z"), date.valid("2026-02-30"))print(date.valid("2026-10-27T14:30:00Z", "date"), date.valid("2026-10-27", "date-time"))print(date.valid(42), date.valid(null), date.valid(""))true true falsefalse falsefalse false falseEdge cases
- Only the exact form counts:
"27/10/2026","2026-1-5", a space before the text, a date-time with a space instead ofT, without seconds or without an offset are allfalse, thoughdate.parsereads some of them. - The calendar is checked:
2024-02-29is valid,2023-02-29is not. - Years are 1 to 9999:
"0000-12-31"is not a date. - A fraction of a second and an offset with seconds are accepted in a date-time.
nullas the second argument is the same as leaving it out: either kind.
print(date.valid("27/10/2026"), date.valid("2026-1-5"), date.valid(" 2026-10-27"))print(date.valid("2026-10-27 14:30:00Z"), date.valid("2026-10-27T14:30Z"), date.valid("2026-10-27T14:30:00"))print(date.valid("2024-02-29"), date.valid("2023-02-29"), date.valid("0000-12-31"))print(date.valid("2026-10-27T14:30:00.123Z"), date.valid("2026-10-27", null))false false falsefalse false falsetrue false falsetrue trueErrors
The value never fails. The second argument must be "date", "date-time" or
null: anything else is a runtime error.
print(date.valid("2026-10-27", "time"))line 1: `date.valid` takes "date" or "date-time" as argument 2, got "time"Chaining
The value comes first in a pipeline. In a route, a check with a 400 of your own:
print(["2026-10-27", "soon", "2026-02-30"] | filter(date.valid))print("2026-10-27T14:30:00Z" | date.valid("date"))["2026-10-27"]falseA form with date fields, and the route it posts to. A browser's type="date" sends
YYYY-MM-DD, but anyone can post anything, so the route checks before counting:
route GET /leave = <form method="post" action="/leave"> <input type="date" name="from" required/> to <input type="date" name="to" required/> <button>Count the days</button> </form>route POST /leave { form: { from: str, to: str } } { if !date.valid(from, "date") || !date.valid(to, "date") { reply 400 "Give dates as YYYY-MM-DD" } `${date.days_between(from, to)} days`}From 2026-11-02 to 2026-11-13 the answer is 11 days; to=next week gets 400 Give dates as YYYY-MM-DD. A form without to at all does not match the pattern, and gets
400 bad request: no route pattern matches this request before the route runs.
See also
date.parse, date.of, date.parts, date.date_in, type_of
Thread 0 posts
On date.valid(): questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.
Edit this page on GitHub · every example's output was made by running it (tools/refcheck.mjs) · questions on Discord or r/quillo