Format description

A format description is the manner in which the time crate knows how a value should be formatted and parsed.

While it is possible to construct a format description manually, this is generally not recommended, as it is more tedious and less readable than the alternative. Unless you are doing this, you will likely never need to know anything about FormatItem other than that it is produced by the format_description! macro or any of the various parsing methods.

If the format description is statically known, you should use the format_description! macro. This is identical to the format_description::parse method, but runs at compile-time, throwing an error if the format description is invalid. If you do not know the desired format statically (such as if you are using one provided by the user), you should use the format_description::parse_owned method (or similar method in the format_description module), which is fallible.

Format descriptions have components and literals. Literals are formatted and parsed as-is. Components are the mechanism by which values (such as a Time or Date) are dynamically formatted and parsed. They have significant flexibility, allowing for differences in padding, variable widths for subsecond values, numerical or textual representations, and more.

Either a literal or a component may be present at the start of the format description. It is valid to have both consecutive literals and consecutive components. Components must be fully contained between brackets with optional whitespace. Escaping behavior varies by version, and is described below.

Modifiers

Many of the components have optional modifiers to change how it is formatted or parsed.

The padding modifier, such as used on the hour and month components can be padded with space, zero or none. In the case of none leading zeros are still accepted during parsing.

Traits

A format description is not a single type; it is instead represented by two internal traits (one for formatting and one for parsing) that are implemented by a number of types. Currently, all types that implement one trait also implement the other, but this is not guaranteed.

