Rat docs

Date

Five members on the date namespace. Timestamps are epoch seconds (a regular int) — there's no separate Date kind, so dates compose with arithmetic, JSON, and storage out of the box. Layouts use a small token alphabet (YYYY, MM, DD, HH, mm, ss) instead of Go's reference-time format, so most developers get the spelling right on the first try. All times are UTC in v1.

date.now — current epoch seconds

Reads the system clock; same call shape server and client

date.now() returns the current Unix timestamp as an integer. Server-tier calls read the host clock at render time; client-tier calls read the browser clock when the handler fires.

<p> [date.now()]
<button on_click[log[date.now()]]> log browser date.now()
Result

1780932028

date.parse — ISO 8601 and common variants

Falls back through RFC3339, space-separated, plain date forms

date.parse(s) tries a small set of layouts in order: RFC3339 with nanoseconds, RFC3339, YYYY-MM-DD HH:mm:ss, YYYY-MM-DD, YYYY/MM/DD, MM/DD/YYYY. Returns the epoch seconds; an unparseable input is an error (caller can use a guard to default).

<p> [date.parse('2026-06-07T12:34:56Z')]
<p> [date.parse('2026-06-07')]
Result

ISO datetime → 1780835696

Date only → 1780790400

date.format — render with a token layout

YYYY MM DD HH mm ss; everything else is literal text

date.format(epoch, layout) renders the timestamp using the token layout. Tokens are two- or four-character so they never collide with English words — "Today is YYYY!" formats cleanly without escapes.

<p> [date.format(date.parse('2026-06-07T12:34:56Z'), 'YYYY-MM-DD HH:mm:ss')]
<p> [date.format(date.parse('2026-06-07T12:34:56Z'), 'DD/MM/YYYY')]
Result

2026-06-07 12:34:56

07/06/2026

date.add — shift by N units

Calendar-aware for month / year boundaries

date.add(epoch, unit, n) returns a new epoch shifted by n units. Accepted units: s, m, h, d, w, M, y (and their long names). Month and year arithmetic is calendar-aware — Jan 31 + 1M lands on Feb 28/29, not March 3.

<p> [date.format(date.add(date.parse('2026-01-31'), 'M', 1), 'YYYY-MM-DD')]
<p> [date.format(date.add(date.parse('2026-06-07'), 'd', 7), 'YYYY-MM-DD')]
Result

Jan 31 + 1 month → 2026-02-28

Jun 7 + 7 days → 2026-06-14

date.diff — whole-unit difference

Returns int; sign is a - b

date.diff(a, b, unit) returns the number of whole units between two epochs. The result is truncated toward zero — six full days plus 23 hours diffs as 6. Month and year diffs are calendar-aware: they only count "full" periods.

<p> [date.diff(date.parse('2026-06-07'), date.parse('2026-06-01'), 'd')]
Result

Jun 7 − Jun 1 in days → 6

Composing — relative time formatter

"3 days ago" from any past timestamp

Combine date.now() with date.diff for a simple "X ago" renderer. Same pattern works for "starts in Y" by flipping the diff arguments.

> server
posted_at: date.parse('2026-06-01T08:00:00Z')

> since[posted, unit] >> date.diff(date.now(), posted, unit)

> page
<p> [since(posted_at, 'd')] days ago
<p> [since(posted_at, 'h')] hours ago

Next: Regex — RE2 patterns, match objects, and the same backref syntax server- and client-side.