Skip to content

Date, DateTime, Instant and Duration, and the time module (HQL-0041 part 1) - #12

Merged
ewiger merged 6 commits into
mainfrom
feat/time
Nov 12, 2026
Merged

ewiger merged 6 commits into
mainfrom
feat/time

Conversation

@ewiger

@ewiger ewiger commented Nov 12, 2026

Copy link
Copy Markdown
Owner

Implements part 1 of HQL-0041, the time module (issue 0064).

What it adds

  • Four time scalars in core: Date, DateTime, Instant and Duration, on jiff.
    • Built from ISO 8601 text, Date("2026-10-24"), or from named parts, Date(year = 2026, month = 2, day = 28).
    • Text that does not parse, or a part out of range, is an evaluation error.
    • Eq and Ord for each, so ==, <, sort, max, Set and group compare by time; Add and Sub for Duration alone.
  • The time module (import time):
    • zones, where a reading in a DST gap moves forward and one in an overlap is the earlier instant
    • parts: year, weekday, iso_week and the rest
    • calendar arithmetic: add_months clamps to the month's last day
    • truncate to Week, Month, Quarter and Year, and dates(start, end)
    • fmt and parse_* with strftime patterns, and to_* conversions that give none
    • the evaluation clock: now(), today() and local_zone(), read once per evaluation; --now and --zone fix it
  • Data:
    • Every format writes a time value as its ISO 8601 text.
    • A declared time field reads its text; an undeclared date-looking string stays a String.
    • PostgreSQL DATE, TIMESTAMP and TIMESTAMPTZ, and Spark DATE, TIMESTAMP_NTZ and TIMESTAMP, map to Date, DateTime and Instant.
    • SQLite keeps a time value as its ISO text.

Language changes to review

  • Calls with no positional argument. A declaration with no positional parameter takes Unit as its input, and a call writes none. now() and the named-part constructors need this. Until now fn now() was refused on purpose; the contract test now pins the new behaviour.
  • Spelling hints. A hint prefers prelude names, and offers a name another module provides only when it is one edit away. Without this, an unbound pages was answered with dates. Every hint that existed before is unchanged.

Departures from HQL-0041 part 1

The spec now states each of these.

  • The abstract unit type is TimeUnit; Unit is core's unit type.
  • No Utc value, because a module declares no values. A form without the zone reads in UTC; otherwise write Zone("UTC").
  • Zone is not Orderable.
  • abs over Duration waits until a second module can declare abs beside math.

Open

Listed in issue 0064.

  • The PostgreSQL and Spark mappings have not run against a server.
  • Spark writes a TIMESTAMP with no offset; it is read as UTC.
  • hql --version does not yet name the zone database it carries.
  • An existing bug: g.key is refused inside group over a record type the program declares.

Tests

  • tests/time.rs: 16 integration tests.
  • Unit tests in src/time.rs.
  • examples/time/: 12 corpus cases.
  • A new Learn page, "Date and time", each program run against the binary.
  • Reference pages regenerated.
  • cargo test (675 passed), cargo clippy --all-targets -- -D warnings and mkdocs build --strict are clean after merging main.

The four time scalars of HQL-0041 part 1, on jiff: constructors from
ISO 8601 text and from parts in core, Eq and Ord for each, Add and Sub
for Duration, and the time module's zones, parts, calendar arithmetic,
truncation, strftime patterns and evaluation clock (--now, --zone).

A declared time field reads its ISO text from JSON, YAML and CSV, and
every format writes a time value as that text. SQL DATE, TIMESTAMP and
TIMESTAMPTZ columns map to Date, DateTime and Instant.

A declaration with no positional parameter takes Unit as its input, so
now() and Date(year = ..., month = ..., day = ...) are calls. A
spelling hint prefers prelude names and offers an imported-only name
for a near miss alone.
@ewiger
ewiger merged commit d61efef into main Nov 12, 2026
5 checks passed
@ewiger
ewiger deleted the feat/time branch November 12, 2026 23:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant