Skip to main content

time/parsing/
parsed.rs

1//! Information parsed from an input and format description.
2
3use core::num::NonZero;
4
5use deranged::{
6    Option_ri8, Option_ri16, Option_ri32, Option_ri128, Option_ru8, Option_ru16, Option_ru32, ri8,
7    ri16, ri32, ri128, ru8, ru16, ru32,
8};
9use num_conv::prelude::*;
10
11use crate::date::{MAX_YEAR, MIN_YEAR};
12use crate::error::TryFromParsed::InsufficientInformation;
13use crate::format_description::__private::{Component as ComponentV3, FormatDescriptionV3Inner};
14#[cfg(feature = "alloc")]
15use crate::format_description::OwnedFormatItem;
16use crate::format_description::{BorrowedFormatItem, Component, Period};
17use crate::internal_macros::{bug, const_try_opt};
18use crate::parsing::ParsedItem;
19use crate::parsing::component::{
20    parse_calendar_year_century_extended_range, parse_calendar_year_century_standard_range,
21    parse_calendar_year_full_extended_range, parse_calendar_year_full_standard_range,
22    parse_calendar_year_last_two, parse_day, parse_end, parse_hour_12, parse_hour_24, parse_ignore,
23    parse_iso_year_century_extended_range, parse_iso_year_century_standard_range,
24    parse_iso_year_full_extended_range, parse_iso_year_full_standard_range,
25    parse_iso_year_last_two, parse_minute, parse_month_long, parse_month_numerical,
26    parse_month_short, parse_offset_hour, parse_offset_minute, parse_offset_second, parse_ordinal,
27    parse_period, parse_second, parse_subsecond, parse_unix_timestamp_microsecond,
28    parse_unix_timestamp_millisecond, parse_unix_timestamp_nanosecond, parse_unix_timestamp_second,
29    parse_week_number_iso, parse_week_number_monday, parse_week_number_sunday, parse_weekday_long,
30    parse_weekday_monday, parse_weekday_short, parse_weekday_sunday,
31};
32use crate::unit::{Day, Hour, Minute, Nanosecond, Second};
33use crate::{
34    Date, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset, Weekday, error,
35};
36
37/// Sealed to prevent downstream implementations.
38mod sealed {
39    use super::*;
40
41    /// A trait to allow `parse_item` to be generic.
42    pub trait AnyFormatItem {
43        /// Parse a single item, returning the remaining input on success.
44        fn parse_item<'a>(
45            &self,
46            parsed: &mut Parsed,
47            input: &'a [u8],
48        ) -> Result<&'a [u8], error::ParseFromDescription>;
49    }
50}
51
52impl sealed::AnyFormatItem for BorrowedFormatItem<'_> {
53    #[inline(always)]
54    fn parse_item<'a>(
55        &self,
56        parsed: &mut Parsed,
57        input: &'a [u8],
58    ) -> Result<&'a [u8], error::ParseFromDescription> {
59        match self {
60            #[expect(deprecated)]
61            Self::Literal(literal) => Parsed::parse_literal(input, literal),
62            Self::StringLiteral(literal) => Parsed::parse_literal(input, literal.as_bytes()),
63            Self::Component(component) => parsed.parse_component(input, *component),
64            Self::Compound(compound) => parsed.parse_items(input, compound),
65            Self::Optional(item) => parsed.parse_item(input, *item).or(Ok(input)),
66            Self::First(items) => {
67                let mut first_err = None;
68
69                for item in items.iter() {
70                    match parsed.parse_item(input, item) {
71                        Ok(remaining_input) => return Ok(remaining_input),
72                        Err(err) if first_err.is_none() => first_err = Some(err),
73                        Err(_) => {}
74                    }
75                }
76
77                match first_err {
78                    Some(err) => Err(err),
79                    // This location will be reached if the slice is empty, skipping the `for` loop.
80                    // As this case is expected to be uncommon, there's no need to check up front.
81                    None => Ok(input),
82                }
83            }
84        }
85    }
86}
87
88#[cfg(feature = "alloc")]
89impl sealed::AnyFormatItem for OwnedFormatItem {
90    #[inline]
91    fn parse_item<'a>(
92        &self,
93        parsed: &mut Parsed,
94        input: &'a [u8],
95    ) -> Result<&'a [u8], error::ParseFromDescription> {
96        match self {
97            #[expect(deprecated)]
98            Self::Literal(literal) => Parsed::parse_literal(input, literal),
99            Self::StringLiteral(literal) => Parsed::parse_literal(input, literal.as_bytes()),
100            Self::Component(component) => parsed.parse_component(input, *component),
101            Self::Compound(compound) => parsed.parse_items(input, compound),
102            Self::Optional(item) => parsed.parse_item(input, item.as_ref()).or(Ok(input)),
103            Self::First(items) => {
104                let mut first_err = None;
105
106                for item in items.iter() {
107                    match parsed.parse_item(input, item) {
108                        Ok(remaining_input) => return Ok(remaining_input),
109                        Err(err) if first_err.is_none() => first_err = Some(err),
110                        Err(_) => {}
111                    }
112                }
113
114                match first_err {
115                    Some(err) => Err(err),
116                    // This location will be reached if the slice is empty, skipping the `for` loop.
117                    // As this case is expected to be uncommon, there's no need to check up front.
118                    None => Ok(input),
119                }
120            }
121        }
122    }
123}
124
125/// All information parsed.
126///
127/// This information is directly used to construct the final values.
128///
129/// Most users will not need think about this struct in any way. It is public to allow for manual
130/// control over values, in the instance that the default parser is insufficient.
131#[derive(Debug, Clone, Copy)]
132pub struct Parsed {
133    /// Calendar year.
134    year: Option_ri32<{ MIN_YEAR }, { MAX_YEAR }>,
135    /// All digits except the last two of the calendar year.
136    year_century: Option_ri16<{ (MIN_YEAR / 100) as i16 }, { (MAX_YEAR / 100) as i16 }>,
137    /// The last two digits of the calendar year.
138    year_last_two: Option_ru8<0, 99>,
139    /// Year of the [ISO week date](https://en.wikipedia.org/wiki/ISO_week_date).
140    iso_year: Option_ri32<{ MIN_YEAR }, { MAX_YEAR }>,
141    /// All digits except the last two of the ISO week year.
142    iso_year_century: Option_ri16<{ (MIN_YEAR / 100) as i16 }, { (MAX_YEAR / 100) as i16 }>,
143    /// The last two digits of the ISO week year.
144    iso_year_last_two: Option_ru8<0, 99>,
145    /// Month of the year.
146    month: Option<Month>,
147    /// Week of the year, where week one begins on the first Sunday of the calendar year.
148    sunday_week_number: Option_ru8<0, 53>,
149    /// Week of the year, where week one begins on the first Monday of the calendar year.
150    monday_week_number: Option_ru8<0, 53>,
151    /// Week of the year, where week one is the Monday-to-Sunday period containing January 4.
152    iso_week_number: Option_ru8<1, 53>,
153    /// Day of the week.
154    weekday: Option<Weekday>,
155    /// Day of the year.
156    ordinal: Option_ru16<1, 366>,
157    /// Day of the month.
158    day: Option_ru8<1, 31>,
159    /// Hour within the day.
160    hour_24: Option_ru8<0, { Hour::per_t::<u8>(Day) - 1 }>,
161    /// Hour within the 12-hour period (midnight to noon or vice versa). This is typically used in
162    /// conjunction with AM/PM, which is indicated by the `hour_12_is_pm` field.
163    hour_12: Option_ru8<1, 12>,
164    /// Whether the `hour_12` field indicates a time that "PM".
165    hour_12_is_pm: Option<bool>,
166    /// Minute within the hour.
167    minute: Option_ru8<0, { Minute::per_t::<u8>(Hour) - 1 }>,
168    /// Second within the minute.
169    // do not subtract one, as leap seconds may be allowed
170    second: Option_ru8<0, { Second::per_t::<u8>(Minute) }>,
171    /// Nanosecond within the second.
172    subsecond: Option_ru32<0, { Nanosecond::per_t::<u32>(Second) - 1 }>,
173    /// Whole hours of the UTC offset.
174    offset_hour: Option_ri8<-25, 25>,
175    /// Minutes within the hour of the UTC offset.
176    offset_minute:
177        Option_ri8<{ -Minute::per_t::<i8>(Hour) + 1 }, { Minute::per_t::<i8>(Hour) - 1 }>,
178    /// Seconds within the minute of the UTC offset.
179    offset_second:
180        Option_ri8<{ -Second::per_t::<i8>(Minute) + 1 }, { Second::per_t::<i8>(Minute) - 1 }>,
181    /// The Unix timestamp in nanoseconds.
182    unix_timestamp_nanos: Option_ri128<
183        {
184            OffsetDateTime::new_in_offset(Date::MIN, Time::MIDNIGHT, UtcOffset::UTC)
185                .unix_timestamp_nanos()
186        },
187        {
188            OffsetDateTime::new_in_offset(Date::MAX, Time::MAX, UtcOffset::UTC)
189                .unix_timestamp_nanos()
190        },
191    >,
192    /// Indicates whether the [`UtcOffset`] is negative. This information is obtained when parsing
193    /// the offset hour, but may not otherwise be stored due to "-0" being equivalent to "0".
194    offset_is_negative: bool,
195    /// Indicates whether the `year_century` component is negative. This information is obtained
196    /// when parsing, but may not otherwise be stored due to "-0" being equivalent to "0".
197    year_century_is_negative: bool,
198    /// Indicates whether the `iso_year_century` component is negative. This information is
199    /// obtained when parsing, but may not otherwise be stored due to "-0" being equivalent to "0".
200    iso_year_century_is_negative: bool,
201    /// Indicates whether a leap second is permitted to be parsed. This is required by some
202    /// well-known formats.
203    pub(super) leap_second_allowed: bool,
204}
205
206impl Default for Parsed {
207    #[inline]
208    fn default() -> Self {
209        Self::new()
210    }
211}
212
213impl Parsed {
214    /// Create a new instance of `Parsed` with no information known.
215    #[inline]
216    pub const fn new() -> Self {
217        Self {
218            year: Option_ri32::None,
219            year_century: Option_ri16::None,
220            year_last_two: Option_ru8::None,
221            iso_year: Option_ri32::None,
222            iso_year_century: Option_ri16::None,
223            iso_year_last_two: Option_ru8::None,
224            month: None,
225            sunday_week_number: Option_ru8::None,
226            monday_week_number: Option_ru8::None,
227            iso_week_number: Option_ru8::None,
228            weekday: None,
229            ordinal: Option_ru16::None,
230            day: Option_ru8::None,
231            hour_24: Option_ru8::None,
232            hour_12: Option_ru8::None,
233            hour_12_is_pm: None,
234            minute: Option_ru8::None,
235            second: Option_ru8::None,
236            subsecond: Option_ru32::None,
237            offset_hour: Option_ri8::None,
238            offset_minute: Option_ri8::None,
239            offset_second: Option_ri8::None,
240            unix_timestamp_nanos: Option_ri128::None,
241            offset_is_negative: false,
242            year_century_is_negative: false,
243            iso_year_century_is_negative: false,
244            leap_second_allowed: false,
245        }
246    }
247
248    /// Parse a [`FormatDescriptionV3Inner`], mutating the struct. The remaining input is returned
249    /// as the `Ok` value.
250    #[inline]
251    pub(crate) fn parse_v3_inner<'a>(
252        &mut self,
253        mut input: &'a [u8],
254        format_description: &FormatDescriptionV3Inner<'_>,
255    ) -> Result<&'a [u8], error::ParseFromDescription> {
256        match format_description {
257            FormatDescriptionV3Inner::Component(component) => {
258                self.parse_component_v3(input, *component)
259            }
260            FormatDescriptionV3Inner::BorrowedLiteral(literal) => {
261                Self::parse_literal(input, literal.as_bytes())
262            }
263            FormatDescriptionV3Inner::BorrowedCompound(items) => {
264                let mut this = *self;
265                for item in *items {
266                    input = this.parse_v3_inner(input, item)?;
267                }
268                *self = this;
269                Ok(input)
270            }
271            FormatDescriptionV3Inner::BorrowedOptional { format: _, item } => {
272                self.parse_v3_inner(input, item).or(Ok(input))
273            }
274            FormatDescriptionV3Inner::BorrowedFirst(items) => {
275                let mut first_err = None;
276
277                for item in items.iter() {
278                    match self.parse_v3_inner(input, item) {
279                        Ok(remaining_input) => return Ok(remaining_input),
280                        Err(err) if first_err.is_none() => first_err = Some(err),
281                        Err(_) => {}
282                    }
283                }
284
285                match first_err {
286                    Some(err) => Err(err),
287                    // This location will be reached if the slice is empty, skipping the `for` loop.
288                    // As this case is expected to be uncommon, there's no need to check up front.
289                    None => Ok(input),
290                }
291            }
292            #[cfg(feature = "alloc")]
293            FormatDescriptionV3Inner::OwnedLiteral(literal) => {
294                Self::parse_literal(input, literal.as_bytes())
295            }
296            #[cfg(feature = "alloc")]
297            FormatDescriptionV3Inner::OwnedCompound(items) => {
298                let mut this = *self;
299                for item in items {
300                    input = this.parse_v3_inner(input, item)?;
301                }
302                *self = this;
303                Ok(input)
304            }
305            #[cfg(feature = "alloc")]
306            FormatDescriptionV3Inner::OwnedOptional { format: _, item } => {
307                self.parse_v3_inner(input, item).or(Ok(input))
308            }
309            #[cfg(feature = "alloc")]
310            FormatDescriptionV3Inner::OwnedFirst(items) => {
311                let mut first_err = None;
312
313                for item in items {
314                    match self.parse_v3_inner(input, item) {
315                        Ok(remaining_input) => return Ok(remaining_input),
316                        Err(err) if first_err.is_none() => first_err = Some(err),
317                        Err(_) => {}
318                    }
319                }
320
321                match first_err {
322                    Some(err) => Err(err),
323                    // This location will be reached if the slice is empty, skipping the `for` loop.
324                    // As this case is expected to be uncommon, there's no need to check up front.
325                    None => Ok(input),
326                }
327            }
328        }
329    }
330
331    /// Parse a single component, mutating the struct. The remaining input is returned as the `Ok`
332    /// value.
333    #[inline]
334    fn parse_component_v3<'a>(
335        &mut self,
336        input: &'a [u8],
337        component: ComponentV3,
338    ) -> Result<&'a [u8], error::ParseFromDescription> {
339        use error::ParseFromDescription::InvalidComponent;
340
341        match component {
342            ComponentV3::Day(modifiers) => parse_day(input, modifiers)
343                .and_then(|parsed| parsed.consume_value(|value| self.set_day(value)))
344                .ok_or(InvalidComponent("day")),
345            ComponentV3::MonthShort(modifiers) => parse_month_short(input, modifiers)
346                .and_then(|parsed| parsed.consume_value(|value| self.set_month(value)))
347                .ok_or(InvalidComponent("month")),
348            ComponentV3::MonthLong(modifiers) => parse_month_long(input, modifiers)
349                .and_then(|parsed| parsed.consume_value(|value| self.set_month(value)))
350                .ok_or(InvalidComponent("month")),
351            ComponentV3::MonthNumerical(modifiers) => parse_month_numerical(input, modifiers)
352                .and_then(|parsed| parsed.consume_value(|value| self.set_month(value)))
353                .ok_or(InvalidComponent("month")),
354            ComponentV3::Ordinal(modifiers) => parse_ordinal(input, modifiers)
355                .and_then(|parsed| parsed.consume_value(|value| self.set_ordinal(value)))
356                .ok_or(InvalidComponent("ordinal")),
357            ComponentV3::WeekdayShort(modifiers) => parse_weekday_short(input, modifiers)
358                .and_then(|parsed| parsed.consume_value(|value| self.set_weekday(value)))
359                .ok_or(InvalidComponent("weekday")),
360            ComponentV3::WeekdayLong(modifiers) => parse_weekday_long(input, modifiers)
361                .and_then(|parsed| parsed.consume_value(|value| self.set_weekday(value)))
362                .ok_or(InvalidComponent("weekday")),
363            ComponentV3::WeekdaySunday(modifiers) => parse_weekday_sunday(input, modifiers)
364                .and_then(|parsed| parsed.consume_value(|value| self.set_weekday(value)))
365                .ok_or(InvalidComponent("weekday")),
366            ComponentV3::WeekdayMonday(modifiers) => parse_weekday_monday(input, modifiers)
367                .and_then(|parsed| parsed.consume_value(|value| self.set_weekday(value)))
368                .ok_or(InvalidComponent("weekday")),
369            ComponentV3::WeekNumberIso(modifiers) => parse_week_number_iso(input, modifiers)
370                .and_then(|parsed| {
371                    parsed.consume_value(|value| self.set_iso_week_number(NonZero::new(value)?))
372                })
373                .ok_or(InvalidComponent("week number")),
374            ComponentV3::WeekNumberSunday(modifiers) => parse_week_number_sunday(input, modifiers)
375                .and_then(|parsed| parsed.consume_value(|value| self.set_sunday_week_number(value)))
376                .ok_or(InvalidComponent("week number")),
377            ComponentV3::WeekNumberMonday(modifiers) => parse_week_number_monday(input, modifiers)
378                .and_then(|parsed| parsed.consume_value(|value| self.set_monday_week_number(value)))
379                .ok_or(InvalidComponent("week number")),
380            ComponentV3::CalendarYearFullExtendedRange(modifiers) => {
381                parse_calendar_year_full_extended_range(input, modifiers)
382                    .and_then(|parsed| parsed.consume_value(|value| self.set_year(value)))
383                    .ok_or(InvalidComponent("year"))
384            }
385            ComponentV3::CalendarYearFullStandardRange(modifiers) => {
386                parse_calendar_year_full_standard_range(input, modifiers)
387                    .and_then(|parsed| parsed.consume_value(|value| self.set_year(value)))
388                    .ok_or(InvalidComponent("year"))
389            }
390            ComponentV3::IsoYearFullExtendedRange(modifiers) => {
391                parse_iso_year_full_extended_range(input, modifiers)
392                    .and_then(|parsed| parsed.consume_value(|value| self.set_iso_year(value)))
393                    .ok_or(InvalidComponent("year"))
394            }
395            ComponentV3::IsoYearFullStandardRange(modifiers) => {
396                parse_iso_year_full_standard_range(input, modifiers)
397                    .and_then(|parsed| parsed.consume_value(|value| self.set_iso_year(value)))
398                    .ok_or(InvalidComponent("year"))
399            }
400            ComponentV3::CalendarYearCenturyExtendedRange(modifiers) => {
401                parse_calendar_year_century_extended_range(input, modifiers)
402                    .and_then(|parsed| {
403                        parsed.consume_value(|(value, is_negative)| {
404                            self.set_year_century(value, is_negative)
405                        })
406                    })
407                    .ok_or(InvalidComponent("year"))
408            }
409            ComponentV3::CalendarYearCenturyStandardRange(modifiers) => {
410                parse_calendar_year_century_standard_range(input, modifiers)
411                    .and_then(|parsed| {
412                        parsed.consume_value(|(value, is_negative)| {
413                            self.set_year_century(value, is_negative)
414                        })
415                    })
416                    .ok_or(InvalidComponent("year"))
417            }
418            ComponentV3::IsoYearCenturyExtendedRange(modifiers) => {
419                parse_iso_year_century_extended_range(input, modifiers)
420                    .and_then(|parsed| {
421                        parsed.consume_value(|(value, is_negative)| {
422                            self.set_iso_year_century(value, is_negative)
423                        })
424                    })
425                    .ok_or(InvalidComponent("year"))
426            }
427            ComponentV3::IsoYearCenturyStandardRange(modifiers) => {
428                parse_iso_year_century_standard_range(input, modifiers)
429                    .and_then(|parsed| {
430                        parsed.consume_value(|(value, is_negative)| {
431                            self.set_iso_year_century(value, is_negative)
432                        })
433                    })
434                    .ok_or(InvalidComponent("year"))
435            }
436            ComponentV3::CalendarYearLastTwo(modifiers) => {
437                parse_calendar_year_last_two(input, modifiers)
438                    .and_then(|parsed| parsed.consume_value(|value| self.set_year_last_two(value)))
439                    .ok_or(InvalidComponent("year"))
440            }
441            ComponentV3::IsoYearLastTwo(modifiers) => parse_iso_year_last_two(input, modifiers)
442                .and_then(|parsed| parsed.consume_value(|value| self.set_iso_year_last_two(value)))
443                .ok_or(InvalidComponent("year")),
444            ComponentV3::Hour12(modifiers) => parse_hour_12(input, modifiers)
445                .and_then(|parsed| {
446                    parsed.consume_value(|value| self.set_hour_12(NonZero::new(value)?))
447                })
448                .ok_or(InvalidComponent("hour")),
449            ComponentV3::Hour24(modifiers) => parse_hour_24(input, modifiers)
450                .and_then(|parsed| parsed.consume_value(|value| self.set_hour_24(value)))
451                .ok_or(InvalidComponent("hour")),
452            ComponentV3::Minute(modifiers) => parse_minute(input, modifiers)
453                .and_then(|parsed| parsed.consume_value(|value| self.set_minute(value)))
454                .ok_or(InvalidComponent("minute")),
455            ComponentV3::Period(modifiers) => parse_period(input, modifiers)
456                .and_then(|parsed| {
457                    parsed.consume_value(|value| self.set_hour_12_is_pm(value == Period::Pm))
458                })
459                .ok_or(InvalidComponent("period")),
460            ComponentV3::Second(modifiers) => parse_second(input, modifiers)
461                .and_then(|parsed| parsed.consume_value(|value| self.set_second(value)))
462                .ok_or(InvalidComponent("second")),
463            ComponentV3::Subsecond(modifiers) => parse_subsecond(input, modifiers)
464                .and_then(|parsed| parsed.consume_value(|value| self.set_subsecond(value)))
465                .ok_or(InvalidComponent("subsecond")),
466            ComponentV3::OffsetHour(modifiers) => parse_offset_hour(input, modifiers)
467                .and_then(|parsed| {
468                    parsed.consume_value(|(value, is_negative)| {
469                        self.set_offset_hour(value)?;
470                        self.offset_is_negative = is_negative;
471                        Some(())
472                    })
473                })
474                .ok_or(InvalidComponent("offset hour")),
475            ComponentV3::OffsetMinute(modifiers) => parse_offset_minute(input, modifiers)
476                .and_then(|parsed| {
477                    parsed.consume_value(|value| self.set_offset_minute_signed(value))
478                })
479                .ok_or(InvalidComponent("offset minute")),
480            ComponentV3::OffsetSecond(modifiers) => parse_offset_second(input, modifiers)
481                .and_then(|parsed| {
482                    parsed.consume_value(|value| self.set_offset_second_signed(value))
483                })
484                .ok_or(InvalidComponent("offset second")),
485            ComponentV3::Ignore(modifiers) => parse_ignore(input, modifiers)
486                .map(ParsedItem::<()>::into_inner)
487                .ok_or(InvalidComponent("ignore")),
488            ComponentV3::UnixTimestampSecond(modifiers) => {
489                parse_unix_timestamp_second(input, modifiers)
490                    .and_then(|parsed| {
491                        parsed.consume_value(|value| self.set_unix_timestamp_nanos(value))
492                    })
493                    .ok_or(InvalidComponent("unix_timestamp"))
494            }
495            ComponentV3::UnixTimestampMillisecond(modifiers) => {
496                parse_unix_timestamp_millisecond(input, modifiers)
497                    .and_then(|parsed| {
498                        parsed.consume_value(|value| self.set_unix_timestamp_nanos(value))
499                    })
500                    .ok_or(InvalidComponent("unix_timestamp"))
501            }
502            ComponentV3::UnixTimestampMicrosecond(modifiers) => {
503                parse_unix_timestamp_microsecond(input, modifiers)
504                    .and_then(|parsed| {
505                        parsed.consume_value(|value| self.set_unix_timestamp_nanos(value))
506                    })
507                    .ok_or(InvalidComponent("unix_timestamp"))
508            }
509            ComponentV3::UnixTimestampNanosecond(modifiers) => {
510                parse_unix_timestamp_nanosecond(input, modifiers)
511                    .and_then(|parsed| {
512                        parsed.consume_value(|value| self.set_unix_timestamp_nanos(value))
513                    })
514                    .ok_or(InvalidComponent("unix_timestamp"))
515            }
516            ComponentV3::End(modifiers) => parse_end(input, modifiers)
517                .map(ParsedItem::<()>::into_inner)
518                .ok_or(error::ParseFromDescription::UnexpectedTrailingCharacters),
519        }
520    }
521
522    /// Parse a single [`BorrowedFormatItem`] or [`OwnedFormatItem`], mutating the struct. The
523    /// remaining input is returned as the `Ok` value.
524    ///
525    /// If a [`BorrowedFormatItem::Optional`] or [`OwnedFormatItem::Optional`] is passed, parsing
526    /// will not fail; the input will be returned as-is if the expected format is not present.
527    #[inline]
528    pub fn parse_item<'a>(
529        &mut self,
530        input: &'a [u8],
531        item: &impl sealed::AnyFormatItem,
532    ) -> Result<&'a [u8], error::ParseFromDescription> {
533        item.parse_item(self, input)
534    }
535
536    /// Parse a sequence of [`BorrowedFormatItem`]s or [`OwnedFormatItem`]s, mutating the struct.
537    /// The remaining input is returned as the `Ok` value.
538    ///
539    /// This method will fail if any of the contained [`BorrowedFormatItem`]s or
540    /// [`OwnedFormatItem`]s fail to parse. `self` will not be mutated in this instance.
541    #[inline]
542    pub fn parse_items<'a>(
543        &mut self,
544        mut input: &'a [u8],
545        items: &[impl sealed::AnyFormatItem],
546    ) -> Result<&'a [u8], error::ParseFromDescription> {
547        // Make a copy that we can mutate. It will only be set to the user's copy if everything
548        // succeeds.
549        let mut this = *self;
550        for item in items {
551            input = this.parse_item(input, item)?;
552        }
553        *self = this;
554        Ok(input)
555    }
556
557    /// Parse a literal byte sequence. The remaining input is returned as the `Ok` value.
558    #[inline]
559    pub fn parse_literal<'a>(
560        input: &'a [u8],
561        literal: &[u8],
562    ) -> Result<&'a [u8], error::ParseFromDescription> {
563        input
564            .strip_prefix(literal)
565            .ok_or(error::ParseFromDescription::InvalidLiteral)
566    }
567
568    /// Parse a single component, mutating the struct. The remaining input is returned as the `Ok`
569    /// value.
570    #[inline]
571    pub fn parse_component<'a>(
572        &mut self,
573        input: &'a [u8],
574        component: Component,
575    ) -> Result<&'a [u8], error::ParseFromDescription> {
576        self.parse_component_v3(input, component.into())
577    }
578}
579
580/// Getter methods
581impl Parsed {
582    /// Obtain the `year` component.
583    #[inline]
584    pub const fn year(&self) -> Option<i32> {
585        self.year.get_primitive()
586    }
587
588    /// Obtain the `year_century` component.
589    ///
590    /// If the year is zero, the sign of the century is not stored. To differentiate between
591    /// positive and negative zero, use `year_century_is_negative`.
592    #[inline]
593    pub const fn year_century(&self) -> Option<i16> {
594        self.year_century.get_primitive()
595    }
596
597    /// Obtain the `year_century_is_negative` component.
598    ///
599    /// This indicates whether the value returned from `year_century` is negative. If the year is
600    /// zero, it is necessary to call this method for disambiguation.
601    #[inline]
602    pub const fn year_century_is_negative(&self) -> Option<bool> {
603        match self.year_century() {
604            Some(_) => Some(self.year_century_is_negative),
605            None => None,
606        }
607    }
608
609    /// Obtain the `year_last_two` component.
610    #[inline]
611    pub const fn year_last_two(&self) -> Option<u8> {
612        self.year_last_two.get_primitive()
613    }
614
615    /// Obtain the `iso_year` component.
616    #[inline]
617    pub const fn iso_year(&self) -> Option<i32> {
618        self.iso_year.get_primitive()
619    }
620
621    /// Obtain the `iso_year_century` component.
622    ///
623    /// If the year is zero, the sign of the century is not stored. To differentiate between
624    /// positive and negative zero, use `iso_year_century_is_negative`.
625    #[inline]
626    pub const fn iso_year_century(&self) -> Option<i16> {
627        self.iso_year_century.get_primitive()
628    }
629
630    /// Obtain the `iso_year_century_is_negative` component.
631    ///
632    /// This indicates whether the value returned from `iso_year_century` is negative. If the year
633    /// is zero, it is necessary to call this method for disambiguation.
634    #[inline]
635    pub const fn iso_year_century_is_negative(&self) -> Option<bool> {
636        match self.iso_year_century() {
637            Some(_) => Some(self.iso_year_century_is_negative),
638            None => None,
639        }
640    }
641
642    /// Obtain the `iso_year_last_two` component.
643    #[inline]
644    pub const fn iso_year_last_two(&self) -> Option<u8> {
645        self.iso_year_last_two.get_primitive()
646    }
647
648    /// Obtain the `month` component.
649    #[inline]
650    pub const fn month(&self) -> Option<Month> {
651        self.month
652    }
653
654    /// Obtain the `sunday_week_number` component.
655    #[inline]
656    pub const fn sunday_week_number(&self) -> Option<u8> {
657        self.sunday_week_number.get_primitive()
658    }
659
660    /// Obtain the `monday_week_number` component.
661    #[inline]
662    pub const fn monday_week_number(&self) -> Option<u8> {
663        self.monday_week_number.get_primitive()
664    }
665
666    /// Obtain the `iso_week_number` component.
667    #[inline]
668    pub const fn iso_week_number(&self) -> Option<NonZero<u8>> {
669        NonZero::new(const_try_opt!(self.iso_week_number.get_primitive()))
670    }
671
672    /// Obtain the `weekday` component.
673    #[inline]
674    pub const fn weekday(&self) -> Option<Weekday> {
675        self.weekday
676    }
677
678    /// Obtain the `ordinal` component.
679    #[inline]
680    pub const fn ordinal(&self) -> Option<NonZero<u16>> {
681        NonZero::new(const_try_opt!(self.ordinal.get_primitive()))
682    }
683
684    /// Obtain the `day` component.
685    #[inline]
686    pub const fn day(&self) -> Option<NonZero<u8>> {
687        NonZero::new(const_try_opt!(self.day.get_primitive()))
688    }
689
690    /// Obtain the `hour_24` component.
691    #[inline]
692    pub const fn hour_24(&self) -> Option<u8> {
693        self.hour_24.get_primitive()
694    }
695
696    /// Obtain the `hour_12` component.
697    #[inline]
698    pub const fn hour_12(&self) -> Option<NonZero<u8>> {
699        NonZero::new(const_try_opt!(self.hour_12.get_primitive()))
700    }
701
702    /// Obtain the `hour_12_is_pm` component.
703    #[inline]
704    pub const fn hour_12_is_pm(&self) -> Option<bool> {
705        self.hour_12_is_pm
706    }
707
708    /// Obtain the `minute` component.
709    #[inline]
710    pub const fn minute(&self) -> Option<u8> {
711        self.minute.get_primitive()
712    }
713
714    /// Obtain the `second` component.
715    #[inline]
716    pub const fn second(&self) -> Option<u8> {
717        self.second.get_primitive()
718    }
719
720    /// Obtain the `subsecond` component.
721    #[inline]
722    pub const fn subsecond(&self) -> Option<u32> {
723        self.subsecond.get_primitive()
724    }
725
726    /// Obtain the `offset_hour` component.
727    #[inline]
728    pub const fn offset_hour(&self) -> Option<i8> {
729        self.offset_hour.get_primitive()
730    }
731
732    /// Obtain the absolute value of the `offset_minute` component.
733    #[doc(hidden)]
734    #[deprecated(since = "0.3.8", note = "use `parsed.offset_minute_signed()` instead")]
735    #[inline]
736    pub const fn offset_minute(&self) -> Option<u8> {
737        Some(const_try_opt!(self.offset_minute_signed()).unsigned_abs())
738    }
739
740    /// Obtain the `offset_minute` component.
741    #[inline]
742    pub const fn offset_minute_signed(&self) -> Option<i8> {
743        match (self.offset_minute.get_primitive(), self.offset_is_negative) {
744            (Some(offset_minute), true) => Some(-offset_minute),
745            (Some(offset_minute), _) => Some(offset_minute),
746            (None, _) => None,
747        }
748    }
749
750    /// Obtain the absolute value of the `offset_second` component.
751    #[doc(hidden)]
752    #[deprecated(since = "0.3.8", note = "use `parsed.offset_second_signed()` instead")]
753    #[inline]
754    pub const fn offset_second(&self) -> Option<u8> {
755        Some(const_try_opt!(self.offset_second_signed()).unsigned_abs())
756    }
757
758    /// Obtain the `offset_second` component.
759    #[inline]
760    pub const fn offset_second_signed(&self) -> Option<i8> {
761        match (self.offset_second.get_primitive(), self.offset_is_negative) {
762            (Some(offset_second), true) => Some(-offset_second),
763            (Some(offset_second), _) => Some(offset_second),
764            (None, _) => None,
765        }
766    }
767
768    /// Obtain the `unix_timestamp_nanos` component.
769    #[inline]
770    pub const fn unix_timestamp_nanos(&self) -> Option<i128> {
771        self.unix_timestamp_nanos.get_primitive()
772    }
773}
774
775/// Generate setters based on the builders.
776macro_rules! setters {
777    ($($name:ident $setter:ident $builder:ident $type:ty;)*) => {$(
778        #[doc = concat!("Set the `", stringify!($name), "` component.")]
779        #[inline]
780        pub const fn $setter(&mut self, value: $type) -> Option<()> {
781            match self.$builder(value) {
782                Some(value) => {
783                    *self = value;
784                    Some(())
785                },
786                None => None,
787            }
788        }
789    )*};
790}
791
792/// Setter methods
793///
794/// All setters return `Option<()>`, which is `Some` if the value was set, and `None` if not. The
795/// setters _may_ fail if the value is invalid, though behavior is not guaranteed.
796impl Parsed {
797    setters! {
798        year set_year with_year i32;
799    }
800
801    /// Set the `year_century` component.
802    ///
803    /// If the value is zero, the sign of the century is taken from the second parameter. Otherwise
804    /// the sign is inferred from the value.
805    #[inline]
806    pub const fn set_year_century(&mut self, value: i16, is_negative: bool) -> Option<()> {
807        self.year_century = Option_ri16::Some(const_try_opt!(ri16::new(value)));
808        if value != 0 {
809            self.year_century_is_negative = value.is_negative();
810        } else {
811            self.year_century_is_negative = is_negative;
812        }
813        Some(())
814    }
815
816    setters! {
817        year_last_two set_year_last_two with_year_last_two u8;
818        iso_year set_iso_year with_iso_year i32;
819        iso_year_last_two set_iso_year_last_two with_iso_year_last_two u8;
820    }
821
822    /// Set the `iso_year_century` component.
823    ///
824    /// If the value is zero, the sign of the century is taken from the second parameter. Otherwise
825    /// the sign is inferred from the value.
826    #[inline]
827    pub const fn set_iso_year_century(&mut self, value: i16, is_negative: bool) -> Option<()> {
828        self.iso_year_century = Option_ri16::Some(const_try_opt!(ri16::new(value)));
829        if value != 0 {
830            self.iso_year_century_is_negative = value.is_negative();
831        } else {
832            self.iso_year_century_is_negative = is_negative;
833        }
834        Some(())
835    }
836
837    setters! {
838        month set_month with_month Month;
839        sunday_week_number set_sunday_week_number with_sunday_week_number u8;
840        monday_week_number set_monday_week_number with_monday_week_number u8;
841        iso_week_number set_iso_week_number with_iso_week_number NonZero<u8>;
842        weekday set_weekday with_weekday Weekday;
843        ordinal set_ordinal with_ordinal NonZero<u16>;
844        day set_day with_day NonZero<u8>;
845        hour_24 set_hour_24 with_hour_24 u8;
846        hour_12 set_hour_12 with_hour_12 NonZero<u8>;
847        hour_12_is_pm set_hour_12_is_pm with_hour_12_is_pm bool;
848        minute set_minute with_minute u8;
849        second set_second with_second u8;
850        subsecond set_subsecond with_subsecond u32;
851        offset_hour set_offset_hour with_offset_hour i8;
852        offset_minute set_offset_minute_signed with_offset_minute_signed i8;
853        offset_second set_offset_second_signed with_offset_second_signed i8;
854        unix_timestamp_nanos set_unix_timestamp_nanos with_unix_timestamp_nanos i128;
855    }
856
857    /// Set the `offset_minute` component.
858    #[doc(hidden)]
859    #[deprecated(
860        since = "0.3.8",
861        note = "use `parsed.set_offset_minute_signed()` instead"
862    )]
863    #[inline]
864    pub const fn set_offset_minute(&mut self, value: u8) -> Option<()> {
865        if value > i8::MAX.cast_unsigned() {
866            None
867        } else {
868            self.set_offset_minute_signed(value.cast_signed())
869        }
870    }
871
872    /// Set the `offset_minute` component.
873    #[doc(hidden)]
874    #[deprecated(
875        since = "0.3.8",
876        note = "use `parsed.set_offset_second_signed()` instead"
877    )]
878    #[inline]
879    pub const fn set_offset_second(&mut self, value: u8) -> Option<()> {
880        if value > i8::MAX.cast_unsigned() {
881            None
882        } else {
883            self.set_offset_second_signed(value.cast_signed())
884        }
885    }
886}
887
888/// Builder methods
889///
890/// All builder methods return `Option<Self>`, which is `Some` if the value was set, and `None` if
891/// not. The builder methods _may_ fail if the value is invalid, though behavior is not guaranteed.
892impl Parsed {
893    /// Set the `year` component and return `self`.
894    #[inline]
895    pub const fn with_year(mut self, value: i32) -> Option<Self> {
896        self.year = Option_ri32::Some(const_try_opt!(ri32::new(value)));
897        Some(self)
898    }
899
900    /// Set the `year_century` component and return `self`.
901    ///
902    /// If the value is zero, the sign of the century is taken from the second parameter. Otherwise
903    /// the sign is inferred from the value.
904    #[inline]
905    pub const fn with_year_century(mut self, value: i16, is_negative: bool) -> Option<Self> {
906        self.year_century = Option_ri16::Some(const_try_opt!(ri16::new(value)));
907        if value != 0 {
908            self.year_century_is_negative = value.is_negative();
909        } else {
910            self.year_century_is_negative = is_negative;
911        }
912        Some(self)
913    }
914
915    /// Set the `year_last_two` component and return `self`.
916    #[inline]
917    pub const fn with_year_last_two(mut self, value: u8) -> Option<Self> {
918        self.year_last_two = Option_ru8::Some(const_try_opt!(ru8::new(value)));
919        Some(self)
920    }
921
922    /// Set the `iso_year` component and return `self`.
923    #[inline]
924    pub const fn with_iso_year(mut self, value: i32) -> Option<Self> {
925        self.iso_year = Option_ri32::Some(const_try_opt!(ri32::new(value)));
926        Some(self)
927    }
928
929    /// Set the `iso_year_century` component and return `self`.
930    ///
931    /// If the value is zero, the sign of the century is taken from the second parameter. Otherwise
932    /// the sign is inferred from the value.
933    #[inline]
934    pub const fn with_iso_year_century(mut self, value: i16, is_negative: bool) -> Option<Self> {
935        self.iso_year_century = Option_ri16::Some(const_try_opt!(ri16::new(value)));
936        if value != 0 {
937            self.iso_year_century_is_negative = value.is_negative();
938        } else {
939            self.iso_year_century_is_negative = is_negative;
940        }
941        Some(self)
942    }
943
944    /// Set the `iso_year_last_two` component and return `self`.
945    #[inline]
946    pub const fn with_iso_year_last_two(mut self, value: u8) -> Option<Self> {
947        self.iso_year_last_two = Option_ru8::Some(const_try_opt!(ru8::new(value)));
948        Some(self)
949    }
950
951    /// Set the `month` component and return `self`.
952    #[inline]
953    pub const fn with_month(mut self, value: Month) -> Option<Self> {
954        self.month = Some(value);
955        Some(self)
956    }
957
958    /// Set the `sunday_week_number` component and return `self`.
959    #[inline]
960    pub const fn with_sunday_week_number(mut self, value: u8) -> Option<Self> {
961        self.sunday_week_number = Option_ru8::Some(const_try_opt!(ru8::new(value)));
962        Some(self)
963    }
964
965    /// Set the `monday_week_number` component and return `self`.
966    #[inline]
967    pub const fn with_monday_week_number(mut self, value: u8) -> Option<Self> {
968        self.monday_week_number = Option_ru8::Some(const_try_opt!(ru8::new(value)));
969        Some(self)
970    }
971
972    /// Set the `iso_week_number` component and return `self`.
973    #[inline]
974    pub const fn with_iso_week_number(mut self, value: NonZero<u8>) -> Option<Self> {
975        self.iso_week_number = Option_ru8::Some(const_try_opt!(ru8::new(value.get())));
976        Some(self)
977    }
978
979    /// Set the `weekday` component and return `self`.
980    #[inline]
981    pub const fn with_weekday(mut self, value: Weekday) -> Option<Self> {
982        self.weekday = Some(value);
983        Some(self)
984    }
985
986    /// Set the `ordinal` component and return `self`.
987    #[inline]
988    pub const fn with_ordinal(mut self, value: NonZero<u16>) -> Option<Self> {
989        self.ordinal = Option_ru16::Some(const_try_opt!(ru16::new(value.get())));
990        Some(self)
991    }
992
993    /// Set the `day` component and return `self`.
994    #[inline]
995    pub const fn with_day(mut self, value: NonZero<u8>) -> Option<Self> {
996        self.day = Option_ru8::Some(const_try_opt!(ru8::new(value.get())));
997        Some(self)
998    }
999
1000    /// Set the `hour_24` component and return `self`.
1001    #[inline]
1002    pub const fn with_hour_24(mut self, value: u8) -> Option<Self> {
1003        self.hour_24 = Option_ru8::Some(const_try_opt!(ru8::new(value)));
1004        Some(self)
1005    }
1006
1007    /// Set the `hour_12` component and return `self`.
1008    #[inline]
1009    pub const fn with_hour_12(mut self, value: NonZero<u8>) -> Option<Self> {
1010        self.hour_12 = Option_ru8::Some(const_try_opt!(ru8::new(value.get())));
1011        Some(self)
1012    }
1013
1014    /// Set the `hour_12_is_pm` component and return `self`.
1015    #[inline]
1016    pub const fn with_hour_12_is_pm(mut self, value: bool) -> Option<Self> {
1017        self.hour_12_is_pm = Some(value);
1018        Some(self)
1019    }
1020
1021    /// Set the `minute` component and return `self`.
1022    #[inline]
1023    pub const fn with_minute(mut self, value: u8) -> Option<Self> {
1024        self.minute = Option_ru8::Some(const_try_opt!(ru8::new(value)));
1025        Some(self)
1026    }
1027
1028    /// Set the `second` component and return `self`.
1029    #[inline]
1030    pub const fn with_second(mut self, value: u8) -> Option<Self> {
1031        self.second = Option_ru8::Some(const_try_opt!(ru8::new(value)));
1032        Some(self)
1033    }
1034
1035    /// Set the `subsecond` component and return `self`.
1036    #[inline]
1037    pub const fn with_subsecond(mut self, value: u32) -> Option<Self> {
1038        self.subsecond = Option_ru32::Some(const_try_opt!(ru32::new(value)));
1039        Some(self)
1040    }
1041
1042    /// Set the `offset_hour` component and return `self`.
1043    #[inline]
1044    pub const fn with_offset_hour(mut self, value: i8) -> Option<Self> {
1045        self.offset_hour = Option_ri8::Some(const_try_opt!(ri8::new(value)));
1046        Some(self)
1047    }
1048
1049    /// Set the `offset_minute` component and return `self`.
1050    #[doc(hidden)]
1051    #[deprecated(
1052        since = "0.3.8",
1053        note = "use `parsed.with_offset_minute_signed()` instead"
1054    )]
1055    #[inline]
1056    pub const fn with_offset_minute(self, value: u8) -> Option<Self> {
1057        if value > i8::MAX.cast_unsigned() {
1058            None
1059        } else {
1060            self.with_offset_minute_signed(value.cast_signed())
1061        }
1062    }
1063
1064    /// Set the `offset_minute` component and return `self`.
1065    #[inline]
1066    pub const fn with_offset_minute_signed(mut self, value: i8) -> Option<Self> {
1067        self.offset_minute = Option_ri8::Some(const_try_opt!(ri8::new(value)));
1068        Some(self)
1069    }
1070
1071    /// Set the `offset_minute` component and return `self`.
1072    #[doc(hidden)]
1073    #[deprecated(
1074        since = "0.3.8",
1075        note = "use `parsed.with_offset_second_signed()` instead"
1076    )]
1077    #[inline]
1078    pub const fn with_offset_second(self, value: u8) -> Option<Self> {
1079        if value > i8::MAX.cast_unsigned() {
1080            None
1081        } else {
1082            self.with_offset_second_signed(value.cast_signed())
1083        }
1084    }
1085
1086    /// Set the `offset_second` component and return `self`.
1087    #[inline]
1088    pub const fn with_offset_second_signed(mut self, value: i8) -> Option<Self> {
1089        self.offset_second = Option_ri8::Some(const_try_opt!(ri8::new(value)));
1090        Some(self)
1091    }
1092
1093    /// Set the `unix_timestamp_nanos` component and return `self`.
1094    #[inline]
1095    pub const fn with_unix_timestamp_nanos(mut self, value: i128) -> Option<Self> {
1096        self.unix_timestamp_nanos = Option_ri128::Some(const_try_opt!(ri128::new(value)));
1097        Some(self)
1098    }
1099}
1100
1101impl TryFrom<Parsed> for Date {
1102    type Error = error::TryFromParsed;
1103
1104    #[inline]
1105    fn try_from(mut parsed: Parsed) -> Result<Self, Self::Error> {
1106        /// Match on the components that need to be present.
1107        macro_rules! match_ {
1108            (_ => $catch_all:expr $(,)?) => {
1109                $catch_all
1110            };
1111            (($($name:ident),* $(,)?) => $arm:expr, $($rest:tt)*) => {
1112                if let ($(Some($name)),*) = ($(parsed.$name()),*) {
1113                    $arm
1114                } else {
1115                    match_!($($rest)*)
1116                }
1117            };
1118        }
1119
1120        /// Get the value needed to adjust the ordinal day for Sunday and Monday-based week
1121        /// numbering.
1122        #[inline]
1123        const fn adjustment(year: i32) -> i16 {
1124            // Safety: `ordinal` is not zero.
1125            match unsafe { Date::__from_ordinal_date_unchecked(year, 1) }.weekday() {
1126                Weekday::Monday => 7,
1127                Weekday::Tuesday => 1,
1128                Weekday::Wednesday => 2,
1129                Weekday::Thursday => 3,
1130                Weekday::Friday => 4,
1131                Weekday::Saturday => 5,
1132                Weekday::Sunday => 6,
1133            }
1134        }
1135
1136        // If we do not have the year but we have *both* the century and the last two digits, we can
1137        // construct the year. Likewise for the ISO year.
1138        if let (None, Some(century), Some(is_negative), Some(last_two)) = (
1139            parsed.year(),
1140            parsed.year_century(),
1141            parsed.year_century_is_negative(),
1142            parsed.year_last_two(),
1143        ) {
1144            let year = if is_negative {
1145                100 * century.extend::<i32>() - last_two.cast_signed().extend::<i32>()
1146            } else {
1147                100 * century.extend::<i32>() + last_two.cast_signed().extend::<i32>()
1148            };
1149            parsed.year = Option_ri32::from(ri32::new(year));
1150        }
1151        if let (None, Some(century), Some(is_negative), Some(last_two)) = (
1152            parsed.iso_year(),
1153            parsed.iso_year_century(),
1154            parsed.iso_year_century_is_negative(),
1155            parsed.iso_year_last_two(),
1156        ) {
1157            let iso_year = if is_negative {
1158                100 * century.extend::<i32>() - last_two.cast_signed().extend::<i32>()
1159            } else {
1160                100 * century.extend::<i32>() + last_two.cast_signed().extend::<i32>()
1161            };
1162            parsed.iso_year = Option_ri32::from(ri32::new(iso_year));
1163        }
1164
1165        match_! {
1166            (year, ordinal) => Ok(Self::from_ordinal_date(year, ordinal.get())?),
1167            (year, month, day) => Ok(Self::from_calendar_date(year, month, day.get())?),
1168            (iso_year, iso_week_number, weekday) => Ok(Self::from_iso_week_date(
1169                iso_year,
1170                iso_week_number.get(),
1171                weekday,
1172            )?),
1173            (year, sunday_week_number, weekday) => Ok(Self::from_ordinal_date(
1174                year,
1175                (sunday_week_number.cast_signed().extend::<i16>() * 7
1176                    + weekday.number_days_from_sunday().cast_signed().extend::<i16>()
1177                    - adjustment(year)
1178                    + 1).cast_unsigned(),
1179            )?),
1180            (year, monday_week_number, weekday) => Ok(Self::from_ordinal_date(
1181                year,
1182                (monday_week_number.cast_signed().extend::<i16>() * 7
1183                    + weekday.number_days_from_monday().cast_signed().extend::<i16>()
1184                    - adjustment(year)
1185                    + 1).cast_unsigned(),
1186            )?),
1187            _ => Err(InsufficientInformation),
1188        }
1189    }
1190}
1191
1192impl TryFrom<Parsed> for Time {
1193    type Error = error::TryFromParsed;
1194
1195    #[inline]
1196    fn try_from(parsed: Parsed) -> Result<Self, Self::Error> {
1197        let hour = match (parsed.hour_24(), parsed.hour_12(), parsed.hour_12_is_pm()) {
1198            (Some(hour), _, _) => hour,
1199            (_, Some(hour), Some(false)) if hour.get() == 12 => 0,
1200            (_, Some(hour), Some(true)) if hour.get() == 12 => 12,
1201            (_, Some(hour), Some(false)) => hour.get(),
1202            (_, Some(hour), Some(true)) => hour.get() + 12,
1203            _ => return Err(InsufficientInformation),
1204        };
1205
1206        if parsed.hour_24().is_none()
1207            && parsed.hour_12().is_some()
1208            && parsed.hour_12_is_pm().is_some()
1209            && parsed.minute().is_none()
1210            && parsed.second().is_none()
1211            && parsed.subsecond().is_none()
1212        {
1213            return Ok(Self::from_hms_nano(hour, 0, 0, 0)?);
1214        }
1215
1216        // Reject combinations such as hour-second with minute omitted.
1217        match (parsed.minute(), parsed.second(), parsed.subsecond()) {
1218            (None, None, None) => Ok(Self::from_hms_nano(hour, 0, 0, 0)?),
1219            (Some(minute), None, None) => Ok(Self::from_hms_nano(hour, minute, 0, 0)?),
1220            (Some(minute), Some(second), None) => Ok(Self::from_hms_nano(hour, minute, second, 0)?),
1221            (Some(minute), Some(second), Some(subsecond)) => {
1222                Ok(Self::from_hms_nano(hour, minute, second, subsecond)?)
1223            }
1224            _ => Err(InsufficientInformation),
1225        }
1226    }
1227}
1228
1229#[inline]
1230fn utc_offset_try_from_parsed<const REQUIRED: bool>(
1231    parsed: Parsed,
1232) -> Result<UtcOffset, error::TryFromParsed> {
1233    let hour = match (REQUIRED, parsed.offset_hour()) {
1234        // An offset is required, but the hour is missing. Return an error.
1235        (true, None) => return Err(InsufficientInformation),
1236        // An offset is not required (e.g. for `UtcDateTime`). As the hour is missing, minutes and
1237        // seconds are not parsed. This is UTC.
1238        (false, None) => return Ok(UtcOffset::UTC),
1239        // Any other situation has an hour present.
1240        (_, Some(hour)) => hour,
1241    };
1242    let minute = parsed.offset_minute_signed();
1243    // Force `second` to be `None` if `minute` is `None`.
1244    let second = minute.and_then(|_| parsed.offset_second_signed());
1245
1246    let minute = minute.unwrap_or(0);
1247    let second = second.unwrap_or(0);
1248
1249    UtcOffset::from_hms(hour, minute, second).map_err(Into::into)
1250}
1251
1252impl TryFrom<Parsed> for UtcOffset {
1253    type Error = error::TryFromParsed;
1254
1255    #[inline]
1256    fn try_from(parsed: Parsed) -> Result<Self, Self::Error> {
1257        utc_offset_try_from_parsed::<true>(parsed)
1258    }
1259}
1260
1261impl TryFrom<Parsed> for PrimitiveDateTime {
1262    type Error = error::TryFromParsed;
1263
1264    #[inline]
1265    fn try_from(parsed: Parsed) -> Result<Self, Self::Error> {
1266        Ok(Self::new(parsed.try_into()?, parsed.try_into()?))
1267    }
1268}
1269
1270impl TryFrom<Parsed> for UtcDateTime {
1271    type Error = error::TryFromParsed;
1272
1273    #[inline]
1274    fn try_from(mut parsed: Parsed) -> Result<Self, Self::Error> {
1275        if let Some(timestamp) = parsed.unix_timestamp_nanos() {
1276            let mut value = Self::from_unix_timestamp_nanos(timestamp)?;
1277            if let Some(subsecond) = parsed.subsecond() {
1278                value = value.replace_nanosecond(subsecond)?;
1279            }
1280            return Ok(value);
1281        }
1282
1283        // Some well-known formats explicitly allow leap seconds. We don't currently support them,
1284        // so treat it as the nearest preceding moment that can be represented. Because leap seconds
1285        // always fall at the end of a month UTC, reject any that are at other times.
1286        let leap_second_input = if parsed.leap_second_allowed && parsed.second() == Some(60) {
1287            if parsed.set_second(59).is_none() {
1288                bug!("59 is a valid second");
1289            }
1290            if parsed.set_subsecond(999_999_999).is_none() {
1291                bug!("999_999_999 is a valid subsecond");
1292            }
1293            true
1294        } else {
1295            false
1296        };
1297
1298        let dt = OffsetDateTime::new_in_offset(
1299            Date::try_from(parsed)?,
1300            Time::try_from(parsed)?,
1301            utc_offset_try_from_parsed::<false>(parsed)?,
1302        )
1303        .to_utc();
1304
1305        if leap_second_input && !dt.is_valid_leap_second_stand_in() {
1306            return Err(error::TryFromParsed::ComponentRange(
1307                error::ComponentRange::conditional("second"),
1308            ));
1309        }
1310        Ok(dt)
1311    }
1312}
1313
1314impl TryFrom<Parsed> for OffsetDateTime {
1315    type Error = error::TryFromParsed;
1316
1317    #[inline]
1318    fn try_from(mut parsed: Parsed) -> Result<Self, Self::Error> {
1319        if let Some(timestamp) = parsed.unix_timestamp_nanos() {
1320            let mut value = Self::from_unix_timestamp_nanos(timestamp)?;
1321            if let Some(subsecond) = parsed.subsecond() {
1322                value = value.replace_nanosecond(subsecond)?;
1323            }
1324            return Ok(value);
1325        }
1326
1327        // Some well-known formats explicitly allow leap seconds. We don't currently support them,
1328        // so treat it as the nearest preceding moment that can be represented. Because leap seconds
1329        // always fall at the end of a month UTC, reject any that are at other times.
1330        let leap_second_input = if parsed.leap_second_allowed && parsed.second() == Some(60) {
1331            if parsed.set_second(59).is_none() {
1332                bug!("59 is a valid second");
1333            }
1334            if parsed.set_subsecond(999_999_999).is_none() {
1335                bug!("999_999_999 is a valid subsecond");
1336            }
1337            true
1338        } else {
1339            false
1340        };
1341
1342        let dt = Self::new_in_offset(
1343            Date::try_from(parsed)?,
1344            Time::try_from(parsed)?,
1345            UtcOffset::try_from(parsed)?,
1346        );
1347
1348        if leap_second_input && !dt.is_valid_leap_second_stand_in() {
1349            return Err(error::TryFromParsed::ComponentRange(
1350                error::ComponentRange::conditional("second"),
1351            ));
1352        }
1353        Ok(dt)
1354    }
1355}