Expand description
Convenience routines for serializing SignedDuration
values.
These convenience routines exist because the Serialize
implementation for
SignedDuration
always uses the ISO 8601 duration format. These routines
provide a way to use the “friendly” format.
Only serialization routines are provided because a SignedDuration
’s
Deserialize
implementation automatically handles both the ISO 8601
duration format and the “friendly” format.
§Advice
The Serialize
implementation uses ISO 8601 because it is a widely
accepted interchange format for communicating durations. If you need to
inter-operate with other systems, it is almost certainly the correct
choice.
The “friendly” format does not adhere to any universal specified format.
However, it is perhaps easier to read. Beyond that, its utility for
SignedDuration
is somewhat less compared to Span
, since
for Span
, the friendly format preserves all components of the Span
faithfully. But a SignedDuration
is just a 96-bit integer of nanoseconds,
so there are no individual components to preserve. Still, even with a
SignedDuration
, you might prefer the friendly format.
§Available routines
A SpanPrinter
has a lot of different
configuration options. The convenience routines provided by this module
only cover a small space of those options since it isn’t feasible to
provide a convenience routine for every possible set of configuration
options.
While more convenience routines could be added (please file an issue), only
the most common or popular such routines can be feasibly added. So in the
case where a convenience routine isn’t available for the configuration you
want, you can very easily define your own serialize_with
routine.
The recommended approach is to define a function and a type that
implements the std::fmt::Display
trait. This way, if a serializer can
efficiently support Display
implementations, then an allocation can be
avoided.
use jiff::SignedDuration;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
struct Data {
#[serde(serialize_with = "custom_friendly")]
duration: SignedDuration,
}
let json = r#"{"duration": "36 hours 1100ms"}"#;
let got: Data = serde_json::from_str(&json).unwrap();
assert_eq!(got.duration, SignedDuration::new(36 * 60 * 60 + 1, 100_000_000));
let expected = r#"{"duration":"36:00:01.100"}"#;
assert_eq!(serde_json::to_string(&got).unwrap(), expected);
fn custom_friendly<S: serde::Serializer>(
duration: &SignedDuration,
se: S,
) -> Result<S::Ok, S::Error> {
struct Custom<'a>(&'a SignedDuration);
impl<'a> std::fmt::Display for Custom<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use jiff::fmt::{friendly::SpanPrinter, StdFmtWrite};
static PRINTER: SpanPrinter = SpanPrinter::new()
.hours_minutes_seconds(true)
.precision(Some(3));
PRINTER
.print_duration(self.0, StdFmtWrite(f))
.map_err(|_| core::fmt::Error)
}
}
se.collect_str(&Custom(duration))
}
Recall from above that you only need a custom serialization routine for this. Namely, deserialization automatically supports parsing all configuration options for serialization unconditionally.
Modules§
- Serialize a
Span
in thefriendly
duration format.