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}