Civil dates over unix time on the Date class: from-unix / to-unix / now / ->iso / leap-year?.
(Date now) needs x/sys/posix loaded for (Sys now); everything else is pure. Timezone-aware work happens at the boundary – this module is UTC by design.
DateCivil dates over unix time: pure integer math, proleptic Gregorian, UTC; local is UTC moved by the zone the C library reports.
A date is an alist ((year . Y) (month . M) (day . D) (hour . H) (minute . MIN) (second . S) (wday . W)); month 1-12, wday 0-6 with 0 = Sunday. (Date local secs) adds offset and zone. No timezone database, no locale.
(Date from-unix secs)Split unix seconds into a civil date-time alist (UTC).
Parameters:
INTEGER — Seconds since the unix epoch (negative = pre-1970)Returns: ALIST — ((year . Y) (month . M) (day . D) (hour . H) (minute . MIN) (second . S) (wday . W))
Examples:
(Assoc get 'wday (Date from-unix 0)) => 4
(Assoc get 'day (Date from-unix 86399)) => 1
(Assoc get 'year (Date from-unix -86400)) => 1969(Date to-unix date)Civil date-time alist (UTC) back to unix seconds – the inverse of from-unix.
Parameters:
ALIST — Date alist; hour/minute/second default to 0 when absentReturns: INTEGER — Seconds since the unix epoch
Examples:
(Date to-unix '((year . 1970) (month . 1) (day . 1))) => 0
(Date to-unix (Date from-unix 1234567890)) => 1234567890(Date now)The current wall-clock civil date-time (UTC), from (Sys now).
Returns: ALIST — Date alist for now
(Date local secs)Split unix seconds into a civil date-time alist in local time: from-unix’s fields for secs moved by the zone’s offset, plus offset (seconds east of UTC) and zone (its abbreviation). The zone is the C library’s, through (Sys zone); the calendar is this class’s.
Parameters:
INTEGER — Seconds since the unix epochReturns: ALIST — ((year . Y) (month . M) (day . D) (hour . H) (minute . MIN) (second . S) (wday . W) (offset . SECONDS-EAST) (zone . NAME))
(Date local->unix date)Civil date-time alist in local time back to unix seconds – the inverse of local, as to-unix is of from-unix. The C library resolves it, through (Sys local->unix): a time a daylight change skips or repeats lands where mktime puts it.
Parameters:
ALIST — Date alist in local time; hour/minute/second default to 0 when absentReturns: INTEGER — Seconds since the unix epoch
(Date ->iso date)Format a date alist as an ISO-8601 UTC timestamp.
Parameters:
ALIST — Date alistReturns: STRING — “YYYY-MM-DDTHH:MM:SSZ”
Examples:
(Date ->iso (Date from-unix 1234567890)) => "2009-02-13T23:31:30Z"(Date from-iso s)Parse an ISO-8601 UTC timestamp back to a date alist – the inverse of ->iso (#364). Strict per #61: wrong structure, out-of-range fields, or a nonexistent civil date (Feb 30) raises a label ‘value. A bare date reads as midnight.
Parameters:
STRING — ISO-8601 UTC timestamp: “YYYY-MM-DDTHH:MM:SSZ” or the bare date “YYYY-MM-DD”Returns: ALIST — Canonical date alist (wday included), as from-unix builds
Examples:
(Date from-iso "2009-02-13T23:31:30Z") => (('year . 2009) ('month . 2) ('day . 13) ('hour . 23) ('minute . 31) ('second . 30) ('wday . 5))
(Assoc get 'hour (Date from-iso "1970-01-01")) => 0
(Date to-unix (Date from-iso "2009-02-13T23:31:30Z")) => 1234567890(Date leap-year? y)Gregorian leap-year test.
Parameters:
INTEGER — YearReturns: BOOL — True for leap years
Examples:
(list (Date leap-year? 2024) (Date leap-year? 1900) (Date leap-year? 2000)) => (#t #f #t)