 or [`FromStr`](std::str::FromStr) trait
implementations for printing and parsing respectively. This module provides
a "lower level" API for configuring the behavior of printing and parsing,
including the ability to parse from byte strings (i.e., `&[u8]`).

# Date and time format

The specific format supported depends on what kind of type you're trying to
parse into. Here are some examples to give a general idea:

* `02:21:58` parses into a [`civil::Time`].
* `2020-08-21` parses into a [`civil::Date`].
* `2020-08-21T02:21:58` and `2020-08-21 02:21:58` both parse into a
  [`civil::DateTime`].
* `2020-08-21T02:21:58-04` parses into an [`Timestamp`].
* `2020-08-21T02:21:58-04[America/New_York]` parses into a [`Zoned`].

Smaller types can generally be parsed from strings representing a bigger type.
For example, a `civil::Date` can be parsed from `2020-08-21T02:21:58`.

As mentioned above, the datetime format supported by Jiff is a hybrid of the
"best" parts of [RFC 3339], [RFC 9557] and [ISO 8601]. Generally speaking, [RFC
3339] and [RFC 9557] are supported in their entirety, but not all of ISO 8601
is. For example, `2024-06-16T10.5` is a valid ISO 8601 datetime, but isn't
supported by Jiff. (Only fractional seconds are supported.)

Some additional details worth noting:

* Parsing `Zoned` values requires a datetime string with a time zone
annotation like `[America/New_York]` or `[-07:00]`. If you need to parse a
datetime without a time zone annotation (but with an offset), then you should
parse it as an [`Timestamp`]. From there, it can be converted to a `Zoned` via
[`Timestamp::to_zoned`].
* When parsing `Zoned` values, ambiguous datetimes are handled via the
[`DateTimeParser::disambiguation`] configuration. By default, a "compatible"
mode is used where the earlier time is selected in a backward transition, while
the later time is selected in a forward transition.
* When parsing `Zoned` values, conflicts between the offset and the time zone
in the datetime string are handled via the [`DateTimeParser::offset_conflict`]
configuration. By default, any inconsistency between the offset and the time
zone results in a parse error.
* When parsing civil types like `civil::DateTime`, it's always an error if the
datetime 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<dyn std::error::Error>>(())
```

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<dyn std::error::Error>>(())
```

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
