pub struct Timestamp(/* private fields */);Expand description
Microseconds elapsed since the Unix epoch (January 1, 1970 00:00:00 UTC).
§The unit is microseconds (#254)
Before v0.4.0 this held whole seconds. It now holds microseconds, and
microseconds are the one canonical on-disk unit regardless of a field’s
declared timestamp(s|ms|us) precision — a timestamp(ms) field simply
stores millisecond-aligned microsecond values. Storing each field in its own
unit would make a Timestamp value unit-ambiguous at runtime, which is only
resolvable with a fatter value (a layout change) or a Timestamp<const U>
(generated signature churn everywhere).
i64 microseconds spans ±292,277 years, which is why microseconds rather
than nanoseconds are the floor: nanoseconds would cap the type at 1678–2262,
putting a birth date or a long-dated bond maturity out of range.
§The wire form is RFC 3339, not a number
[Display], FromStr and serde all speak RFC 3339 —
one rendering everywhere, so the create handler’s id.to_string() and a REST
path parameter’s parse() agree with no generated codec. Output is fixed
(exactly 6 fractional digits, always Z, including for a timestamp(s)
field: Display is on the type and cannot see a field’s precision); input is
lenient (fewer or more fractional digits, lowercase t/z, any numeric
offset).
A number would have been a silent break — a client reading seconds would start reading microseconds and display 1970 forever. A client expecting a number and receiving a string fails immediately and visibly.
§Range
The rendering has no failure mode, so the type’s range is RFC 3339’s year
range 0000–9999 (is_rfc3339_representable),
enforced by the generated write path rather than here. Values outside it
still render and re-parse losslessly (with an extended year), so no data is
trapped; they are simply refused at the boundary.
§Examples
use forgedb_types::Timestamp;
let ts = Timestamp::from_micros(1_775_000_000_123_456);
assert_eq!(ts.to_rfc3339(), "2026-03-31T23:33:20.123456Z");
assert_eq!(ts.as_micros(), 1_775_000_000_123_456);
assert_eq!("2026-03-31T23:33:20.123456Z".parse::<Timestamp>().unwrap(), ts);Implementations§
Source§impl Timestamp
impl Timestamp
Sourcepub fn from_micros(micros: i64) -> Self
pub fn from_micros(micros: i64) -> Self
Creates a timestamp from microseconds since the Unix epoch.
use forgedb_types::Timestamp;
assert_eq!(Timestamp::from_micros(1_234_567_890).as_micros(), 1_234_567_890);Sourcepub fn now() -> Self
pub fn now() -> Self
Returns the current timestamp, in microseconds.
use forgedb_types::Timestamp;
assert!(Timestamp::now().as_micros() > 1_577_836_800_000_000);Sourcepub fn to_rfc3339(&self) -> String
pub fn to_rfc3339(&self) -> String
Renders the instant as RFC 3339: exactly 6 fractional digits, always Z.
Total by construction — this is what [Display] calls, and Display
cannot fail. A value outside RFC 3339’s year range renders with an
extended year (+10000-… / -0001-…) so the round-trip stays lossless;
such a value is refused at the write boundary instead, via
is_rfc3339_representable.
Sourcepub fn from_rfc3339(s: &str) -> Result<Self, TimestampParseError>
pub fn from_rfc3339(s: &str) -> Result<Self, TimestampParseError>
Parses an RFC 3339 instant. Lenient about everything the rendering fixes:
any number of fractional digits (sub-microsecond digits are truncated,
since the stored unit is the finest thing the value can mean), a lowercase
t/z separator, and any numeric offset (±HH:MM / ±HHMM / ±HH).
An offset is applied, not recorded: the stored value is an instant.
Sourcepub fn floor_to_micros(&self, quantum_us: i64) -> Self
pub fn floor_to_micros(&self, quantum_us: i64) -> Self
Floors the value to a multiple of quantum_us (res 5): a user-supplied
value finer than a field’s declared precision is recorded coarsely
rather than refused, because rejecting a valid measurement for being too
precise only exports the flooring to every client.
Floor, never truncate toward zero. Truncation rounds a pre-epoch value
forward in time (-0.5s → 0s), which breaks monotonicity across 1970
— two instants an hour apart could quantize to the same value from
opposite sides, or swap order.
A quantum_us of 0 or less is the identity (there is nothing to floor
to), so this never divides by zero on a caller’s behalf.
Sourcepub fn is_rfc3339_representable(&self) -> bool
pub fn is_rfc3339_representable(&self) -> bool
Whether the value renders inside RFC 3339’s year range (0000–9999).
i64 microseconds spans ±292,277 years, so the wire form is narrower than
the storage type. Since [Display] cannot fail, the narrowing is enforced
as a validity constraint at the write boundary (a 422) rather than as a
rendering error — and this predicate is what the generated write path
checks.
Trait Implementations§
impl Copy for Timestamp
Source§impl<'de> Deserialize<'de> for Timestamp
impl<'de> Deserialize<'de> for Timestamp
Source§fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error>
fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error>
impl Eq for Timestamp
Source§impl From<i64> for Timestamp
impl From<i64> for Timestamp
Source§fn from(micros: i64) -> Self
fn from(micros: i64) -> Self
Microseconds since the epoch, matching Timestamp::from_micros.