rust-postgres-interval

A native Rust type for PostgreSQL's interval column, with parsing and formatting for ISO 8601, SQL, and Postgres verbose interval strings.

Library
Cargo
v0.6.0
9stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
37/100Needs Attention
Development Activity36
Maintenance36
Community16
Maturity60
Momentum0

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
71/100Good
Architecture78
Code Quality80
Innovation55
Learning Curve70

pg_interval gives Rust code a dedicated Interval type that mirrors PostgreSQL’s internal representation of the interval column type as months, days, and microseconds. Rather than forcing developers to approximate intervals with chrono::Duration or hand-roll wire-format encoding, the crate models the exact three-component structure Postgres uses internally, so round-tripping values through the database preserves their calendar semantics (a month is not always 30 days) instead of collapsing everything into a fixed-length duration.

Beyond the core type, the crate ships parsers and formatters for four distinct interval string representations — ISO 8601 (P1Y1M1DT1H), SQL standard, plain Postgres, and Postgres verbose (@ 1 hour ago) — plus optional FromSql/ToSql implementations behind a postgres feature flag for direct binary-protocol integration with the postgres and tokio-postgres crates, and lossy conversions to and from both chrono::Duration and std::time::Duration.

What You Get

  • An Interval struct with months, days, and microseconds fields matching Postgres’s internal interval representation exactly
  • Parsers for ISO 8601, SQL standard, Postgres, and Postgres verbose (@ ... ago) interval string formats
  • Matching formatters (to_iso_8601, to_sql, to_postgres, to_postgres_verbose) to serialize an Interval back to any of those formats
  • Optional FromSql/ToSql trait implementations (behind the postgres feature) for direct binary encoding/decoding with the postgres and tokio-postgres crates
  • Lossy conversion helpers to and from chrono::Duration and std::time::Duration, including overflow detection that returns None instead of panicking
  • Operator overloads (Add/Sub) for combining Interval values

Common Use Cases

  • Reading and writing interval columns from a Postgres database via postgres or tokio-postgres without lossy conversion to a fixed-duration type
  • Parsing user-supplied or config-file interval strings (e.g. 1 years 1 months 1 days 1 hours) into a typed value for scheduling or billing logic
  • Serializing computed durations back into Postgres-compatible interval strings for use in raw SQL or migrations
  • Converting between application-level chrono/std::time durations and the calendar-aware interval representation Postgres expects
  • Building ORMs or query builders that need first-class interval support instead of falling back to strings

Under The Hood

Architecture The crate is organized around a single core Interval struct (src/pg_interval.rs) holding months/days/microseconds, with all format-specific logic factored into parallel interval_parse and interval_fmt modules, each containing one submodule per supported format (iso_8601, sql, postgres). An interval_norm module handles the shared normalization step (converting the raw fields into years/months/days/hours/minutes/seconds/microseconds) that both the ISO 8601 and Postgres-verbose formatters build on, and pg_interval_add/pg_interval_sub isolate the Add/Sub operator implementations from the core type definition. The optional integrations module (feature-gated behind postgres) is cleanly separated from the parsing/formatting core, so consumers who only need the in-memory type and string conversions don’t pull in postgres-types or bytes at all — a clear symmetry between parse and format responsibilities that keeps each format’s logic self-contained and easy to extend.

Tech Stack Built on Rust 2024 edition with a deliberately small dependency surface: chrono for Duration interop, bytes for the Buf/BufMut traits used in binary encode/decode, and postgres-types as an optional dependency gated behind the default-on postgres feature for FromSql/ToSql trait implementations against Postgres’s INTERVAL wire type. The crate builds with plain cargo build/cargo test, and CI (GitHub Actions, running inside a rust:alpine container) runs cargo fmt --check, cargo clippy -- -D warnings, and cargo test on every push and PR, then publishes to crates.io automatically on version tags.

Code Quality Each module carries its own #[cfg(test)] mod tests block with focused unit tests covering both typical values and edge cases (negative intervals, overflow, sub-microsecond truncation), and CI enforces clippy -D warnings plus rustfmt --check, so the codebase stays lint-clean and consistently formatted by construction. Fallible operations use a dedicated ParseError type and Result/Option returns rather than panics — arithmetic that could overflow (e.g. from_std_duration on very large durations) explicitly uses checked_mul/checked_add and returns None on overflow instead of wrapping or panicking. Naming is consistent snake_case throughout, and the postgres-feature integration is isolated so it doesn’t leak into the core type’s test surface.

What Makes It Unique Unlike generic duration types that flatten everything into a single elapsed-time value, pg_interval preserves the exact three-field structure (months, days, microseconds) Postgres uses internally, which matters because calendar arithmetic is not linear — “1 month” isn’t a fixed number of days. Supporting round-trip parsing and formatting across four distinct textual interval representations (ISO 8601, SQL, Postgres, and Postgres verbose) in one crate, alongside direct binary wire-format support for the postgres driver, makes it a purpose-built bridge between Rust’s duration types and Postgres’s interval semantics rather than a general-purpose duration library repurposed for the job.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search