Skip to main content
DuckDB’s temporal types map to DuckValue variants whose inner Rust type depends on the chrono feature (on by default). With chrono, you get chrono::NaiveDate / NaiveTime / NaiveDateTime / DateTime<Utc> / Duration. Without it, you get the crate’s native DuckDate / DuckTime / std::time::SystemTime / std::time::Duration.

The variants

The four TIMESTAMP* variants are distinct DuckDB types with different precisions (seconds, milliseconds, microseconds, nanoseconds). They all map to NaiveDateTime under chrono, but they are not interchangeable: a value keeps its originating column type when written back, so a read→write round trip preserves precision.

Timezone-aware values

TIMESTAMPTZ (TimestampTz) is a UTC instant — chrono::DateTime<Utc>. DuckDB stores TIMESTAMP and TIMESTAMPTZ in the same microsecond wire format but treats them as distinct logical types, so the variant you get back tells you which column type it came from. TIME_TZ (TimeTz) is a time-of-day with an offset; it uses the crate’s TimeTz wrapper even under chrono (there is no exact chrono counterpart).

Intervals

INTERVAL (Interval) carries months, days, and microseconds. Under chrono it maps to chrono::Duration; without chrono, to std::time::Duration.
A DuckDB INTERVAL has three independent components (months, days, micros) because months and days are not fixed-length. Converting to a single Duration collapses that structure — round-trip a value through its original column type rather than reconstructing it from a Duration when the month/day split matters.

±infinity — TemporalInfinity

DuckDB reserves the extreme sentinels of DATE/TIMESTAMP for +infinity / -infinity, which no finite chrono value can represent. Rather than lose them, such a value reads back as:
This variant is feature-independent (no chrono type involved). It is tagged with the temporal family (TemporalKind) and direction (Sign) so it round-trips losslessly into the same column type. TemporalKind::type_id() gives the DuckDB duckdb_type id it belongs to.
DuckDB uses ±INT64_MAX for timestamp infinity (-infinity == i64::MIN + 1), not i64::MIN. You never deal with the raw sentinel — read the TemporalInfinity variant instead.

Decomposing timestamps

For calendar/clock arithmetic without pulling in chrono, the crate root re-exports DuckDB-backed helpers:
Both use DuckDB’s own normalisation (duckdb_from_timestamp / duckdb_to_timestamp).

Choosing chrono vs native

chrono (default)

Rich date/time arithmetic, formatting, and ecosystem interop. Keep it on unless you must trim dependencies.

no-chrono (native)

DuckDate / DuckTime / SystemTime with zero extra dependencies — for embedded or size-sensitive builds. Disable chrono in Cargo.

See also