e pattern language is a simple sequence of conversion specifiers interspersed by literals and arbitrary whitespace. This means that you sometimes need delimiters or spaces between components. For example, this is fine: ``` use jiff::fmt::strtime; let date = strtime::parse("%Y%m%d", "20240715")?.to_date()?; assert_eq!(date.to_string(), "2024-07-15"); # Ok::<(), Box>(()) ``` But this is ambiguous (is the year `999` or `9990`?): ``` use jiff::fmt::strtime; assert!(strtime::parse("%Y%m%d", "9990715").is_err()); ``` In this case, since years greedily consume up to 4 digits by default, `9990` is parsed as the year. And since months greedily consume up to 2 digits by default, `71` is parsed as the month, which results in an invalid day. If you expect your datetimes to always use 4 digits for the year, then it might be okay to skip on the delimiters. For example, the year `999` could be written with a leading zero: ``` use jiff::fmt::strtime; let date = strtime::parse("%Y%m%d", "09990715")?.to_date()?; assert_eq!(date.to_string(), "0999-07-15"); // Indeed, the leading zero is written by default when // formatting, since years are padded out to 4 digits // by default: assert_eq!(date.strftime("%Y%m%d").to_string(), "09990715"); # Ok::<(), Box>(()) ``` The main advice here is that these APIs can come in handy for ad hoc tasks that would otherwise be annoying to deal with. For example, I once wrote a tool to extract data from an XML dump of my SMS messages, and one of the date formats used was `Apr 1, 2022 20:46:15`. That doesn't correspond to any standard, and while parsing it with a regex isn't that difficult, it's pretty annoying, especially because of the English abbreviated month name. That's exactly the kind of use case where this module shines. If the formatting machinery in this module isn't flexible enough for your use case and you don't control the format, it is recommended to write a bespoke parser (possibly with regex). It is unlikely that the expressiveness of this formatting machinery will be improved much. (Although it is plausible to add new conversion specifiers.) # Conversion specifications This table lists the complete set of conversion specifiers supported in the format. While most conversion specifiers are supported as is in both parsing and formatting, there are some differences. Where differences occur, they are noted in the table below. When parsing, and whenever a conversion specifier matches an enumeration of strings, the strings are matched without regard to ASCII case. | Specifier | Example | Description | | --------- | ------- | ----------- | | `%%` | `%%` | A literal `%`. | | `%A`, `%a` | `Sunday`, `Sun` | The full and abbreviated weekday, respectively. | | `%B`, `%b`, `%h` | `June`, `Jun`, `Jun` | The full and abbreviated month name, respectively. | | `%C` | `20` | The century of the year. No padding. | | `%c` | `2024 M07 14, Sun 17:31:59` | The date and clock time via [`Custom`]. Supported when formatting only. | | `%D` | `7/14/24` | Equivalent to `%m/%d/%y`. | | `%d`, `%e` | `25`, ` 5` | The day of the month. `%d` is zero-padded, `%e` is space padded. | | `%F` | `2024-07-14` | Equivalent to `%Y-%m-%d`. | | `%f` | `000456` | Fractional seconds, up to nanosecond precision. | | `%.f` | `.000456` | Optional fractional seconds, with dot, up to nanosecond precision. | | `%G` | `2024` | An [ISO 8601 week-based] year. Zero padded to 4 digits. | | `%g` | `24` | A two-digit [ISO 8601 week-based] year. Represents only 1969-2068. Zero padded. | | `%H` | `23` | The hour in a 24 hour clock. Zero padded. | | `%I` | `11` | The hour in a 12 hour clock. Zero padded. | | `%j` | `060` | The day of the year. Range is `1..=366`. Zero padded to 3 digits. | | `%k` | `15` | The hour in a 24 hour clock. Space padded. | | `%l` | ` 3` | The hour in a 12 hour clock. Space padded. | | `%M` | `04` | The minute. Zero padded. | | `%m` | `01` | The month. Zero padded. | | `%N` | `123456000` | Fractional seconds, up to nanosecond precision. Alias for `%9f`. | | `%n` | `\n` | Formats as a newline character. Parses arbitrary whitespace. | | `%P` | `am` | Whether the time is in the AM or PM, lowercase. | | `%p` | `PM` | Whether the time is in the AM or PM, uppercase. | | `%Q` | `America/New_York`, `+0530` | An IANA time zone identifier, or `%z` if one doesn't exist. | | `%:Q` | `America/New_York`, `+05:30` | An IANA time zone identifier, or `%:z` if one doesn't exist. | | `%q` | `4` | The quarter of the year. Supported when formatting only. | | `%R` | `23:30` | Equivalent to `%H:%M`. | | `%r` | `8:30:00 AM` | The 12-hour clock time via [`Custom`]. Supported when formatting only. | | `%S` | `59` | The second. Zero padded. | | `%s` | `1737396540` | A Unix timestamp, in seconds. | | `%T` | `23:30:59` | Equivalent to `%H:%M:%S`. | | `%t` | `\t` | Formats as a tab character. Parses arbitrary whitespace. | | `%U` | `03` | Week number. Week 1 is the first week starting with a Sunday. Zero padded. | | `%u` | `7` | The day of the week beginning with Monday at `1`. | | `%V` | `05` | Week number in the [ISO 8601 week-based] calendar. Zero padded. | | `%W` | `03` | Week number. Week 1 is the first week starting with a Monday. Zero padded. | | `%w` | `0` | The day of the week beginning with Sunday at `0`. | | `%X` | `17:31:59` | The clock time via [`Custom`]. Supported when formatting only. | | `%x` | `2024 M07 14` | The date via [`Custom`]. Supported when formatting only. | | `%Y` | `2024` | A full year, including century. Zero padded to 4 digits. | | `%y` | `24` | A two-digit year. Represents only 1969-2068. Zero padded. | | `%Z` | `EDT` | A time zone abbreviation. Supported when formatting only. | | `%z` | `+0530` | A time zone offset in the format `[+-]HHMM[SS]`. | | `%:z` | `+05:30` | A time zone offset in the format `[+-]HH:MM[:SS]`. | | `%::z` | `+05:30:00` | A time zone offset in the format `[+-]HH:MM:SS`. | | `%:::z` | `-04`, `+05:30` | A time zone offset in the format `[+-]HH:[MM[:SS]]`. | When formatting, the following flags can be inserted immediately after the `%` and before the directive: * `_` - Pad a numeric result to the left with spaces. * `-` - Do not pad a numeric result. * `0` - Pad a numeric result to the left with zeros. * `^` - Use alphabetic uppercase for all relevant strings. * `#` - Swap the case of the result string. This is typically only useful with `%p` or `%Z`, since they are the only conversion specifiers that emit strings entirely in uppercase by default. The above flags override the "default" settings of a specifier. For example, `%_d` pads with spaces instead of zeros, and `%0e` pads with zeros instead of spaces. The exceptions are the locale (`%c`, `%r`, `%X`, `%x`), and time zone (`%z`, `%:z`) specifiers. They are unaffected by any flags. Moreover, any number of decimal digits can be inserted after the (possibly absent) flag and before the directive, so long as the parsed number is less than 256. The number formed by these digits will correspond to the minimum amount of padding (to the left). Note that padding is clamped to a maximum of `20`. The flags and padding amount above may be used when parsing as well. Most settings are ignored during parsing except for padding. For example, if one wanted to parse `003` as the day `3`, then one should use `%03d`. Otherwise, by default, `%d` will only try to consume at most 2 digits. The `%f` and `%.f` flags also support specifying the precision, up to nanoseconds. For example, `%3f` and `%.3f` will both always print a fractional second component to exactly 3 decimal places. When no precision is specified, then `%f` will always emit at least one digit, even if it's zero. But `%.f` will emit the empty string when the fractional component is zero. Otherwise, it will include the leading `.`. For parsing, `%f` does not include the leading dot, but `%.f` does. Note that all of the options above are still parsed for `%f` and `%.f`, but they are all no-ops (except for the padding for `%f`, which is instead interpreted as a precision setting). When using a precision setting, truncation is used. If you need a different rounding mode, you should use higher level APIs like [`Timestamp::round`] or [`Zoned::round`]. # Conditionally unsupported Jiff does not support `%Q` or `%:Q` (IANA time zone identifier) when the `alloc` crate feature is not enabled. This is because a time zone identifier is variable width data. If you have a use case for this, please [detail it in a new issue](https://github.com/BurntSushi/jiff/issues/new). # Unsupported The following things are currently unsupported: * Parsing or formatting fractional seconds in the time time zone offset. * The `%+` conversion specifier is not supported since there doesn't seem to be any consistent definition for it. * With only Jiff, the `%c`, `%r`, `%X` and `%x` locale oriented specifiers use a default "unknown" locale via the [`DefaultCustom`] implementation of the [`Custom`] trait. An example of the default locale format for `%c` is `2024 M07 14, Sun 17:31:59`. One can either switch the POSIX locale via [`PosixCustom`] (e.g., `Sun Jul 14 17:31:59 2024`), or write your own implementation of [`Custom`] powered by [`icu`] and glued together with Jiff via [`jiff-icu`]. * The `E` and `O` locale modifiers are not supported. [`strftime`]: https://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html [`strptime`]: https://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html [ISO 8601 week-based]: https://en.wikipedia.org/wiki/ISO_week_date [`icu`]: https://docs.rs/icu [`jiff-icu`]: https://docs.rs/jiff-icu