time/format_description/
modifier.rs

1//! Various modifiers for components.
2
3use core::num::NonZeroU16;
4
5/// Day of the month.
6#[non_exhaustive]
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct Day {
9    /// The padding to obtain the minimum width.
10    pub padding: Padding,
11}
12
13/// The representation of a month.
14#[non_exhaustive]
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum MonthRepr {
17    /// The number of the month (January is 1, December is 12).
18    Numerical,
19    /// The long form of the month name (e.g. "January").
20    Long,
21    /// The short form of the month name (e.g. "Jan").
22    Short,
23}
24
25/// Month of the year.
26#[non_exhaustive]
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub struct Month {
29    /// The padding to obtain the minimum width.
30    pub padding: Padding,
31    /// What form of representation should be used?
32    pub repr: MonthRepr,
33    /// Is the value case sensitive when parsing?
34    pub case_sensitive: bool,
35}
36
37/// Ordinal day of the year.
38#[non_exhaustive]
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub struct Ordinal {
41    /// The padding to obtain the minimum width.
42    pub padding: Padding,
43}
44
45/// The representation used for the day of the week.
46#[non_exhaustive]
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum WeekdayRepr {
49    /// The short form of the weekday (e.g. "Mon").
50    Short,
51    /// The long form of the weekday (e.g. "Monday").
52    Long,
53    /// A numerical representation using Sunday as the first day of the week.
54    ///
55    /// Sunday is either 0 or 1, depending on the other modifier's value.
56    Sunday,
57    /// A numerical representation using Monday as the first day of the week.
58    ///
59    /// Monday is either 0 or 1, depending on the other modifier's value.
60    Monday,
61}
62
63/// Day of the week.
64#[non_exhaustive]
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub struct Weekday {
67    /// What form of representation should be used?
68    pub repr: WeekdayRepr,
69    /// When using a numerical representation, should it be zero or one-indexed?
70    pub one_indexed: bool,
71    /// Is the value case sensitive when parsing?
72    pub case_sensitive: bool,
73}
74
75/// The representation used for the week number.
76#[non_exhaustive]
77#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78pub enum WeekNumberRepr {
79    /// Week 1 is the week that contains January 4.
80    Iso,
81    /// Week 1 begins on the first Sunday of the calendar year.
82    Sunday,
83    /// Week 1 begins on the first Monday of the calendar year.
84    Monday,
85}
86
87/// Week within the year.
88#[non_exhaustive]
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub struct WeekNumber {
91    /// The padding to obtain the minimum width.
92    pub padding: Padding,
93    /// What kind of representation should be used?
94    pub repr: WeekNumberRepr,
95}
96
97/// The representation used for a year value.
98#[non_exhaustive]
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub enum YearRepr {
101    /// The full value of the year.
102    Full,
103    /// All digits except the last two. Includes the sign, if any.
104    Century,
105    /// Only the last two digits of the year.
106    LastTwo,
107}
108
109/// The range of years that are supported.
110///
111/// This modifier has no effect when the year repr is [`LastTwo`](YearRepr::LastTwo).
112#[non_exhaustive]
113#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub enum YearRange {
115    /// Years between -9999 and 9999 are supported.
116    Standard,
117    /// Years between -999_999 and 999_999 are supported, with the sign being required if the year
118    /// contains more than four digits.
119    ///
120    /// If the `large-dates` feature is not enabled, this variant is equivalent to `Standard`.
121    Extended,
122}
123
124/// Year of the date.
125#[non_exhaustive]
126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub struct Year {
128    /// The padding to obtain the minimum width.
129    pub padding: Padding,
130    /// What kind of representation should be used?
131    pub repr: YearRepr,
132    /// What range of years is supported?
133    pub range: YearRange,
134    /// Whether the value is based on the ISO week number or the Gregorian calendar.
135    pub iso_week_based: bool,
136    /// Whether the `+` sign is present when a positive year contains fewer than five digits.
137    pub sign_is_mandatory: bool,
138}
139
140/// Hour of the day.
141#[non_exhaustive]
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub struct Hour {
144    /// The padding to obtain the minimum width.
145    pub padding: Padding,
146    /// Is the hour displayed using a 12 or 24-hour clock?
147    pub is_12_hour_clock: bool,
148}
149
150/// Minute within the hour.
151#[non_exhaustive]
152#[derive(Debug, Clone, Copy, PartialEq, Eq)]
153pub struct Minute {
154    /// The padding to obtain the minimum width.
155    pub padding: Padding,
156}
157
158/// AM/PM part of the time.
159#[non_exhaustive]
160#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub struct Period {
162    /// Is the period uppercase or lowercase?
163    pub is_uppercase: bool,
164    /// Is the value case sensitive when parsing?
165    ///
166    /// Note that when `false`, the `is_uppercase` field has no effect on parsing behavior.
167    pub case_sensitive: bool,
168}
169
170/// Second within the minute.
171#[non_exhaustive]
172#[derive(Debug, Clone, Copy, PartialEq, Eq)]
173pub struct Second {
174    /// The padding to obtain the minimum width.
175    pub padding: Padding,
176}
177
178/// The number of digits present in a subsecond representation.
179#[non_exhaustive]
180#[derive(Debug, Clone, Copy, PartialEq, Eq)]
181pub enum SubsecondDigits {
182    /// Exactly one digit.
183    One,
184    /// Exactly two digits.
185    Two,
186    /// Exactly three digits.
187    Three,
188    /// Exactly four digits.
189    Four,
190    /// Exactly five digits.
191    Five,
192    /// Exactly six digits.
193    Six,
194    /// Exactly seven digits.
195    Seven,
196    /// Exactly eight digits.
197    Eight,
198    /// Exactly nine digits.
199    Nine,
200    /// Any number of digits (up to nine) that is at least one. When formatting, the minimum digits
201    /// necessary will be used.
202    OneOrMore,
203}
204
205/// Subsecond within the second.
206#[non_exhaustive]
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub struct Subsecond {
209    /// How many digits are present in the component?
210    pub digits: SubsecondDigits,
211}
212
213/// Hour of the UTC offset.
214#[non_exhaustive]
215#[derive(Debug, Clone, Copy, PartialEq, Eq)]
216pub struct OffsetHour {
217    /// Whether the `+` sign is present on positive values.
218    pub sign_is_mandatory: bool,
219    /// The padding to obtain the minimum width.
220    pub padding: Padding,
221}
222
223/// Minute within the hour of the UTC offset.
224#[non_exhaustive]
225#[derive(Debug, Clone, Copy, PartialEq, Eq)]
226pub struct OffsetMinute {
227    /// The padding to obtain the minimum width.
228    pub padding: Padding,
229}
230
231/// Second within the minute of the UTC offset.
232#[non_exhaustive]
233#[derive(Debug, Clone, Copy, PartialEq, Eq)]
234pub struct OffsetSecond {
235    /// The padding to obtain the minimum width.
236    pub padding: Padding,
237}
238
239/// Type of padding to ensure a minimum width.
240#[non_exhaustive]
241#[derive(Debug, Clone, Copy, PartialEq, Eq)]
242pub enum Padding {
243    /// A space character (` `) should be used as padding.
244    Space,
245    /// A zero character (`0`) should be used as padding.
246    Zero,
247    /// There is no padding. This can result in a width below the otherwise minimum number of
248    /// characters.
249    None,
250}
251
252/// Ignore some number of bytes.
253///
254/// This has no effect when formatting.
255#[non_exhaustive]
256#[derive(Debug, Clone, Copy, PartialEq, Eq)]
257pub struct Ignore {
258    /// The number of bytes to ignore.
259    pub count: NonZeroU16,
260}
261
262// Needed as `Default` is deliberately not implemented for `Ignore`. The number of bytes to ignore
263// must be explicitly provided.
264impl Ignore {
265    /// Create an instance of `Ignore` with the provided number of bytes to ignore.
266    pub const fn count(count: NonZeroU16) -> Self {
267        Self { count }
268    }
269}
270
271/// The precision of a Unix timestamp.
272#[non_exhaustive]
273#[derive(Debug, Clone, Copy, PartialEq, Eq)]
274pub enum UnixTimestampPrecision {
275    /// Seconds since the Unix epoch.
276    Second,
277    /// Milliseconds since the Unix epoch.
278    Millisecond,
279    /// Microseconds since the Unix epoch.
280    Microsecond,
281    /// Nanoseconds since the Unix epoch.
282    Nanosecond,
283}
284
285/// A Unix timestamp.
286#[non_exhaustive]
287#[derive(Debug, Clone, Copy, PartialEq, Eq)]
288pub struct UnixTimestamp {
289    /// The precision of the timestamp.
290    pub precision: UnixTimestampPrecision,
291    /// Whether the `+` sign must be present for a non-negative timestamp.
292    pub sign_is_mandatory: bool,
293}
294
295/// The end of input.
296///
297/// There is currently not customization for this modifier.
298#[non_exhaustive]
299#[derive(Debug, Clone, Copy, PartialEq, Eq)]
300pub struct End;
301
302/// Generate the provided code if and only if `pub` is present.
303macro_rules! if_pub {
304    (pub $(#[$attr:meta])*; $($x:tt)*) => {
305        $(#[$attr])*
306        ///
307        /// This function exists since [`Default::default()`] cannot be used in a `const` context.
308        /// It may be removed once that becomes possible. As the [`Default`] trait is in the
309        /// prelude, removing this function in the future will not cause any resolution failures for
310        /// the overwhelming majority of users; only users who use `#![no_implicit_prelude]` will be
311        /// affected. As such it will not be considered a breaking change.
312        $($x)*
313    };
314    ($($_:tt)*) => {};
315}
316
317/// Implement `Default` for the given type. This also generates an inherent implementation of a
318/// `default` method that is `const fn`, permitting the default value to be used in const contexts.
319// Every modifier should use this macro rather than a derived `Default`.
320macro_rules! impl_const_default {
321    ($($(#[$doc:meta])* $(@$pub:ident)? $type:ty => $default:expr;)*) => {$(
322        impl $type {
323            if_pub! {
324                $($pub)?
325                $(#[$doc])*;
326                pub const fn default() -> Self {
327                    $default
328                }
329            }
330        }
331
332        $(#[$doc])*
333        impl Default for $type {
334            fn default() -> Self {
335                $default
336            }
337        }
338    )*};
339}
340
341impl_const_default! {
342    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
343    @pub Day => Self { padding: Padding::Zero };
344    /// Creates a modifier that indicates the value uses the
345    /// [`Numerical`](Self::Numerical) representation.
346    MonthRepr => Self::Numerical;
347    /// Creates an instance of this type that indicates the value uses the
348    /// [`Numerical`](MonthRepr::Numerical) representation, is [padded with zeroes](Padding::Zero),
349    /// and is case-sensitive when parsing.
350    @pub Month => Self {
351        padding: Padding::Zero,
352        repr: MonthRepr::Numerical,
353        case_sensitive: true,
354    };
355    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
356    @pub Ordinal => Self { padding: Padding::Zero };
357    /// Creates a modifier that indicates the value uses the [`Long`](Self::Long) representation.
358    WeekdayRepr => Self::Long;
359    /// Creates a modifier that indicates the value uses the [`Long`](WeekdayRepr::Long)
360    /// representation and is case-sensitive when parsing. If the representation is changed to a
361    /// numerical one, the instance defaults to one-based indexing.
362    @pub Weekday => Self {
363        repr: WeekdayRepr::Long,
364        one_indexed: true,
365        case_sensitive: true,
366    };
367    /// Creates a modifier that indicates that the value uses the [`Iso`](Self::Iso) representation.
368    WeekNumberRepr => Self::Iso;
369    /// Creates a modifier that indicates that the value is [padded with zeroes](Padding::Zero)
370            /// and uses the [`Iso`](WeekNumberRepr::Iso) representation.
371    @pub WeekNumber => Self {
372        padding: Padding::Zero,
373        repr: WeekNumberRepr::Iso,
374    };
375    /// Creates a modifier that indicates the value uses the [`Full`](Self::Full) representation.
376    YearRepr => Self::Full;
377    /// Creates a modifier that indicates the value uses the [`Extended`](Self::Extended) range.
378    YearRange => Self::Extended;
379    /// Creates a modifier that indicates the value uses the [`Full`](YearRepr::Full)
380    /// representation, is [padded with zeroes](Padding::Zero), uses the Gregorian calendar as its
381    /// base, and only includes the year's sign if necessary.
382    @pub Year => Self {
383        padding: Padding::Zero,
384        repr: YearRepr::Full,
385        range: YearRange::Extended,
386        iso_week_based: false,
387        sign_is_mandatory: false,
388    };
389    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero) and
390    /// has the 24-hour representation.
391    @pub Hour => Self {
392        padding: Padding::Zero,
393        is_12_hour_clock: false,
394    };
395    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
396    @pub Minute => Self { padding: Padding::Zero };
397    /// Creates a modifier that indicates the value uses the upper-case representation and is
398    /// case-sensitive when parsing.
399    @pub Period => Self {
400        is_uppercase: true,
401        case_sensitive: true,
402    };
403    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
404    @pub Second => Self { padding: Padding::Zero };
405    /// Creates a modifier that indicates the stringified value contains [one or more
406    /// digits](Self::OneOrMore).
407    SubsecondDigits => Self::OneOrMore;
408    /// Creates a modifier that indicates the stringified value contains [one or more
409    /// digits](SubsecondDigits::OneOrMore).
410    @pub Subsecond => Self { digits: SubsecondDigits::OneOrMore };
411    /// Creates a modifier that indicates the value only uses a sign for negative values and is
412    /// [padded with zeroes](Padding::Zero).
413    @pub OffsetHour => Self {
414        sign_is_mandatory: false,
415        padding: Padding::Zero,
416    };
417    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
418    @pub OffsetMinute => Self { padding: Padding::Zero };
419    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
420    @pub OffsetSecond => Self { padding: Padding::Zero };
421    /// Creates a modifier that indicates the value is [padded with zeroes](Self::Zero).
422    Padding => Self::Zero;
423    /// Creates a modifier that indicates the value represents the [number of seconds](Self::Second)
424    /// since the Unix epoch.
425    UnixTimestampPrecision => Self::Second;
426    /// Creates a modifier that indicates the value represents the [number of
427    /// seconds](UnixTimestampPrecision::Second) since the Unix epoch. The sign is not mandatory.
428    @pub UnixTimestamp => Self {
429        precision: UnixTimestampPrecision::Second,
430        sign_is_mandatory: false,
431    };
432    /// Creates a modifier used to represent the end of input.
433    @pub End => End;
434}