The following types currently implement both the Formattable and Parsable traits:

  • FormatItem<'_>
  • [FormatItem<'_>]
  • T where <T as Deref>::Target: Formattable (or Parsable)
  • All well known formats

Versioning

There are multiple versions of the format description syntax in time. Similar to Rust editions, all versions are and will remain supported indefinitely. Some features may only be available in newer versions for technical reasons.

In most cases, you do not need to worry about the version of the format description. However, there are some differences.

Differences

LiteralVersion 1Version 2
[[[\[
]]\]
\\\\

[first] and [optional] are supported in both version 1 and version 2, but individual methods may prevent their use. This is because some methods return a format description that is entirely borrowed. However, when parsing [first] and [optional], the generated sequence is necessarily owned. For this reason, you will need to use the format_description::parse_owned method or the format_description! macro to use these components.

Version used

format_description::parse uses version 1 unconditionally. This is the only method that has a non-configurable version. format_description::parse_borrowed and format_description::parse_owned require the user to specify the version. If the version is not valid, compilation will fail. format_description! defaults to version 1, but can be configured to use a different version.

Configuring format_description!

For backwards-compatibility reasons, the format_description! macro defaults to version 1. If you want to use a different version, you can do so by setting the version parameter to 2. Note that this is only necessary if you are relying on a difference in behavior between the versions.

use time::macros::format_description;
let _ = format_description!("[hour]:[minute]:[second]"); // Version 1 is implied.
let _ = format_description!(version = 1, "[hour]:[minute]:[second]");
let _ = format_description!(version = 2, "[hour]:[minute]:[second]");

Attempting to provide an invalid version will result in a compile-time error.

use time::macros::format_description;
// 0 is not a valid version, so compilation will fail.
let _ = format_description!(version = 0, "[hour]:[minute]:[second]");

Version 1

version 1 top-level syntax

[[ produces a literal [. No other character must be escaped.

Version 2

version 2 top-level syntax

\ is used to begin an escape sequence. Currently, the only valid escape sequences are \[, \], and \\. Any other character following \ is invalid.

Components

Follows is the syntax for all components in alphabetical order. Any of the following may be used where component is present in the above diagram. "Whitespace" refers to any non-empty sequence of ASCII whitespace characters.

  • Day of month: [day]

    syntax for day component

    The padded value has a width of 2. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

  • First item: [first]

    syntax for first component

    A series of FormatItems (or OwnedFormatItems) where, when parsing, the first successful parse is used. When formatting, the first item is used.

    format_description refers to a complete format description that is nested; whitespace (including leading and trailing) is significant.

  • End of input: [end]

    syntax for end component

    This component indicates the end of the input. When formatting, it is a no-op. When parsing, it will only succeed if there is no further input. It does not consume any input.

    There is no customization available for this component.

  • Clock hour: [hour]

    syntax for hour component

    The padded value has a width of 2. You can choose between padding with zeroes, spacing, or having no padding at all. The default is to pad the value with zeroes.

    Users have the option to choose between two representations. One is the 12-hour clock, frequently used in the Anglosphere, while the alternative (the 24-hour clock) is frequently used elsewhere. The 12-hour clock is typically used in conjunction with AM/PM.

  • Ignore: [ignore count:X]

    syntax for ignore component

    When parsing, this ignores the indicated number of bytes. This component is a no-op when formatting. The count modifier is mandatory. Its value must be a positive integer.

  • Minute within the clock hour: [minute]

    syntax for minute component

    The padded value has a width of 2. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

  • Month: [month]

    syntax for month component

    The padded value has a width of 2. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

    Users have the option to choose between three representations. The default is numerical. Alternatives are long and short, both of which are textual formats and have no padding. The long format is the full English name of the month, while the short format is the first three letters of it.

    When parsing, there is the option to consume text-based formats case-insensitively.

  • Whole hours offset from UTC: [offset_hour]

    syntax for offset hour component

    The padded value has a width of 2. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

    Users have the option to choose whether the sign is automatic (the default) or mandatory. If the sign is automatic, it will only be present when the value is negative. If mandatory, it will always be present.

  • Minutes within the hour offset from UTC: [offset_minute]

    syntax for offset minute component

    The padded value has a width of 2. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

    This value is always positive. As such, it has no sign.

  • Seconds within the minute offset from UTC: [offset_second]

    syntax for offset second component

    The padded value has a width of 2. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

    This value is always positive. As such, it has no sign.

  • Optional items: [optional]

    syntax for optional component

    An item that may or may not be present while parsing. While formatting, the value is always present.

    format_description refers to a complete format description that is nested; whitespace (including leading and trailing) is significant.

  • Day of year: [ordinal]

    syntax for ordinal component

    The padded value has a width of 3. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

  • AM/PM: [period]

    syntax for period component

    Users have the option to choose whether the value is uppercase or lowercase. This component is typically used in conjunction with the hour of the day with repr:12.

    When parsing, there is the option to consume text-based formats case-insensitively.

  • Second within the clock minute: [second]

    syntax for second component

    The padded value has a width of 2. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

  • Subsecond within the clock second: [subsecond]

    syntax for subsecond component

    Users have the choice of how many digits should be displayed or parsed. By default, this is one or more, where the minimum number of digits will be used when formatting and any nonzero number of digits are accepted by the parser (though digits after the ninth will be discarded). There is the option to require a fixed number of digits between one and nine. When formatting, the value is not rounded if more digits would otherwise be present.

  • Unix timestamp: [unix_timestamp]

    syntax for unix timestamp component

    Users can choose between four levels of precision: second (the default), millisecond, microsecond, and nanosecond. The sign can also be made mandatory rather than optional.

  • Week of the year: [week_number]

    syntax for week number component

    The padded value has a width of 2. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

    Users can choose between three representations: iso (the default), sunday, and monday. ISO week numbers are in between 1 and 53, while others are between 0 and 53. ISO week one is the Monday-to-Sunday week that contains January 4. Week one of other representations begins on the first instance of that day in the calendar year (e.g. Sunday-based week numbering has week one start on the first Sunday of the year).

  • Day of the week: [weekday]

    syntax for weekday component

    Users can choose between a number of representations for the day of the week. There are long (the default) and short, both of which are textual representations; the long representation is the weekday's full name in English, while the short is the first three letters. There are also sunday and monday representations, which are numerical. These formats are either zero to six or one to seven (depending on whether one_indexed is false or true, respectively), with the named day being at the start of that range.

    When parsing, there is the option to consume text-based formats case-insensitively.

  • Year: [year]

    syntax for year component

    The padded value has a width of 4. You can choose between padding with zeroes, spaces, or having no padding at all. The default is to pad the value with zeroes.

    Users can choose between two representations: the full year (the default) and the last two digits of the year. This should be relatively straightforward. Note that when parsing, if only the last two digits of the year are present, the value returned may not be what was expected — if the return is successful at all (it's not guaranteed).

    There are two bases for the year: calendar and iso_week. The former is what you want if using the month, day, ordinal, or similar. You likely only want to use iso_week if you are using the week number with repr:iso. Don't be like Twitter; know which should be used when.

    Users have the option to choose whether the sign is automatic (the default) or mandatory. If the sign is automatic, it will only be present when the value is negative or if the large-dates feature is enabled and the value contains more than four digits. If mandatory, it will always be present.

    When the large-dates feature is enabled, ambiguities may exist when parsing. For example, if a year is immediately followed by the week number, the parser will eagerly consume six digits even if the year should only be four and the week number the remaining two.