Skip to main content

time/format_description/
modifier.rs

1//! Various modifiers for components.
2
3use core::num::NonZero;
4
5/// Generate the provided code if and only if `pub` is present.
6macro_rules! if_pub {
7    (pub $(#[$attr:meta])*; $($x:tt)*) => {
8        $(#[$attr])*
9        ///
10        /// This function exists since [`Default::default()`] cannot be used in a `const` context.
11        /// It may be removed once that becomes possible. As the [`Default`] trait is in the
12        /// prelude, removing this function in the future will not cause any resolution failures for
13        /// the overwhelming majority of users; only users who use `#![no_implicit_prelude]` will be
14        /// affected. As such it will not be considered a breaking change.
15        $($x)*
16    };
17    ($($_:tt)*) => {};
18}
19
20/// Implement `Default` for the given type. This also generates an inherent implementation of a
21/// `default` method that is `const fn`, permitting the default value to be used in const contexts.
22// Every modifier should use this macro rather than a derived `Default`.
23macro_rules! impl_const_default {
24    ($($(
25        #[doc = $doc:expr])*
26        $(#[cfg($($cfg:tt)+)])?
27        $(#[expect($($expected:tt)+)])?
28        $(@$pub:ident)? $type:ty => $default:expr;
29    )*) => {$(
30        $(#[cfg($($cfg)+)])?
31        $(#[expect($($expected)+)])?
32        impl $type {
33            if_pub! {
34                $($pub)?
35                $(#[doc = $doc])*;
36                #[inline]
37                pub const fn default() -> Self {
38                    $default
39                }
40            }
41        }
42
43        $(#[doc = $doc])*
44        $(#[cfg($($cfg)+)])?
45        $(#[expect($($expected)+)])?
46        impl Default for $type {
47            #[inline]
48            fn default() -> Self {
49                $default
50            }
51        }
52    )*};
53}
54
55// Keep this first so that it's shown at the top of documentation.
56impl_const_default! {
57    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
58    @pub Day => Self { padding: Padding::Zero };
59    /// Creates a modifier that indicates the value uses the
60    /// [`Numerical`](Self::Numerical) representation.
61    #[expect(deprecated)]
62    MonthRepr => Self::Numerical;
63    @pub MonthShort => Self { case_sensitive: true };
64    @pub MonthLong => Self { case_sensitive: true };
65    @pub MonthNumerical => Self { padding: Padding::Zero };
66    /// Creates an instance of this type that indicates the value uses the
67    /// [`Numerical`](MonthRepr::Numerical) representation, is [padded with zeroes](Padding::Zero),
68    /// and is case-sensitive when parsing.
69    #[expect(deprecated)]
70    @pub Month => Self {
71        padding: Padding::Zero,
72        repr: MonthRepr::Numerical,
73        case_sensitive: true,
74    };
75    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
76    @pub Ordinal => Self { padding: Padding::Zero };
77    /// Creates a modifier that indicates the value uses the [`Long`](Self::Long) representation.
78    #[expect(deprecated)]
79    WeekdayRepr => Self::Long;
80    @pub WeekdayShort => Self { case_sensitive: true };
81    @pub WeekdayLong => Self { case_sensitive: true };
82    @pub WeekdaySunday => Self { one_indexed: true };
83    @pub WeekdayMonday => Self { one_indexed: true };
84    /// Creates a modifier that indicates the value uses the [`Long`](WeekdayRepr::Long)
85    /// representation and is case-sensitive when parsing. If the representation is changed to a
86    /// numerical one, the instance defaults to one-based indexing.
87    #[expect(deprecated)]
88    @pub Weekday => Self {
89        repr: WeekdayRepr::Long,
90        one_indexed: true,
91        case_sensitive: true,
92    };
93    /// Creates a modifier that indicates that the value uses the [`Iso`](Self::Iso) representation.
94    #[expect(deprecated)]
95    WeekNumberRepr => Self::Iso;
96    @pub WeekNumberIso => Self { padding: Padding::Zero };
97    @pub WeekNumberSunday => Self { padding: Padding::Zero };
98    @pub WeekNumberMonday => Self { padding: Padding::Zero };
99    /// Creates a modifier that indicates that the value is [padded with zeroes](Padding::Zero)
100    /// and uses the [`Iso`](WeekNumberRepr::Iso) representation.
101    #[expect(deprecated)]
102    @pub WeekNumber => Self {
103        padding: Padding::Zero,
104        repr: WeekNumberRepr::Iso,
105    };
106    /// Creates a modifier that indicates the value uses the [`Full`](Self::Full) representation.
107    #[expect(deprecated)]
108    YearRepr => Self::Full;
109    /// Creates a modifier that indicates the value uses the [`Extended`](Self::Extended) range.
110    ///
111    /// Note that this is the default modifier for version 1 and 2 format descriptions. Version 3
112    /// format descriptions (which cannot be manually constructed) use `Standard` as the default.
113    #[expect(deprecated)]
114    YearRange => Self::Extended;
115    @pub CalendarYearFullExtendedRange => Self {
116        padding: Padding::Zero,
117        sign_is_mandatory: false,
118    };
119    @pub CalendarYearFullStandardRange => Self {
120        padding: Padding::Zero,
121        sign_is_mandatory: false,
122    };
123    @pub IsoYearFullExtendedRange => Self {
124        padding: Padding::Zero,
125        sign_is_mandatory: false,
126    };
127    @pub IsoYearFullStandardRange => Self {
128        padding: Padding::Zero,
129        sign_is_mandatory: false,
130    };
131    @pub CalendarYearCenturyExtendedRange => Self {
132        padding: Padding::Zero,
133        sign_is_mandatory: false,
134    };
135    @pub CalendarYearCenturyStandardRange => Self {
136        padding: Padding::Zero,
137        sign_is_mandatory: false,
138    };
139    @pub IsoYearCenturyExtendedRange => Self {
140        padding: Padding::Zero,
141        sign_is_mandatory: false,
142    };
143    @pub IsoYearCenturyStandardRange => Self {
144        padding: Padding::Zero,
145        sign_is_mandatory: false,
146    };
147    @pub CalendarYearLastTwo => Self {
148        padding: Padding::Zero,
149    };
150    @pub IsoYearLastTwo => Self {
151        padding: Padding::Zero,
152    };
153    /// Creates a modifier that indicates the value uses the [`Full`](YearRepr::Full)
154    /// representation, is [padded with zeroes](Padding::Zero), uses the Gregorian calendar as its
155    /// base, and only includes the year's sign if necessary.
156    #[expect(deprecated)]
157    @pub Year => Self {
158        padding: Padding::Zero,
159        repr: YearRepr::Full,
160        range: YearRange::Extended,
161        iso_week_based: false,
162        sign_is_mandatory: false,
163    };
164    @pub Hour12 => Self { padding: Padding::Zero };
165    @pub Hour24 => Self { padding: Padding::Zero };
166    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero) and
167    /// has the 24-hour representation.
168    #[expect(deprecated)]
169    @pub Hour => Self {
170        padding: Padding::Zero,
171        is_12_hour_clock: false,
172    };
173    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
174    @pub Minute => Self { padding: Padding::Zero };
175    /// Creates a modifier that indicates the value uses the upper-case representation and is
176    /// case-sensitive when parsing.
177    @pub Period => Self {
178        is_uppercase: true,
179        case_sensitive: true,
180    };
181    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
182    @pub Second => Self { padding: Padding::Zero };
183    /// Creates a modifier that indicates the stringified value contains [one or more
184    /// digits](Self::OneOrMore).
185    SubsecondDigits => Self::OneOrMore;
186    /// Creates a modifier that indicates the stringified value contains [one or more
187    /// digits](SubsecondDigits::OneOrMore).
188    @pub Subsecond => Self { digits: SubsecondDigits::OneOrMore };
189    /// Creates a modifier that indicates the value only uses a sign for negative values and is
190    /// [padded with zeroes](Padding::Zero).
191    @pub OffsetHour => Self {
192        sign_is_mandatory: false,
193        padding: Padding::Zero,
194    };
195    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
196    @pub OffsetMinute => Self { padding: Padding::Zero };
197    /// Creates a modifier that indicates the value is [padded with zeroes](Padding::Zero).
198    @pub OffsetSecond => Self { padding: Padding::Zero };
199    /// Creates a modifier that indicates the value is [padded with zeroes](Self::Zero).
200    Padding => Self::Zero;
201    /// Creates a modifier that indicates the value represents the [number of seconds](Self::Second)
202    /// since the Unix epoch.
203    #[expect(deprecated)]
204    UnixTimestampPrecision => Self::Second;
205    @pub UnixTimestampSecond => Self { sign_is_mandatory: false };
206    @pub UnixTimestampMillisecond => Self { sign_is_mandatory: false };
207    @pub UnixTimestampMicrosecond => Self { sign_is_mandatory: false };
208    @pub UnixTimestampNanosecond => Self { sign_is_mandatory: false };
209    /// Creates a modifier that indicates the value represents the [number of
210    /// seconds](UnixTimestampPrecision::Second) since the Unix epoch. The sign is not mandatory.
211    #[expect(deprecated)]
212    @pub UnixTimestamp => Self {
213        precision: UnixTimestampPrecision::Second,
214        sign_is_mandatory: false,
215    };
216    /// Indicate that any trailing characters after the end of input are prohibited and will cause
217    /// an error when used with `parse`.
218    TrailingInput => Self::Prohibit;
219    /// Creates a modifier used to represent the end of input, not allowing any trailing input (i.e.
220    /// the input must be fully consumed).
221    @pub End => Self { trailing_input: TrailingInput::Prohibit };
222}
223
224macro_rules! builder_methods {
225    ($(
226        $(#[$fn_attr:meta])*
227        fn $method:ident($field:ident : $field_ty:ty);
228    )+) => {$(
229        $(#[$fn_attr])*
230        #[allow(clippy::needless_update, reason = "needed for types with multiple fields")]
231        #[inline]
232        #[must_use = "this returns the result of the operation, without modifying the original"]
233        pub const fn $method(self, $field: $field_ty) -> Self {
234            Self { $field, ..self }
235        }
236    )+ };
237}
238
239/// Day of the month.
240#[non_exhaustive]
241#[derive(Debug, Clone, Copy, PartialEq, Eq)]
242pub struct Day {
243    /// The padding to obtain the minimum width.
244    pub padding: Padding,
245}
246
247impl Day {
248    builder_methods! {
249        /// Set the padding type.
250        fn with_padding(padding: Padding);
251    }
252}
253
254/// The representation of a month.
255#[non_exhaustive]
256#[deprecated(
257    since = "0.3.48",
258    note = "used only in the deprecated `Month` component"
259)]
260#[derive(Debug, Clone, Copy, PartialEq, Eq)]
261pub enum MonthRepr {
262    /// The number of the month (January is 1, December is 12).
263    Numerical,
264    /// The long form of the month name (e.g. "January").
265    Long,
266    /// The short form of the month name (e.g. "Jan").
267    Short,
268}
269
270/// Month of the year using the short form of the month name (e.g. "Jan").
271#[derive(Debug, Clone, Copy, PartialEq, Eq)]
272pub struct MonthShort {
273    /// Is the value case sensitive when parsing?
274    pub(crate) case_sensitive: bool,
275}
276
277impl MonthShort {
278    builder_methods! {
279        /// Set whether the value is case sensitive when parsing.
280        fn with_case_sensitive(case_sensitive: bool);
281    }
282}
283
284/// Month of the year using the long form of the month name (e.g. "January").
285#[derive(Debug, Clone, Copy, PartialEq, Eq)]
286pub struct MonthLong {
287    /// Is the value case sensitive when parsing?
288    pub(crate) case_sensitive: bool,
289}
290
291impl MonthLong {
292    builder_methods! {
293        /// Set whether the value is case sensitive when parsing.
294        fn with_case_sensitive(case_sensitive: bool);
295    }
296}
297
298/// Month of the year using a numerical representation (e.g. "1" for January).
299#[derive(Debug, Clone, Copy, PartialEq, Eq)]
300pub struct MonthNumerical {
301    /// The padding to obtain the minimum width.
302    pub(crate) padding: Padding,
303}
304
305impl MonthNumerical {
306    builder_methods! {
307        /// Set the padding type.
308        fn with_padding(padding: Padding);
309    }
310}
311
312/// Month of the year.
313#[non_exhaustive]
314#[allow(deprecated)]
315#[deprecated(
316    since = "0.3.48",
317    note = "use `MonthShort`, `MonthLong`, or `MonthNumeric` instead"
318)]
319#[derive(Debug, Clone, Copy, PartialEq, Eq)]
320pub struct Month {
321    /// The padding to obtain the minimum width.
322    pub padding: Padding,
323    /// What form of representation should be used?
324    pub repr: MonthRepr,
325    /// Is the value case sensitive when parsing?
326    pub case_sensitive: bool,
327}
328
329#[expect(deprecated)]
330impl Month {
331    builder_methods! {
332        /// Set the padding type.
333        fn with_padding(padding: Padding);
334        /// Set the manner in which the month is represented.
335        fn with_repr(repr: MonthRepr);
336        /// Set whether the value is case sensitive when parsing.
337        fn with_case_sensitive(case_sensitive: bool);
338    }
339}
340
341/// Ordinal day of the year.
342#[non_exhaustive]
343#[derive(Debug, Clone, Copy, PartialEq, Eq)]
344pub struct Ordinal {
345    /// The padding to obtain the minimum width.
346    pub padding: Padding,
347}
348
349impl Ordinal {
350    builder_methods! {
351        /// Set the padding type.
352        fn with_padding(padding: Padding);
353    }
354}
355
356/// The representation used for the day of the week.
357#[non_exhaustive]
358#[deprecated(
359    since = "0.3.48",
360    note = "used only in the deprecated `Weekday` component"
361)]
362#[derive(Debug, Clone, Copy, PartialEq, Eq)]
363pub enum WeekdayRepr {
364    /// The short form of the weekday (e.g. "Mon").
365    Short,
366    /// The long form of the weekday (e.g. "Monday").
367    Long,
368    /// A numerical representation using Sunday as the first day of the week.
369    ///
370    /// Sunday is either 0 or 1, depending on the other modifier's value.
371    Sunday,
372    /// A numerical representation using Monday as the first day of the week.
373    ///
374    /// Monday is either 0 or 1, depending on the other modifier's value.
375    Monday,
376}
377
378/// Day of the week using the short form of the weekday (e.g. "Mon").
379#[derive(Debug, Clone, Copy, PartialEq, Eq)]
380pub struct WeekdayShort {
381    /// Is the value case sensitive when parsing?
382    pub(crate) case_sensitive: bool,
383}
384
385impl WeekdayShort {
386    builder_methods! {
387        /// Set whether the value is case sensitive when parsing.
388        fn with_case_sensitive(case_sensitive: bool);
389    }
390}
391
392/// Day of the week using the long form of the weekday (e.g. "Monday").
393#[derive(Debug, Clone, Copy, PartialEq, Eq)]
394pub struct WeekdayLong {
395    /// Is the value case sensitive when parsing?
396    pub(crate) case_sensitive: bool,
397}
398
399impl WeekdayLong {
400    builder_methods! {
401        /// Set whether the value is case sensitive when parsing.
402        fn with_case_sensitive(case_sensitive: bool);
403    }
404}
405
406/// Day of the week using a numerical representation with Sunday as the first day of the week.
407#[derive(Debug, Clone, Copy, PartialEq, Eq)]
408pub struct WeekdaySunday {
409    /// Is the value zero or one-indexed?
410    pub(crate) one_indexed: bool,
411}
412
413impl WeekdaySunday {
414    builder_methods! {
415        /// Set whether the value is one-indexed.
416        fn with_one_indexed(one_indexed: bool);
417    }
418}
419
420/// Day of the week using a numerical representation with Monday as the first day of the week.
421#[derive(Debug, Clone, Copy, PartialEq, Eq)]
422pub struct WeekdayMonday {
423    /// Is the value zero or one-indexed?
424    pub(crate) one_indexed: bool,
425}
426
427impl WeekdayMonday {
428    builder_methods! {
429        /// Set whether the value is one-indexed.
430        fn with_one_indexed(one_indexed: bool);
431    }
432}
433
434/// Day of the week.
435#[non_exhaustive]
436#[allow(deprecated)]
437#[deprecated(
438    since = "0.3.48",
439    note = "use `WeekdayShort`, `WeekdayLong`, `WeekdaySunday`, or `WeekdayMonday` instead"
440)]
441#[derive(Debug, Clone, Copy, PartialEq, Eq)]
442pub struct Weekday {
443    /// What form of representation should be used?
444    pub repr: WeekdayRepr,
445    /// When using a numerical representation, should it be zero or one-indexed?
446    pub one_indexed: bool,
447    /// Is the value case sensitive when parsing?
448    pub case_sensitive: bool,
449}
450
451#[expect(deprecated)]
452impl Weekday {
453    builder_methods! {
454        /// Set the manner in which the weekday is represented.
455        fn with_repr(repr: WeekdayRepr);
456        /// Set whether the value is one-indexed when using a numerical representation.
457        fn with_one_indexed(one_indexed: bool);
458        /// Set whether the value is case sensitive when parsing.
459        fn with_case_sensitive(case_sensitive: bool);
460    }
461}
462
463/// The representation used for the week number.
464#[non_exhaustive]
465#[deprecated(
466    since = "0.3.48",
467    note = "used only in the deprecated `WeekNumber` component"
468)]
469#[derive(Debug, Clone, Copy, PartialEq, Eq)]
470pub enum WeekNumberRepr {
471    /// Week 1 is the week that contains January 4.
472    Iso,
473    /// Week 1 begins on the first Sunday of the calendar year.
474    Sunday,
475    /// Week 1 begins on the first Monday of the calendar year.
476    Monday,
477}
478
479/// Week within the year using the ISO week calendar.
480///
481/// Week 1 is the week that contains January 4. All weeks begin on a Monday.
482#[derive(Debug, Clone, Copy, PartialEq, Eq)]
483pub struct WeekNumberIso {
484    /// The padding to obtain the minimum width.
485    pub padding: Padding,
486}
487
488impl WeekNumberIso {
489    builder_methods! {
490        /// Set the padding type.
491        fn with_padding(padding: Padding);
492    }
493}
494
495/// Week within the calendar year.
496///
497/// Week 1 begins on the first Sunday of the calendar year.
498#[derive(Debug, Clone, Copy, PartialEq, Eq)]
499pub struct WeekNumberSunday {
500    /// The padding to obtain the minimum width.
501    pub padding: Padding,
502}
503
504impl WeekNumberSunday {
505    builder_methods! {
506        /// Set the padding type.
507        fn with_padding(padding: Padding);
508    }
509}
510
511/// Week within the calendar year.
512///
513/// Week 1 begins on the first Monday of the calendar year.
514#[derive(Debug, Clone, Copy, PartialEq, Eq)]
515pub struct WeekNumberMonday {
516    /// The padding to obtain the minimum width.
517    pub padding: Padding,
518}
519
520impl WeekNumberMonday {
521    builder_methods! {
522        /// Set the padding type.
523        fn with_padding(padding: Padding);
524    }
525}
526
527/// Week within the year.
528#[non_exhaustive]
529#[allow(deprecated)]
530#[deprecated(
531    since = "0.3.48",
532    note = "use `WeekNumberIso`, `WeekNumberSunday`, or `WeekNumberMonday` instead"
533)]
534#[derive(Debug, Clone, Copy, PartialEq, Eq)]
535pub struct WeekNumber {
536    /// The padding to obtain the minimum width.
537    pub padding: Padding,
538    /// What kind of representation should be used?
539    pub repr: WeekNumberRepr,
540}
541
542#[expect(deprecated)]
543impl WeekNumber {
544    builder_methods! {
545        /// Set the padding type.
546        fn with_padding(padding: Padding);
547        /// Set the manner in which the week number is represented.
548        fn with_repr(repr: WeekNumberRepr);
549    }
550}
551
552/// The representation used for a year value.
553#[non_exhaustive]
554#[deprecated(
555    since = "0.3.48",
556    note = "used only in the deprecated `Year` component"
557)]
558#[derive(Debug, Clone, Copy, PartialEq, Eq)]
559pub enum YearRepr {
560    /// The full value of the year.
561    Full,
562    /// All digits except the last two. Includes the sign, if any.
563    Century,
564    /// Only the last two digits of the year.
565    LastTwo,
566}
567
568/// The range of years that are supported.
569///
570/// This modifier has no effect when the year repr is [`LastTwo`](YearRepr::LastTwo).
571#[non_exhaustive]
572#[deprecated(
573    since = "0.3.48",
574    note = "used only in the deprecated `Year` component"
575)]
576#[derive(Debug, Clone, Copy, PartialEq, Eq)]
577pub enum YearRange {
578    /// Years between -9999 and 9999 are supported.
579    Standard,
580    /// Years between -999_999 and 999_999 are supported, with the sign being required if the year
581    /// contains more than four digits.
582    ///
583    /// If the `large-dates` feature is not enabled, this variant is equivalent to `Standard`.
584    Extended,
585}
586
587/// Year of the date. All digits are included, the calendar year is used, and the range of years
588/// supported is ±999,999.
589#[derive(Debug, Clone, Copy, PartialEq, Eq)]
590pub struct CalendarYearFullExtendedRange {
591    /// The padding to obtain the minimum width.
592    pub(crate) padding: Padding,
593    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
594    /// necessary.
595    pub(crate) sign_is_mandatory: bool,
596}
597
598impl CalendarYearFullExtendedRange {
599    builder_methods! {
600        /// Set the padding type.
601        fn with_padding(padding: Padding);
602        /// Set whether the `+` sign is mandatory for non-negative years with more than four digits.
603        fn with_sign_is_mandatory(sign_is_mandatory: bool);
604    }
605}
606
607/// Year of the date. All digits are included, the calendar year is used, and the range of years
608/// supported is ±9,999.
609#[derive(Debug, Clone, Copy, PartialEq, Eq)]
610pub struct CalendarYearFullStandardRange {
611    /// The padding to obtain the minimum width.
612    pub(crate) padding: Padding,
613    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
614    /// necessary.
615    pub(crate) sign_is_mandatory: bool,
616}
617
618impl CalendarYearFullStandardRange {
619    builder_methods! {
620        /// Set the padding type.
621        fn with_padding(padding: Padding);
622        /// Set whether the `+` sign is present on non-negative years.
623        fn with_sign_is_mandatory(sign_is_mandatory: bool);
624    }
625}
626
627/// Year of the date. All digits are included, the ISO week-numbering year is used, and the range of
628/// years supported is ±999,999.
629#[derive(Debug, Clone, Copy, PartialEq, Eq)]
630pub struct IsoYearFullExtendedRange {
631    /// The padding to obtain the minimum width.
632    pub(crate) padding: Padding,
633    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
634    /// necessary.
635    pub(crate) sign_is_mandatory: bool,
636}
637
638impl IsoYearFullExtendedRange {
639    builder_methods! {
640        /// Set the padding type.
641        fn with_padding(padding: Padding);
642        /// Set whether the `+` sign is mandatory for non-negative years with more than four digits.
643        fn with_sign_is_mandatory(sign_is_mandatory: bool);
644    }
645}
646
647/// Year of the date. All digits are included, the ISO week-numbering year is used, and the range of
648/// supported is ±9,999.
649#[derive(Debug, Clone, Copy, PartialEq, Eq)]
650pub struct IsoYearFullStandardRange {
651    /// The padding to obtain the minimum width.
652    pub(crate) padding: Padding,
653    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
654    /// necessary.
655    pub(crate) sign_is_mandatory: bool,
656}
657
658impl IsoYearFullStandardRange {
659    builder_methods! {
660        /// Set the padding type.
661        fn with_padding(padding: Padding);
662        /// Set whether the `+` sign is present on non-negative years.
663        fn with_sign_is_mandatory(sign_is_mandatory: bool);
664    }
665}
666
667/// Year of the date. Only the century is included (i.e. all digits except the last two), the
668/// calendar year is used, and the range of years supported is ±999,999.
669#[derive(Debug, Clone, Copy, PartialEq, Eq)]
670pub struct CalendarYearCenturyExtendedRange {
671    /// The padding to obtain the minimum width.
672    pub(crate) padding: Padding,
673    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
674    /// necessary.
675    pub(crate) sign_is_mandatory: bool,
676}
677
678impl CalendarYearCenturyExtendedRange {
679    builder_methods! {
680        /// Set the padding type.
681        fn with_padding(padding: Padding);
682        /// Set whether the `+` sign is mandatory for non-negative years with more than four digits.
683        fn with_sign_is_mandatory(sign_is_mandatory: bool);
684    }
685}
686
687/// Year of the date. Only the century is included (i.e. all digits except the last two), the
688/// calendar year is used, and the range of years supported is ±9,999.
689#[derive(Debug, Clone, Copy, PartialEq, Eq)]
690pub struct CalendarYearCenturyStandardRange {
691    /// The padding to obtain the minimum width.
692    pub(crate) padding: Padding,
693    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
694    /// necessary.
695    pub(crate) sign_is_mandatory: bool,
696}
697
698impl CalendarYearCenturyStandardRange {
699    builder_methods! {
700        /// Set the padding type.
701        fn with_padding(padding: Padding);
702        /// Set whether the `+` sign is present on non-negative years.
703        fn with_sign_is_mandatory(sign_is_mandatory: bool);
704    }
705}
706
707/// Year of the date. Only the century is included (i.e. all digits except the last two), the ISO
708/// week-numbering year is used, and the range of years supported is ±999,999.
709#[derive(Debug, Clone, Copy, PartialEq, Eq)]
710pub struct IsoYearCenturyExtendedRange {
711    /// The padding to obtain the minimum width.
712    pub(crate) padding: Padding,
713    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
714    /// necessary.
715    pub(crate) sign_is_mandatory: bool,
716}
717
718impl IsoYearCenturyExtendedRange {
719    builder_methods! {
720        /// Set the padding type.
721        fn with_padding(padding: Padding);
722        /// Set whether the `+` sign is mandatory for non-negative years with more than four digits.
723        fn with_sign_is_mandatory(sign_is_mandatory: bool);
724    }
725}
726
727/// Year of the date. Only the century is included (i.e. all digits except the last two), the ISO
728/// week-numbering year is used, and the range of years supported is ±9,999.
729#[derive(Debug, Clone, Copy, PartialEq, Eq)]
730pub struct IsoYearCenturyStandardRange {
731    /// The padding to obtain the minimum width.
732    pub(crate) padding: Padding,
733    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
734    /// necessary.
735    pub(crate) sign_is_mandatory: bool,
736}
737
738impl IsoYearCenturyStandardRange {
739    builder_methods! {
740        /// Set the padding type.
741        fn with_padding(padding: Padding);
742        /// Set whether the `+` sign is present on non-negative years.
743        fn with_sign_is_mandatory(sign_is_mandatory: bool);
744    }
745}
746
747/// Year of the date. Only the last two digits are included, and the calendar year is used.
748#[non_exhaustive]
749#[derive(Debug, Clone, Copy, PartialEq, Eq)]
750pub struct CalendarYearLastTwo {
751    /// The padding to obtain the minimum width.
752    pub(crate) padding: Padding,
753}
754
755impl CalendarYearLastTwo {
756    builder_methods! {
757        /// Set the padding type.
758        fn with_padding(padding: Padding);
759    }
760}
761
762/// Year of the date. Only the last two digits are included, and the ISO week-numbering year is
763/// used.
764#[non_exhaustive]
765#[derive(Debug, Clone, Copy, PartialEq, Eq)]
766pub struct IsoYearLastTwo {
767    /// The padding to obtain the minimum width.
768    pub(crate) padding: Padding,
769}
770
771impl IsoYearLastTwo {
772    builder_methods! {
773        /// Set the padding type.
774        fn with_padding(padding: Padding);
775    }
776}
777
778/// Year of the date.
779#[non_exhaustive]
780#[allow(deprecated)]
781#[deprecated(
782    since = "0.3.48",
783    note = "use one of the various `Year*` components instead"
784)]
785#[derive(Debug, Clone, Copy, PartialEq, Eq)]
786pub struct Year {
787    /// The padding to obtain the minimum width.
788    pub padding: Padding,
789    /// What kind of representation should be used?
790    pub repr: YearRepr,
791    /// What range of years is supported?
792    pub range: YearRange,
793    /// Whether the value is based on the ISO week number or the Gregorian calendar.
794    pub iso_week_based: bool,
795    /// Whether the `+` sign is present when a non-negative year contains fewer digits than
796    /// necessary.
797    pub sign_is_mandatory: bool,
798}
799
800#[expect(deprecated)]
801impl Year {
802    builder_methods! {
803        /// Set the padding type.
804        fn with_padding(padding: Padding);
805        /// Set the manner in which the year is represented.
806        fn with_repr(repr: YearRepr);
807        /// Set the range of years that are supported.
808        fn with_range(range: YearRange);
809        /// Set whether the year is based on the ISO week number.
810        fn with_iso_week_based(iso_week_based: bool);
811        /// Set whether the `+` sign is mandatory for positive years with fewer than five digits.
812        fn with_sign_is_mandatory(sign_is_mandatory: bool);
813    }
814}
815
816/// Hour of the day using a 12-hour clock.
817#[derive(Debug, Clone, Copy, PartialEq, Eq)]
818pub struct Hour12 {
819    /// The padding to obtain the minimum width.
820    pub(crate) padding: Padding,
821}
822
823impl Hour12 {
824    builder_methods! {
825        /// Set the padding type.
826        fn with_padding(padding: Padding);
827    }
828}
829
830/// Hour of the day using a 24-hour clock.
831#[derive(Debug, Clone, Copy, PartialEq, Eq)]
832pub struct Hour24 {
833    /// The padding to obtain the minimum width.
834    pub(crate) padding: Padding,
835}
836
837impl Hour24 {
838    builder_methods! {
839        /// Set the padding type.
840        fn with_padding(padding: Padding);
841    }
842}
843
844/// Hour of the day.
845#[non_exhaustive]
846#[deprecated(since = "0.3.48", note = "use `Hour12` or `Hour24` instead")]
847#[derive(Debug, Clone, Copy, PartialEq, Eq)]
848pub struct Hour {
849    /// The padding to obtain the minimum width.
850    pub padding: Padding,
851    /// Is the hour displayed using a 12 or 24-hour clock?
852    pub is_12_hour_clock: bool,
853}
854
855#[expect(deprecated)]
856impl Hour {
857    builder_methods! {
858        /// Set the padding type.
859        fn with_padding(padding: Padding);
860        /// Set whether the hour uses a 12-hour clock.
861        fn with_is_12_hour_clock(is_12_hour_clock: bool);
862    }
863}
864
865/// Minute within the hour.
866#[non_exhaustive]
867#[derive(Debug, Clone, Copy, PartialEq, Eq)]
868pub struct Minute {
869    /// The padding to obtain the minimum width.
870    pub padding: Padding,
871}
872
873impl Minute {
874    builder_methods! {
875        /// Set the padding type.
876        fn with_padding(padding: Padding);
877    }
878}
879
880/// AM/PM part of the time.
881#[non_exhaustive]
882#[derive(Debug, Clone, Copy, PartialEq, Eq)]
883pub struct Period {
884    /// Is the period uppercase or lowercase?
885    pub is_uppercase: bool,
886    /// Is the value case sensitive when parsing?
887    ///
888    /// Note that when `false`, the `is_uppercase` field has no effect on parsing behavior.
889    pub case_sensitive: bool,
890}
891
892impl Period {
893    builder_methods! {
894        /// Set whether the period is uppercase.
895        fn with_is_uppercase(is_uppercase: bool);
896        /// Set whether the value is case sensitive when parsing.
897        fn with_case_sensitive(case_sensitive: bool);
898    }
899}
900
901/// Second within the minute.
902#[non_exhaustive]
903#[derive(Debug, Clone, Copy, PartialEq, Eq)]
904pub struct Second {
905    /// The padding to obtain the minimum width.
906    pub padding: Padding,
907}
908
909impl Second {
910    builder_methods! {
911        /// Set the padding type.
912        fn with_padding(padding: Padding);
913    }
914}
915
916/// The number of digits present in a subsecond representation.
917#[non_exhaustive]
918#[derive(Debug, Clone, Copy, PartialEq, Eq)]
919pub enum SubsecondDigits {
920    /// Exactly one digit.
921    One,
922    /// Exactly two digits.
923    Two,
924    /// Exactly three digits.
925    Three,
926    /// Exactly four digits.
927    Four,
928    /// Exactly five digits.
929    Five,
930    /// Exactly six digits.
931    Six,
932    /// Exactly seven digits.
933    Seven,
934    /// Exactly eight digits.
935    Eight,
936    /// Exactly nine digits.
937    Nine,
938    /// Any number of digits (up to nine) that is at least one. When formatting, the minimum digits
939    /// necessary will be used.
940    OneOrMore,
941}
942
943/// Subsecond within the second.
944#[non_exhaustive]
945#[derive(Debug, Clone, Copy, PartialEq, Eq)]
946pub struct Subsecond {
947    /// How many digits are present in the component?
948    pub digits: SubsecondDigits,
949}
950
951impl Subsecond {
952    builder_methods! {
953        /// Set the number of digits present in the subsecond representation.
954        fn with_digits(digits: SubsecondDigits);
955    }
956}
957
958/// Hour of the UTC offset.
959#[non_exhaustive]
960#[derive(Debug, Clone, Copy, PartialEq, Eq)]
961pub struct OffsetHour {
962    /// Whether the `+` sign is present on positive values.
963    pub sign_is_mandatory: bool,
964    /// The padding to obtain the minimum width.
965    pub padding: Padding,
966}
967
968impl OffsetHour {
969    builder_methods! {
970        /// Set whether the `+` sign is mandatory for positive values.
971        fn with_sign_is_mandatory(sign_is_mandatory: bool);
972        /// Set the padding type.
973        fn with_padding(padding: Padding);
974    }
975}
976
977/// Minute within the hour of the UTC offset.
978#[non_exhaustive]
979#[derive(Debug, Clone, Copy, PartialEq, Eq)]
980pub struct OffsetMinute {
981    /// The padding to obtain the minimum width.
982    pub padding: Padding,
983}
984
985impl OffsetMinute {
986    builder_methods! {
987        /// Set the padding type.
988        fn with_padding(padding: Padding);
989    }
990}
991
992/// Second within the minute of the UTC offset.
993#[non_exhaustive]
994#[derive(Debug, Clone, Copy, PartialEq, Eq)]
995pub struct OffsetSecond {
996    /// The padding to obtain the minimum width.
997    pub padding: Padding,
998}
999
1000impl OffsetSecond {
1001    builder_methods! {
1002        /// Set the padding type.
1003        fn with_padding(padding: Padding);
1004    }
1005}
1006
1007/// Type of padding to ensure a minimum width.
1008#[non_exhaustive]
1009#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1010pub enum Padding {
1011    /// A space character (` `) should be used as padding.
1012    Space,
1013    /// A zero character (`0`) should be used as padding.
1014    Zero,
1015    /// There is no padding. This can result in a width below the otherwise minimum number of
1016    /// characters.
1017    None,
1018}
1019
1020/// Ignore some number of bytes.
1021///
1022/// This has no effect when formatting.
1023#[non_exhaustive]
1024#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1025pub struct Ignore {
1026    /// The number of bytes to ignore.
1027    pub count: NonZero<u16>,
1028}
1029
1030// Needed as `Default` is deliberately not implemented for `Ignore`. The number of bytes to ignore
1031// must be explicitly provided.
1032impl Ignore {
1033    /// Create an instance of `Ignore` with the provided number of bytes to ignore.
1034    #[inline]
1035    pub const fn count(count: NonZero<u16>) -> Self {
1036        Self { count }
1037    }
1038
1039    builder_methods! {
1040        /// Set the number of bytes to ignore.
1041        fn with_count(count: NonZero<u16>);
1042    }
1043}
1044
1045/// The precision of a Unix timestamp.
1046#[non_exhaustive]
1047#[deprecated(
1048    since = "0.3.48",
1049    note = "only used in the deprecated `UnixTimestamp` component"
1050)]
1051#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1052pub enum UnixTimestampPrecision {
1053    /// Seconds since the Unix epoch.
1054    Second,
1055    /// Milliseconds since the Unix epoch.
1056    Millisecond,
1057    /// Microseconds since the Unix epoch.
1058    Microsecond,
1059    /// Nanoseconds since the Unix epoch.
1060    Nanosecond,
1061}
1062
1063/// A Unix timestamp in seconds.
1064#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1065pub struct UnixTimestampSecond {
1066    /// Whether the `+` sign must be present for a non-negative timestamp.
1067    pub(crate) sign_is_mandatory: bool,
1068}
1069
1070impl UnixTimestampSecond {
1071    builder_methods! {
1072        /// Set whether the `+` sign is mandatory for non-negative timestamps.
1073        fn with_sign_is_mandatory(sign_is_mandatory: bool);
1074    }
1075}
1076
1077/// A Unix timestamp in milliseconds.
1078#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1079pub struct UnixTimestampMillisecond {
1080    /// Whether the `+` sign must be present for a non-negative timestamp.
1081    pub(crate) sign_is_mandatory: bool,
1082}
1083
1084impl UnixTimestampMillisecond {
1085    builder_methods! {
1086        /// Set whether the `+` sign is mandatory for non-negative timestamps.
1087        fn with_sign_is_mandatory(sign_is_mandatory: bool);
1088    }
1089}
1090
1091/// A Unix timestamp in microseconds.
1092#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1093pub struct UnixTimestampMicrosecond {
1094    /// Whether the `+` sign must be present for a non-negative timestamp.
1095    pub(crate) sign_is_mandatory: bool,
1096}
1097
1098impl UnixTimestampMicrosecond {
1099    builder_methods! {
1100        /// Set whether the `+` sign is mandatory for non-negative timestamps.
1101        fn with_sign_is_mandatory(sign_is_mandatory: bool);
1102    }
1103}
1104
1105/// A Unix timestamp in nanoseconds.
1106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1107pub struct UnixTimestampNanosecond {
1108    /// Whether the `+` sign must be present for a non-negative timestamp.
1109    pub(crate) sign_is_mandatory: bool,
1110}
1111
1112impl UnixTimestampNanosecond {
1113    builder_methods! {
1114        /// Set whether the `+` sign is mandatory for non-negative timestamps.
1115        fn with_sign_is_mandatory(sign_is_mandatory: bool);
1116    }
1117}
1118
1119/// A Unix timestamp.
1120#[non_exhaustive]
1121#[allow(deprecated)]
1122#[deprecated(
1123    since = "0.3.48",
1124    note = "use `UnixTimestampSeconds`, `UnixTimestampMilliseconds`, `UnixTimestampMicroseconds`, \
1125            or `UnixTimestampNanoseconds` instead"
1126)]
1127#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1128pub struct UnixTimestamp {
1129    /// The precision of the timestamp.
1130    pub precision: UnixTimestampPrecision,
1131    /// Whether the `+` sign must be present for a non-negative timestamp.
1132    pub sign_is_mandatory: bool,
1133}
1134
1135#[expect(deprecated)]
1136impl UnixTimestamp {
1137    builder_methods! {
1138        /// Set the precision of the timestamp.
1139        fn with_precision(precision: UnixTimestampPrecision);
1140        /// Set whether the `+` sign is mandatory for non-negative timestamps.
1141        fn with_sign_is_mandatory(sign_is_mandatory: bool);
1142    }
1143}
1144
1145/// Whether trailing input after the declared end is permitted.
1146#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1147pub enum TrailingInput {
1148    /// Trailing input is not permitted and will cause an error.
1149    Prohibit,
1150    /// Trailing input is permitted but discarded.
1151    Discard,
1152}
1153
1154/// The end of input.
1155#[non_exhaustive]
1156#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1157pub struct End {
1158    /// How to handle any input after this component.
1159    pub(crate) trailing_input: TrailingInput,
1160}
1161
1162impl End {
1163    builder_methods! {
1164        /// Set how to handle any input after this component.
1165        fn with_trailing_input(trailing_input: TrailingInput);
1166    }
1167}