time/format_description/
modifier.rs

1//! Various modifiers for components.
2
3use core::num::NonZero;
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: NonZero<u16>,
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    #[inline]
267    pub const fn count(count: NonZero<u16>) -> Self {
268        Self { count }
269    }
270}
271
272/// The precision of a Unix timestamp.
273#[non_exhaustive]
274#[derive(Debug, Clone, Copy, PartialEq, Eq)]
275pub enum UnixTimestampPrecision {
276    /// Seconds since the Unix epoch.
277    Second,
278    /// Milliseconds since the Unix epoch.
279    Millisecond,
280    /// Microseconds since the Unix epoch.
281    Microsecond,
282    /// Nanoseconds since the Unix epoch.
283    Nanosecond,
284}
285
286/// A Unix timestamp.
287#[non_exhaustive]
288#[derive(Debug, Clone, Copy, PartialEq, Eq)]
289pub struct UnixTimestamp {
290    /// The precision of the timestamp.
291    pub precision: UnixTimestampPrecision,
292    /// Whether the `+` sign must be present for a non-negative timestamp.
293    pub sign_is_mandatory: bool,
294}
295
296/// The end of input.
297///
298/// There is currently not customization for this modifier.
299#[non_exhaustive]
300#[derive(Debug, Clone, Copy, PartialEq, Eq)]
301pub struct End;
302
303/// Generate the provided code if and only if `pub` is present.
304macro_rules! if_pub {
305    (pub $(#[$attr:meta])*; $($x:tt)*) => {
306        $(#[$attr])*
307        ///
308        /// This function exists since [`Default::default()`] cannot be used in a `const` context.
309        /// It may be removed once that becomes possible. As the [`Default`] trait is in the
310        /// prelude, removing this function in the future will not cause any resolution failures for
311        /// the overwhelming majority of users; only users who use `#![no_implicit_prelude]` will be
312        /// affected. As such it will not be considered a breaking change.
313        $($x)*
314    };
315    ($($_:tt)*) => {};
316}
317
318/// Implement `Default` for the given type. This also generates an inherent implementation of a
319/// `default` method that is `const fn`, permitting the default value to be used in const contexts.
320// Every modifier should use this macro rather than a derived `Default`.
321macro_rules! impl_const_default {
322    ($($(#[$doc:meta])* $(@$pub:ident)? $type:ty => $default:expr;)*) => {$(
323        impl $type {
324            if_pub! {
325                $($pub)?
326                $(#[$doc])*;
327                #[inline]
328                pub const fn default() -> Self {
329                    $default
330                }
331            }
332        }
333
334        $(#[$doc])*
335        impl Default for $type {
336            #[inline]
337            fn default() -> Self {
338                $default
339            }
340        }
341    )*};
342}
343
344impl_const_default! {
345    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
346    @pub Day => Self { padding: Padding::Zero };
347    /// Creates a modifier that indicates the value uses the
348    /// [`Numerical`](Self::Numerical) representation.
349    MonthRepr => Self::Numerical;
350    /// Creates an instance of this type that indicates the value uses the
351    /// [`Numerical`](MonthRepr::Numerical) representation, is [padded with zeroes](Padding::Zero),
352    /// and is case-sensitive when parsing.
353    @pub Month => Self {
354        padding: Padding::Zero,
355        repr: MonthRepr::Numerical,
356        case_sensitive: true,
357    };
358    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
359    @pub Ordinal => Self { padding: Padding::Zero };
360    /// Creates a modifier that indicates the value uses the [`Long`](Self::Long) representation.
361    WeekdayRepr => Self::Long;
362    /// Creates a modifier that indicates the value uses the [`Long`](WeekdayRepr::Long)
363    /// representation and is case-sensitive when parsing. If the representation is changed to a
364    /// numerical one, the instance defaults to one-based indexing.
365    @pub Weekday => Self {
366        repr: WeekdayRepr::Long,
367        one_indexed: true,
368        case_sensitive: true,
369    };
370    /// Creates a modifier that indicates that the value uses the [`Iso`](Self::Iso) representation.
371    WeekNumberRepr => Self::Iso;
372    /// Creates a modifier that indicates that the value is [padded with zeroes](Padding::Zero)
373            /// and uses the [`Iso`](WeekNumberRepr::Iso) representation.
374    @pub WeekNumber => Self {
375        padding: Padding::Zero,
376        repr: WeekNumberRepr::Iso,
377    };
378    /// Creates a modifier that indicates the value uses the [`Full`](Self::Full) representation.
379    YearRepr => Self::Full;
380    /// Creates a modifier that indicates the value uses the [`Extended`](Self::Extended) range.
381    YearRange => Self::Extended;
382    /// Creates a modifier that indicates the value uses the [`Full`](YearRepr::Full)
383    /// representation, is [padded with zeroes](Padding::Zero), uses the Gregorian calendar as its
384    /// base, and only includes the year's sign if necessary.
385    @pub Year => Self {
386        padding: Padding::Zero,
387        repr: YearRepr::Full,
388        range: YearRange::Extended,
389        iso_week_based: false,
390        sign_is_mandatory: false,
391    };
392    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero) and
393    /// has the 24-hour representation.
394    @pub Hour => Self {
395        padding: Padding::Zero,
396        is_12_hour_clock: false,
397    };
398    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
399    @pub Minute => Self { padding: Padding::Zero };
400    /// Creates a modifier that indicates the value uses the upper-case representation and is
401    /// case-sensitive when parsing.
402    @pub Period => Self {
403        is_uppercase: true,
404        case_sensitive: true,
405    };
406    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
407    @pub Second => Self { padding: Padding::Zero };
408    /// Creates a modifier that indicates the stringified value contains [one or more
409    /// digits](Self::OneOrMore).
410    SubsecondDigits => Self::OneOrMore;
411    /// Creates a modifier that indicates the stringified value contains [one or more
412    /// digits](SubsecondDigits::OneOrMore).
413    @pub Subsecond => Self { digits: SubsecondDigits::OneOrMore };
414    /// Creates a modifier that indicates the value only uses a sign for negative values and is
415    /// [padded with zeroes](Padding::Zero).
416    @pub OffsetHour => Self {
417        sign_is_mandatory: false,
418        padding: Padding::Zero,
419    };
420    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
421    @pub OffsetMinute => Self { padding: Padding::Zero };
422    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
423    @pub OffsetSecond => Self { padding: Padding::Zero };
424    /// Creates a modifier that indicates the value is [padded with zeroes](Self::Zero).
425    Padding => Self::Zero;
426    /// Creates a modifier that indicates the value represents the [number of seconds](Self::Second)
427    /// since the Unix epoch.
428    UnixTimestampPrecision => Self::Second;
429    /// Creates a modifier that indicates the value represents the [number of
430    /// seconds](UnixTimestampPrecision::Second) since the Unix epoch. The sign is not mandatory.
431    @pub UnixTimestamp => Self {
432        precision: UnixTimestampPrecision::Second,
433        sign_is_mandatory: false,
434    };
435    /// Creates a modifier used to represent the end of input.
436    @pub End => End;
437}