e string has a `Z` (Zulu) offset. It's an error since interpreting such strings as civil time is usually a bug. * In all cases, the `T` designator separating the date and time may be an ASCII space instead. The complete datetime format supported is described by the [Temporal ISO 8601 grammar]. # Span format To a first approximation, the span format supported roughly corresponds to this regular expression: ```text P(\d+y)?(\d+m)?(\d+w)?(\d+d)?(T(\d+h)?(\d+m)?(\d+s)?)? ``` But there are some details not easily captured by a simple regular expression: * At least one unit must be specified. To write a zero span, specify `0` for any unit. For example, `P0d` and `PT0s` are equivalent. * The format is case insensitive. The printer will by default capitalize all designators, but the unit designators can be configured to use lowercase with [`SpanPrinter::lowercase`]. For example, `P3y1m10dT5h` instead of `P3Y1M10DT5H`. You might prefer lowercase since you may find it easier to read. However, it is an extension to ISO 8601 and isn't as broadly supported. * Hours, minutes or seconds may be fractional. And the only units that may be fractional are the lowest units. * A span like `P99999999999y` is invalid because it exceeds the allowable range of time representable by a [`Span`]. This is, roughly speaking, a subset of what [ISO 8601] specifies. It isn't strictly speaking a subset since Jiff (like Temporal) permits week units to be mixed with other units. Here are some examples: ``` use jiff::{Span, ToSpan}; let spans = [ ("P40D", 40.days()), ("P1y1d", 1.year().days(1)), ("P3dT4h59m", 3.days().hours(4).minutes(59)), ("PT2H30M", 2.hours().minutes(30)), ("P1m", 1.month()), ("P1w", 1.week()), ("P1w4d", 1.week().days(4)), ("PT1m", 1.minute()), ("PT0.0021s", 2.milliseconds().microseconds(100)), ("PT0s", 0.seconds()), ("P0d", 0.seconds()), ( "P1y1m1dT1h1m1.1s", 1.year().months(1).days(1).hours(1).minutes(1).seconds(1).milliseconds(100), ), ]; for (string, span) in spans { let parsed: Span = string.parse()?; assert_eq!( span.fieldwise(), parsed.fieldwise(), "result of parsing {string:?}", ); } # Ok::<(), Box>(()) ``` One can also parse ISO 8601 durations into a [`SignedDuration`], but units are limited to hours or smaller: ``` use jiff::SignedDuration; let durations = [ ("PT2H30M", SignedDuration::from_secs(2 * 60 * 60 + 30 * 60)), ("PT2.5h", SignedDuration::from_secs(2 * 60 * 60 + 30 * 60)), ("PT1m", SignedDuration::from_mins(1)), ("PT1.5m", SignedDuration::from_secs(90)), ("PT0.0021s", SignedDuration::new(0, 2_100_000)), ("PT0s", SignedDuration::ZERO), ("PT0.000000001s", SignedDuration::from_nanos(1)), ]; for (string, duration) in durations { let parsed: SignedDuration = string.parse()?; assert_eq!(duration, parsed, "result of parsing {string:?}"); } # Ok::<(), Box>(()) ``` The complete span format supported is described by the [Temporal ISO 8601 grammar]. # Differences with Temporal Jiff implements Temporal's grammar pretty closely, but there are a few differences at the time of writing. It is a specific goal that all differences should be rooted in what Jiff itself supports, and not in the grammar itself. * The maximum UTC offset value expressible is `25:59:59` in Jiff, where as in Temporal it's `23:59:59.999999999`. Jiff supports a slightly bigger maximum to account for all valid values of POSIX time zone strings. Jiff also lacks nanosecond precision for UTC offsets, as it's not clear how useful that is in practice. * Jiff doesn't support a datetime range as big as Temporal. For example, in Temporal, `+202024-06-14T17:30[America/New_York]` is valid. But in Jiff, since the maximum supported year is `9999`, parsing will fail. Jiff's datetime range may be expanded in the future, but it is a non-goal to match Temporal's range precisely. * Jiff doesn't support RFC 9557 calendar annotations because Jiff only supports the Gregorian calendar. There is some more [background on Temporal's format] available. [Temporal ISO 8601 grammar]: https://tc39.es/proposal-temporal/#sec-temporal-iso8601grammar [RFC 3339]: https://www.rfc-editor.org/rfc/rfc3339 [RFC 9557]: https://www.rfc-editor.org/rfc/rfc9557.html [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html [background on Temporal's format]: https://github.com/tc39/proposal-temporal/issues/2843