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}