Time and Duration Utilities#
OpenDAL centralizes all timestamp and duration handling in core/src/raw/time.rs . This module provides a Timestamp wrapper type and re-exports Instant, SystemTime, and Duration in a platform-aware way, ensuring the rest of the codebase never imports std::time directly or references the underlying time library.
The module reached its current form through three migrations: chrono → jiff (Oct 2025, breaking), jiff → Timestamp wrapper (Oct 2025, abstraction), and wasm32 support via the web-time crate (Dec 2025, extended Apr 2026).
core/src/raw/time.rs — The Centralized Time Module#
Entry point: core/src/raw/time.rs (introduced in PR #6650), exported via core/src/raw/mod.rs.
Timestamp wrapper#
Timestamp wraps jiff::Timestamp and is the canonical timestamp type across OpenDAL. It is exported as opendal::raw::Timestamp.
Key methods :
| Method | Description |
|---|---|
Timestamp::now() | Current UTC time |
Timestamp::from_millisecond(ms: i64) | Construct from Unix milliseconds |
Timestamp::from_second(s: i64) | Construct from Unix seconds |
Timestamp::as_millisecond() | Milliseconds since Unix epoch |
Timestamp::format_http_date() | RFC 9110 HTTP date string (for If-Modified-Since etc.) |
Timestamp::format_rfc3339() | RFC 3339 string |
Timestamp::format_iso8601() | ISO 8601 string |
Conversion traits implemented: From, TryFrom, FromStr. Parsing via str.parse::<Timestamp>() replaces the old parse_datetime_from_rfc3339() helper .
Public surface#
Metadata::last_modified() returns Option<Timestamp> . Read/write/stat options also use Timestamp for if_modified_since / if_unmodified_since fields.
Platform-aware Instant / SystemTime / Duration#
The module also re-exports Instant, SystemTime, and Duration so consuming code never imports std::time directly :
// wasm32-unknown-unknown
pub use web_time::{Duration, Instant, SystemTime};
// all other targets
pub use std::time::{Duration, Instant, SystemTime};
All layers (retry, timeout, metrics, tail-cut) and services import these types via crate::raw::* instead of std::time .
wasm32 Cross-Platform Support#
std::time::Instant and std::time::SystemTime do not exist in browser WASM environments. PR #6852 resolved this by making time.rs the single gating point: re-exports switch to the web-time crate for wasm32 targets .
PR #7360 subsequently narrowed the gate from cfg(target_arch = "wasm32") to cfg(all(target_arch = "wasm32", target_os = "unknown")), restricting web-time to browser WASM (wasm32-unknown-unknown) only and leaving WASI and other wasm targets unaffected . The web-time dependency is declared under [target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] in core/Cargo.toml .
Timestamp conversions to/from SystemTime use web_time::SystemTimeExt::{from_std, to_std} on wasm32-unknown-unknown, and direct std::time::SystemTime conversions everywhere else .
Migration History#
| Date | PR | Change |
|---|---|---|
| Pre-Oct 2025 | — | core/src/raw/chrono_util.rs with chrono 0.4.x; public API exposed DateTime<Utc> |
| Oct 10, 2025 | #6643 | Breaking: replaced chrono with jiff across 103 files; intermediate jiff_util.rs module |
| Oct 14, 2025 | #6650 | Introduced Timestamp wrapper in time.rs; removed jiff_util.rs; Metadata::last_modified() now returns Option<Timestamp> |
| Dec 1, 2025 | #6852 | Added web-time re-exports for Instant/SystemTime on wasm32; removes all direct std::time imports across layers and services |
| Apr 8, 2026 | #7360 | Narrowed wasm32 gate to wasm32-unknown-unknown only, fixing unintended WASI breakage |
Why jiff over chrono?#
PR #6643 described the migration as replacing the legacy chrono crate with the newer jiff. The Timestamp wrapper was added in PR #6650 immediately afterward to prevent jiff::Timestamp from leaking into the public API, keeping the underlying library swappable without further breaking changes.
Language Binding Strategy#
Each language binding converts Timestamp at its own boundary rather than depending on jiff directly :
- C: calls
as_millisecond()for an integer representation - Java: uses
Timestamp::from_second(s)andinto_inner().as_second()/subsec_nanosecond()forjava.time.Instantconstruction - Node.js: parses
if_modified_since/if_unmodified_sinceviastr.parse::<Timestamp>() - Python: a custom PyO3 wrapper implements
IntoPyObject/FromPyObjectfor automaticdatetime↔Timestampconversion; the core crate has no PyO3 dependency