Coverage Report

Created: 2025-12-28 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/time-0.3.37/src/parsing/parsed.rs
Line
Count
Source
1
//! Information parsed from an input and format description.
2
3
use core::num::{NonZeroU16, NonZeroU8};
4
5
use deranged::{
6
    OptionRangedI128, OptionRangedI16, OptionRangedI32, OptionRangedI8, OptionRangedU16,
7
    OptionRangedU32, OptionRangedU8, RangedI128, RangedI16, RangedI32, RangedI8, RangedU16,
8
    RangedU32, RangedU8,
9
};
10
use num_conv::prelude::*;
11
12
use crate::convert::{Day, Hour, Minute, Nanosecond, Second};
13
use crate::date::{MAX_YEAR, MIN_YEAR};
14
use crate::error::TryFromParsed::InsufficientInformation;
15
#[cfg(feature = "alloc")]
16
use crate::format_description::OwnedFormatItem;
17
use crate::format_description::{modifier, BorrowedFormatItem, Component};
18
use crate::internal_macros::{bug, const_try_opt};
19
use crate::parsing::component::{
20
    parse_day, parse_end, parse_hour, parse_ignore, parse_minute, parse_month, parse_offset_hour,
21
    parse_offset_minute, parse_offset_second, parse_ordinal, parse_period, parse_second,
22
    parse_subsecond, parse_unix_timestamp, parse_week_number, parse_weekday, parse_year, Period,
23
};
24
use crate::parsing::ParsedItem;
25
use crate::{error, Date, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset, Weekday};
26
27
/// Sealed to prevent downstream implementations.
28
mod sealed {
29
    use super::*;
30
31
    /// A trait to allow `parse_item` to be generic.
32
    pub trait AnyFormatItem {
33
        /// Parse a single item, returning the remaining input on success.
34
        fn parse_item<'a>(
35
            &self,
36
            parsed: &mut Parsed,
37
            input: &'a [u8],
38
        ) -> Result<&'a [u8], error::ParseFromDescription>;
39
    }
40
}
41
42
impl sealed::AnyFormatItem for BorrowedFormatItem<'_> {
43
0
    fn parse_item<'a>(
44
0
        &self,
45
0
        parsed: &mut Parsed,
46
0
        input: &'a [u8],
47
0
    ) -> Result<&'a [u8], error::ParseFromDescription> {
48
0
        match self {
49
0
            Self::Literal(literal) => Parsed::parse_literal(input, literal),
50
0
            Self::Component(component) => parsed.parse_component(input, *component),
51
0
            Self::Compound(compound) => parsed.parse_items(input, compound),
52
0
            Self::Optional(item) => parsed.parse_item(input, *item).or(Ok(input)),
53
0
            Self::First(items) => {
54
0
                let mut first_err = None;
55
56
0
                for item in items.iter() {
57
0
                    match parsed.parse_item(input, item) {
58
0
                        Ok(remaining_input) => return Ok(remaining_input),
59
0
                        Err(err) if first_err.is_none() => first_err = Some(err),
60
0
                        Err(_) => {}
61
                    }
62
                }
63
64
0
                match first_err {
65
0
                    Some(err) => Err(err),
66
                    // This location will be reached if the slice is empty, skipping the `for` loop.
67
                    // As this case is expected to be uncommon, there's no need to check up front.
68
0
                    None => Ok(input),
69
                }
70
            }
71
        }
72
0
    }
73
}
74
75
#[cfg(feature = "alloc")]
76
impl sealed::AnyFormatItem for OwnedFormatItem {
77
0
    fn parse_item<'a>(
78
0
        &self,
79
0
        parsed: &mut Parsed,
80
0
        input: &'a [u8],
81
0
    ) -> Result<&'a [u8], error::ParseFromDescription> {
82
0
        match self {
83
0
            Self::Literal(literal) => Parsed::parse_literal(input, literal),
84
0
            Self::Component(component) => parsed.parse_component(input, *component),
85
0
            Self::Compound(compound) => parsed.parse_items(input, compound),
86
0
            Self::Optional(item) => parsed.parse_item(input, item.as_ref()).or(Ok(input)),
87
0
            Self::First(items) => {
88
0
                let mut first_err = None;
89
90
0
                for item in items.iter() {
91
0
                    match parsed.parse_item(input, item) {
92
0
                        Ok(remaining_input) => return Ok(remaining_input),
93
0
                        Err(err) if first_err.is_none() => first_err = Some(err),
94
0
                        Err(_) => {}
95
                    }
96
                }
97
98
0
                match first_err {
99
0
                    Some(err) => Err(err),
100
                    // This location will be reached if the slice is empty, skipping the `for` loop.
101
                    // As this case is expected to be uncommon, there's no need to check up front.
102
0
                    None => Ok(input),
103
                }
104
            }
105
        }
106
0
    }
107
}
108
109
/// All information parsed.
110
///
111
/// This information is directly used to construct the final values.
112
///
113
/// Most users will not need think about this struct in any way. It is public to allow for manual
114
/// control over values, in the instance that the default parser is insufficient.
115
#[derive(Debug, Clone, Copy)]
116
pub struct Parsed {
117
    /// Calendar year.
118
    year: OptionRangedI32<{ MIN_YEAR }, { MAX_YEAR }>,
119
    /// All digits except the last two of the calendar year.
120
    year_century: OptionRangedI16<{ (MIN_YEAR / 100) as i16 }, { (MAX_YEAR / 100) as i16 }>,
121
    /// The last two digits of the calendar year.
122
    year_last_two: OptionRangedU8<0, 99>,
123
    /// Year of the [ISO week date](https://en.wikipedia.org/wiki/ISO_week_date).
124
    iso_year: OptionRangedI32<{ MIN_YEAR }, { MAX_YEAR }>,
125
    /// All digits except the last two of the ISO week year.
126
    iso_year_century: OptionRangedI16<{ (MIN_YEAR / 100) as i16 }, { (MAX_YEAR / 100) as i16 }>,
127
    /// The last two digits of the ISO week year.
128
    iso_year_last_two: OptionRangedU8<0, 99>,
129
    /// Month of the year.
130
    month: Option<Month>,
131
    /// Week of the year, where week one begins on the first Sunday of the calendar year.
132
    sunday_week_number: OptionRangedU8<0, 53>,
133
    /// Week of the year, where week one begins on the first Monday of the calendar year.
134
    monday_week_number: OptionRangedU8<0, 53>,
135
    /// Week of the year, where week one is the Monday-to-Sunday period containing January 4.
136
    iso_week_number: OptionRangedU8<1, 53>,
137
    /// Day of the week.
138
    weekday: Option<Weekday>,
139
    /// Day of the year.
140
    ordinal: OptionRangedU16<1, 366>,
141
    /// Day of the month.
142
    day: OptionRangedU8<1, 31>,
143
    /// Hour within the day.
144
    hour_24: OptionRangedU8<0, { Hour::per(Day) - 1 }>,
145
    /// Hour within the 12-hour period (midnight to noon or vice versa). This is typically used in
146
    /// conjunction with AM/PM, which is indicated by the `hour_12_is_pm` field.
147
    hour_12: OptionRangedU8<1, 12>,
148
    /// Whether the `hour_12` field indicates a time that "PM".
149
    hour_12_is_pm: Option<bool>,
150
    /// Minute within the hour.
151
    minute: OptionRangedU8<0, { Minute::per(Hour) - 1 }>,
152
    /// Second within the minute.
153
    // do not subtract one, as leap seconds may be allowed
154
    second: OptionRangedU8<0, { Second::per(Minute) }>,
155
    /// Nanosecond within the second.
156
    subsecond: OptionRangedU32<0, { Nanosecond::per(Second) - 1 }>,
157
    /// Whole hours of the UTC offset.
158
    offset_hour: OptionRangedI8<-23, 23>,
159
    /// Minutes within the hour of the UTC offset.
160
    offset_minute:
161
        OptionRangedI8<{ -((Minute::per(Hour) - 1) as i8) }, { (Minute::per(Hour) - 1) as _ }>,
162
    /// Seconds within the minute of the UTC offset.
163
    offset_second:
164
        OptionRangedI8<{ -((Second::per(Minute) - 1) as i8) }, { (Second::per(Minute) - 1) as _ }>,
165
    /// The Unix timestamp in nanoseconds.
166
    unix_timestamp_nanos: OptionRangedI128<
167
        {
168
            OffsetDateTime::new_in_offset(Date::MIN, Time::MIDNIGHT, UtcOffset::UTC)
169
                .unix_timestamp_nanos()
170
        },
171
        {
172
            OffsetDateTime::new_in_offset(Date::MAX, Time::MAX, UtcOffset::UTC)
173
                .unix_timestamp_nanos()
174
        },
175
    >,
176
    /// Indicates whether the [`UtcOffset`] is negative. This information is obtained when parsing
177
    /// the offset hour, but may not otherwise be stored due to "-0" being equivalent to "0".
178
    offset_is_negative: bool,
179
    /// Indicates whether the `year_century` component is negative. This information is obtained
180
    /// when parsing, but may not otherwise be stored due to "-0" being equivalent to "0".
181
    year_century_is_negative: bool,
182
    /// Indicates whether the `iso_year_century` component is negative. This information is
183
    /// obtained when parsing, but may not otherwise be stored due to "-0" being equivalent to "0".
184
    iso_year_century_is_negative: bool,
185
    /// Indicates whether a leap second is permitted to be parsed. This is required by some
186
    /// well-known formats.
187
    pub(super) leap_second_allowed: bool,
188
}
189
190
impl Default for Parsed {
191
0
    fn default() -> Self {
192
0
        Self::new()
193
0
    }
194
}
195
196
impl Parsed {
197
    /// Create a new instance of `Parsed` with no information known.
198
0
    pub const fn new() -> Self {
199
0
        Self {
200
0
            year: OptionRangedI32::None,
201
0
            year_century: OptionRangedI16::None,
202
0
            year_last_two: OptionRangedU8::None,
203
0
            iso_year: OptionRangedI32::None,
204
0
            iso_year_century: OptionRangedI16::None,
205
0
            iso_year_last_two: OptionRangedU8::None,
206
0
            month: None,
207
0
            sunday_week_number: OptionRangedU8::None,
208
0
            monday_week_number: OptionRangedU8::None,
209
0
            iso_week_number: OptionRangedU8::None,
210
0
            weekday: None,
211
0
            ordinal: OptionRangedU16::None,
212
0
            day: OptionRangedU8::None,
213
0
            hour_24: OptionRangedU8::None,
214
0
            hour_12: OptionRangedU8::None,
215
0
            hour_12_is_pm: None,
216
0
            minute: OptionRangedU8::None,
217
0
            second: OptionRangedU8::None,
218
0
            subsecond: OptionRangedU32::None,
219
0
            offset_hour: OptionRangedI8::None,
220
0
            offset_minute: OptionRangedI8::None,
221
0
            offset_second: OptionRangedI8::None,
222
0
            unix_timestamp_nanos: OptionRangedI128::None,
223
0
            offset_is_negative: false,
224
0
            year_century_is_negative: false,
225
0
            iso_year_century_is_negative: false,
226
0
            leap_second_allowed: false,
227
0
        }
228
0
    }
229
230
    /// Parse a single [`BorrowedFormatItem`] or [`OwnedFormatItem`], mutating the struct. The
231
    /// remaining input is returned as the `Ok` value.
232
    ///
233
    /// If a [`BorrowedFormatItem::Optional`] or [`OwnedFormatItem::Optional`] is passed, parsing
234
    /// will not fail; the input will be returned as-is if the expected format is not present.
235
0
    pub fn parse_item<'a>(
236
0
        &mut self,
237
0
        input: &'a [u8],
238
0
        item: &impl sealed::AnyFormatItem,
239
0
    ) -> Result<&'a [u8], error::ParseFromDescription> {
240
0
        item.parse_item(self, input)
241
0
    }
Unexecuted instantiation: <time::parsing::parsed::Parsed>::parse_item::<time::format_description::owned_format_item::OwnedFormatItem>
Unexecuted instantiation: <time::parsing::parsed::Parsed>::parse_item::<time::format_description::borrowed_format_item::BorrowedFormatItem>
242
243
    /// Parse a sequence of [`BorrowedFormatItem`]s or [`OwnedFormatItem`]s, mutating the struct.
244
    /// The remaining input is returned as the `Ok` value.
245
    ///
246
    /// This method will fail if any of the contained [`BorrowedFormatItem`]s or
247
    /// [`OwnedFormatItem`]s fail to parse. `self` will not be mutated in this instance.
248
0
    pub fn parse_items<'a>(
249
0
        &mut self,
250
0
        mut input: &'a [u8],
251
0
        items: &[impl sealed::AnyFormatItem],
252
0
    ) -> Result<&'a [u8], error::ParseFromDescription> {
253
        // Make a copy that we can mutate. It will only be set to the user's copy if everything
254
        // succeeds.
255
0
        let mut this = *self;
256
0
        for item in items {
257
0
            input = this.parse_item(input, item)?;
258
        }
259
0
        *self = this;
260
0
        Ok(input)
261
0
    }
Unexecuted instantiation: <time::parsing::parsed::Parsed>::parse_items::<time::format_description::owned_format_item::OwnedFormatItem>
Unexecuted instantiation: <time::parsing::parsed::Parsed>::parse_items::<time::format_description::borrowed_format_item::BorrowedFormatItem>
262
263
    /// Parse a literal byte sequence. The remaining input is returned as the `Ok` value.
264
0
    pub fn parse_literal<'a>(
265
0
        input: &'a [u8],
266
0
        literal: &[u8],
267
0
    ) -> Result<&'a [u8], error::ParseFromDescription> {
268
0
        input
269
0
            .strip_prefix(literal)
270
0
            .ok_or(error::ParseFromDescription::InvalidLiteral)
271
0
    }
272
273
    /// Parse a single component, mutating the struct. The remaining input is returned as the `Ok`
274
    /// value.
275
0
    pub fn parse_component<'a>(
276
0
        &mut self,
277
0
        input: &'a [u8],
278
0
        component: Component,
279
0
    ) -> Result<&'a [u8], error::ParseFromDescription> {
280
        use error::ParseFromDescription::InvalidComponent;
281
282
0
        match component {
283
0
            Component::Day(modifiers) => parse_day(input, modifiers)
284
0
                .and_then(|parsed| parsed.consume_value(|value| self.set_day(value)))
285
0
                .ok_or(InvalidComponent("day")),
286
0
            Component::Month(modifiers) => parse_month(input, modifiers)
287
0
                .and_then(|parsed| parsed.consume_value(|value| self.set_month(value)))
288
0
                .ok_or(InvalidComponent("month")),
289
0
            Component::Ordinal(modifiers) => parse_ordinal(input, modifiers)
290
0
                .and_then(|parsed| parsed.consume_value(|value| self.set_ordinal(value)))
291
0
                .ok_or(InvalidComponent("ordinal")),
292
0
            Component::Weekday(modifiers) => parse_weekday(input, modifiers)
293
0
                .and_then(|parsed| parsed.consume_value(|value| self.set_weekday(value)))
294
0
                .ok_or(InvalidComponent("weekday")),
295
0
            Component::WeekNumber(modifiers) => {
296
0
                let ParsedItem(remaining, value) =
297
0
                    parse_week_number(input, modifiers).ok_or(InvalidComponent("week number"))?;
298
0
                match modifiers.repr {
299
                    modifier::WeekNumberRepr::Iso => {
300
0
                        NonZeroU8::new(value).and_then(|value| self.set_iso_week_number(value))
301
                    }
302
0
                    modifier::WeekNumberRepr::Sunday => self.set_sunday_week_number(value),
303
0
                    modifier::WeekNumberRepr::Monday => self.set_monday_week_number(value),
304
                }
305
0
                .ok_or(InvalidComponent("week number"))?;
306
0
                Ok(remaining)
307
            }
308
0
            Component::Year(modifiers) => {
309
0
                let ParsedItem(remaining, (value, is_negative)) =
310
0
                    parse_year(input, modifiers).ok_or(InvalidComponent("year"))?;
311
0
                match (modifiers.iso_week_based, modifiers.repr) {
312
0
                    (false, modifier::YearRepr::Full) => self.set_year(value),
313
                    (false, modifier::YearRepr::Century) => {
314
0
                        self.set_year_century(value.truncate(), is_negative)
315
                    }
316
                    (false, modifier::YearRepr::LastTwo) => {
317
0
                        self.set_year_last_two(value.cast_unsigned().truncate())
318
                    }
319
0
                    (true, modifier::YearRepr::Full) => self.set_iso_year(value),
320
                    (true, modifier::YearRepr::Century) => {
321
0
                        self.set_iso_year_century(value.truncate(), is_negative)
322
                    }
323
                    (true, modifier::YearRepr::LastTwo) => {
324
0
                        self.set_iso_year_last_two(value.cast_unsigned().truncate())
325
                    }
326
                }
327
0
                .ok_or(InvalidComponent("year"))?;
328
0
                Ok(remaining)
329
            }
330
0
            Component::Hour(modifiers) => {
331
0
                let ParsedItem(remaining, value) =
332
0
                    parse_hour(input, modifiers).ok_or(InvalidComponent("hour"))?;
333
0
                if modifiers.is_12_hour_clock {
334
0
                    NonZeroU8::new(value).and_then(|value| self.set_hour_12(value))
335
                } else {
336
0
                    self.set_hour_24(value)
337
                }
338
0
                .ok_or(InvalidComponent("hour"))?;
339
0
                Ok(remaining)
340
            }
341
0
            Component::Minute(modifiers) => parse_minute(input, modifiers)
342
0
                .and_then(|parsed| parsed.consume_value(|value| self.set_minute(value)))
343
0
                .ok_or(InvalidComponent("minute")),
344
0
            Component::Period(modifiers) => parse_period(input, modifiers)
345
0
                .and_then(|parsed| {
346
0
                    parsed.consume_value(|value| self.set_hour_12_is_pm(value == Period::Pm))
347
0
                })
348
0
                .ok_or(InvalidComponent("period")),
349
0
            Component::Second(modifiers) => parse_second(input, modifiers)
350
0
                .and_then(|parsed| parsed.consume_value(|value| self.set_second(value)))
351
0
                .ok_or(InvalidComponent("second")),
352
0
            Component::Subsecond(modifiers) => parse_subsecond(input, modifiers)
353
0
                .and_then(|parsed| parsed.consume_value(|value| self.set_subsecond(value)))
354
0
                .ok_or(InvalidComponent("subsecond")),
355
0
            Component::OffsetHour(modifiers) => parse_offset_hour(input, modifiers)
356
0
                .and_then(|parsed| {
357
0
                    parsed.consume_value(|(value, is_negative)| {
358
0
                        self.set_offset_hour(value)?;
359
0
                        self.offset_is_negative = is_negative;
360
0
                        Some(())
361
0
                    })
362
0
                })
363
0
                .ok_or(InvalidComponent("offset hour")),
364
0
            Component::OffsetMinute(modifiers) => parse_offset_minute(input, modifiers)
365
0
                .and_then(|parsed| {
366
0
                    parsed.consume_value(|value| self.set_offset_minute_signed(value))
367
0
                })
368
0
                .ok_or(InvalidComponent("offset minute")),
369
0
            Component::OffsetSecond(modifiers) => parse_offset_second(input, modifiers)
370
0
                .and_then(|parsed| {
371
0
                    parsed.consume_value(|value| self.set_offset_second_signed(value))
372
0
                })
373
0
                .ok_or(InvalidComponent("offset second")),
374
0
            Component::Ignore(modifiers) => parse_ignore(input, modifiers)
375
0
                .map(ParsedItem::<()>::into_inner)
376
0
                .ok_or(InvalidComponent("ignore")),
377
0
            Component::UnixTimestamp(modifiers) => parse_unix_timestamp(input, modifiers)
378
0
                .and_then(|parsed| {
379
0
                    parsed.consume_value(|value| self.set_unix_timestamp_nanos(value))
380
0
                })
381
0
                .ok_or(InvalidComponent("unix_timestamp")),
382
0
            Component::End(modifiers) => parse_end(input, modifiers)
383
0
                .map(ParsedItem::<()>::into_inner)
384
0
                .ok_or(error::ParseFromDescription::UnexpectedTrailingCharacters),
385
        }
386
0
    }
387
}
388
389
/// Getter methods
390
impl Parsed {
391
    /// Obtain the `year` component.
392
0
    pub const fn year(&self) -> Option<i32> {
393
0
        self.year.get_primitive()
394
0
    }
395
396
    /// Obtain the `year_century` component.
397
    ///
398
    /// If the year is zero, the sign of the century is not stored. To differentiate between
399
    /// positive and negative zero, use `year_century_is_negative`.
400
0
    pub const fn year_century(&self) -> Option<i16> {
401
0
        self.year_century.get_primitive()
402
0
    }
403
404
    /// Obtain the `year_century_is_negative` component.
405
    ///
406
    /// This indicates whether the value returned from `year_century` is negative. If the year is
407
    /// zero, it is necessary to call this method for disambiguation.
408
0
    pub const fn year_century_is_negative(&self) -> Option<bool> {
409
0
        match self.year_century() {
410
0
            Some(_) => Some(self.year_century_is_negative),
411
0
            None => None,
412
        }
413
0
    }
414
415
    /// Obtain the `year_last_two` component.
416
0
    pub const fn year_last_two(&self) -> Option<u8> {
417
0
        self.year_last_two.get_primitive()
418
0
    }
419
420
    /// Obtain the `iso_year` component.
421
0
    pub const fn iso_year(&self) -> Option<i32> {
422
0
        self.iso_year.get_primitive()
423
0
    }
424
425
    /// Obtain the `iso_year_century` component.
426
    ///
427
    /// If the year is zero, the sign of the century is not stored. To differentiate between
428
    /// positive and negative zero, use `iso_year_century_is_negative`.
429
0
    pub const fn iso_year_century(&self) -> Option<i16> {
430
0
        self.iso_year_century.get_primitive()
431
0
    }
432
433
    /// Obtain the `iso_year_century_is_negative` component.
434
    ///
435
    /// This indicates whether the value returned from `iso_year_century` is negative. If the year
436
    /// is zero, it is necessary to call this method for disambiguation.
437
0
    pub const fn iso_year_century_is_negative(&self) -> Option<bool> {
438
0
        match self.iso_year_century() {
439
0
            Some(_) => Some(self.iso_year_century_is_negative),
440
0
            None => None,
441
        }
442
0
    }
443
444
    /// Obtain the `iso_year_last_two` component.
445
0
    pub const fn iso_year_last_two(&self) -> Option<u8> {
446
0
        self.iso_year_last_two.get_primitive()
447
0
    }
448
449
    /// Obtain the `month` component.
450
0
    pub const fn month(&self) -> Option<Month> {
451
0
        self.month
452
0
    }
453
454
    /// Obtain the `sunday_week_number` component.
455
0
    pub const fn sunday_week_number(&self) -> Option<u8> {
456
0
        self.sunday_week_number.get_primitive()
457
0
    }
458
459
    /// Obtain the `monday_week_number` component.
460
0
    pub const fn monday_week_number(&self) -> Option<u8> {
461
0
        self.monday_week_number.get_primitive()
462
0
    }
463
464
    /// Obtain the `iso_week_number` component.
465
0
    pub const fn iso_week_number(&self) -> Option<NonZeroU8> {
466
0
        NonZeroU8::new(const_try_opt!(self.iso_week_number.get_primitive()))
467
0
    }
468
469
    /// Obtain the `weekday` component.
470
0
    pub const fn weekday(&self) -> Option<Weekday> {
471
0
        self.weekday
472
0
    }
473
474
    /// Obtain the `ordinal` component.
475
0
    pub const fn ordinal(&self) -> Option<NonZeroU16> {
476
0
        NonZeroU16::new(const_try_opt!(self.ordinal.get_primitive()))
477
0
    }
478
479
    /// Obtain the `day` component.
480
0
    pub const fn day(&self) -> Option<NonZeroU8> {
481
0
        NonZeroU8::new(const_try_opt!(self.day.get_primitive()))
482
0
    }
483
484
    /// Obtain the `hour_24` component.
485
0
    pub const fn hour_24(&self) -> Option<u8> {
486
0
        self.hour_24.get_primitive()
487
0
    }
488
489
    /// Obtain the `hour_12` component.
490
0
    pub const fn hour_12(&self) -> Option<NonZeroU8> {
491
0
        NonZeroU8::new(const_try_opt!(self.hour_12.get_primitive()))
492
0
    }
493
494
    /// Obtain the `hour_12_is_pm` component.
495
0
    pub const fn hour_12_is_pm(&self) -> Option<bool> {
496
0
        self.hour_12_is_pm
497
0
    }
498
499
    /// Obtain the `minute` component.
500
0
    pub const fn minute(&self) -> Option<u8> {
501
0
        self.minute.get_primitive()
502
0
    }
503
504
    /// Obtain the `second` component.
505
0
    pub const fn second(&self) -> Option<u8> {
506
0
        self.second.get_primitive()
507
0
    }
508
509
    /// Obtain the `subsecond` component.
510
0
    pub const fn subsecond(&self) -> Option<u32> {
511
0
        self.subsecond.get_primitive()
512
0
    }
513
514
    /// Obtain the `offset_hour` component.
515
0
    pub const fn offset_hour(&self) -> Option<i8> {
516
0
        self.offset_hour.get_primitive()
517
0
    }
518
519
    /// Obtain the absolute value of the `offset_minute` component.
520
    #[doc(hidden)]
521
    #[deprecated(since = "0.3.8", note = "use `parsed.offset_minute_signed()` instead")]
522
0
    pub const fn offset_minute(&self) -> Option<u8> {
523
0
        Some(const_try_opt!(self.offset_minute_signed()).unsigned_abs())
524
0
    }
525
526
    /// Obtain the `offset_minute` component.
527
0
    pub const fn offset_minute_signed(&self) -> Option<i8> {
528
0
        match (self.offset_minute.get_primitive(), self.offset_is_negative) {
529
0
            (Some(offset_minute), true) => Some(-offset_minute),
530
0
            (Some(offset_minute), _) => Some(offset_minute),
531
0
            (None, _) => None,
532
        }
533
0
    }
534
535
    /// Obtain the absolute value of the `offset_second` component.
536
    #[doc(hidden)]
537
    #[deprecated(since = "0.3.8", note = "use `parsed.offset_second_signed()` instead")]
538
0
    pub const fn offset_second(&self) -> Option<u8> {
539
0
        Some(const_try_opt!(self.offset_second_signed()).unsigned_abs())
540
0
    }
541
542
    /// Obtain the `offset_second` component.
543
0
    pub const fn offset_second_signed(&self) -> Option<i8> {
544
0
        match (self.offset_second.get_primitive(), self.offset_is_negative) {
545
0
            (Some(offset_second), true) => Some(-offset_second),
546
0
            (Some(offset_second), _) => Some(offset_second),
547
0
            (None, _) => None,
548
        }
549
0
    }
550
551
    /// Obtain the `unix_timestamp_nanos` component.
552
0
    pub const fn unix_timestamp_nanos(&self) -> Option<i128> {
553
0
        self.unix_timestamp_nanos.get_primitive()
554
0
    }
555
}
556
557
/// Generate setters based on the builders.
558
macro_rules! setters {
559
    ($($name:ident $setter:ident $builder:ident $type:ty;)*) => {$(
560
        #[doc = concat!("Set the `", stringify!($setter), "` component.")]
561
0
        pub fn $setter(&mut self, value: $type) -> Option<()> {
562
0
            *self = self.$builder(value)?;
563
0
            Some(())
564
0
        }
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_minute
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_second
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_hour_12
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_hour_24
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_ordinal
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_weekday
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_iso_year
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_subsecond
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_offset_hour
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_hour_12_is_pm
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_year_last_two
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_iso_week_number
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_iso_year_last_two
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_monday_week_number
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_sunday_week_number
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_offset_minute_signed
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_offset_second_signed
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_unix_timestamp_nanos
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_day
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_year
Unexecuted instantiation: <time::parsing::parsed::Parsed>::set_month
565
    )*};
566
}
567
568
/// Setter methods
569
///
570
/// All setters return `Option<()>`, which is `Some` if the value was set, and `None` if not. The
571
/// setters _may_ fail if the value is invalid, though behavior is not guaranteed.
572
impl Parsed {
573
    setters! {
574
        year set_year with_year i32;
575
    }
576
577
    /// Set the `year_century` component.
578
    ///
579
    /// If the value is zero, the sign of the century is taken from the second parameter. Otherwise
580
    /// the sign is inferred from the value.
581
0
    pub fn set_year_century(&mut self, value: i16, is_negative: bool) -> Option<()> {
582
0
        self.year_century = OptionRangedI16::Some(const_try_opt!(RangedI16::new(value)));
583
0
        if value != 0 {
584
0
            self.year_century_is_negative = value.is_negative();
585
0
        } else {
586
0
            self.year_century_is_negative = is_negative;
587
0
        }
588
0
        Some(())
589
0
    }
590
591
    setters! {
592
        year_last_two set_year_last_two with_year_last_two u8;
593
        iso_year set_iso_year with_iso_year i32;
594
        iso_year_last_two set_iso_year_last_two with_iso_year_last_two u8;
595
    }
596
597
    /// Set the `iso_year_century` component.
598
    ///
599
    /// If the value is zero, the sign of the century is taken from the second parameter. Otherwise
600
    /// the sign is inferred from the value.
601
0
    pub fn set_iso_year_century(&mut self, value: i16, is_negative: bool) -> Option<()> {
602
0
        self.iso_year_century = OptionRangedI16::Some(const_try_opt!(RangedI16::new(value)));
603
0
        if value != 0 {
604
0
            self.iso_year_century_is_negative = value.is_negative();
605
0
        } else {
606
0
            self.iso_year_century_is_negative = is_negative;
607
0
        }
608
0
        Some(())
609
0
    }
610
611
    setters! {
612
        month set_month with_month Month;
613
        sunday_week_number set_sunday_week_number with_sunday_week_number u8;
614
        monday_week_number set_monday_week_number with_monday_week_number u8;
615
        iso_week_number set_iso_week_number with_iso_week_number NonZeroU8;
616
        weekday set_weekday with_weekday Weekday;
617
        ordinal set_ordinal with_ordinal NonZeroU16;
618
        day set_day with_day NonZeroU8;
619
        hour_24 set_hour_24 with_hour_24 u8;
620
        hour_12 set_hour_12 with_hour_12 NonZeroU8;
621
        hour_12_is_pm set_hour_12_is_pm with_hour_12_is_pm bool;
622
        minute set_minute with_minute u8;
623
        second set_second with_second u8;
624
        subsecond set_subsecond with_subsecond u32;
625
        offset_hour set_offset_hour with_offset_hour i8;
626
        offset_minute set_offset_minute_signed with_offset_minute_signed i8;
627
        offset_second set_offset_second_signed with_offset_second_signed i8;
628
        unix_timestamp_nanos set_unix_timestamp_nanos with_unix_timestamp_nanos i128;
629
    }
630
631
    /// Set the `offset_minute` component.
632
    #[doc(hidden)]
633
    #[deprecated(
634
        since = "0.3.8",
635
        note = "use `parsed.set_offset_minute_signed()` instead"
636
    )]
637
0
    pub fn set_offset_minute(&mut self, value: u8) -> Option<()> {
638
0
        if value > i8::MAX.cast_unsigned() {
639
0
            None
640
        } else {
641
0
            self.set_offset_minute_signed(value.cast_signed())
642
        }
643
0
    }
644
645
    /// Set the `offset_minute` component.
646
    #[doc(hidden)]
647
    #[deprecated(
648
        since = "0.3.8",
649
        note = "use `parsed.set_offset_second_signed()` instead"
650
    )]
651
0
    pub fn set_offset_second(&mut self, value: u8) -> Option<()> {
652
0
        if value > i8::MAX.cast_unsigned() {
653
0
            None
654
        } else {
655
0
            self.set_offset_second_signed(value.cast_signed())
656
        }
657
0
    }
658
}
659
660
/// Builder methods
661
///
662
/// All builder methods return `Option<Self>`, which is `Some` if the value was set, and `None` if
663
/// not. The builder methods _may_ fail if the value is invalid, though behavior is not guaranteed.
664
impl Parsed {
665
    /// Set the `year` component and return `self`.
666
0
    pub const fn with_year(mut self, value: i32) -> Option<Self> {
667
0
        self.year = OptionRangedI32::Some(const_try_opt!(RangedI32::new(value)));
668
0
        Some(self)
669
0
    }
670
671
    /// Set the `year_century` component and return `self`.
672
    ///
673
    /// If the value is zero, the sign of the century is taken from the second parameter. Otherwise
674
    /// the sign is inferred from the value.
675
0
    pub const fn with_year_century(mut self, value: i16, is_negative: bool) -> Option<Self> {
676
0
        self.year_century = OptionRangedI16::Some(const_try_opt!(RangedI16::new(value)));
677
0
        if value != 0 {
678
0
            self.year_century_is_negative = value.is_negative();
679
0
        } else {
680
0
            self.year_century_is_negative = is_negative;
681
0
        }
682
0
        Some(self)
683
0
    }
684
685
    /// Set the `year_last_two` component and return `self`.
686
0
    pub const fn with_year_last_two(mut self, value: u8) -> Option<Self> {
687
0
        self.year_last_two = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value)));
688
0
        Some(self)
689
0
    }
690
691
    /// Set the `iso_year` component and return `self`.
692
0
    pub const fn with_iso_year(mut self, value: i32) -> Option<Self> {
693
0
        self.iso_year = OptionRangedI32::Some(const_try_opt!(RangedI32::new(value)));
694
0
        Some(self)
695
0
    }
696
697
    /// Set the `iso_year_century` component and return `self`.
698
    ///
699
    /// If the value is zero, the sign of the century is taken from the second parameter. Otherwise
700
    /// the sign is inferred from the value.
701
0
    pub const fn with_iso_year_century(mut self, value: i16, is_negative: bool) -> Option<Self> {
702
0
        self.iso_year_century = OptionRangedI16::Some(const_try_opt!(RangedI16::new(value)));
703
0
        if value != 0 {
704
0
            self.iso_year_century_is_negative = value.is_negative();
705
0
        } else {
706
0
            self.iso_year_century_is_negative = is_negative;
707
0
        }
708
0
        Some(self)
709
0
    }
710
711
    /// Set the `iso_year_last_two` component and return `self`.
712
0
    pub const fn with_iso_year_last_two(mut self, value: u8) -> Option<Self> {
713
0
        self.iso_year_last_two = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value)));
714
0
        Some(self)
715
0
    }
716
717
    /// Set the `month` component and return `self`.
718
0
    pub const fn with_month(mut self, value: Month) -> Option<Self> {
719
0
        self.month = Some(value);
720
0
        Some(self)
721
0
    }
722
723
    /// Set the `sunday_week_number` component and return `self`.
724
0
    pub const fn with_sunday_week_number(mut self, value: u8) -> Option<Self> {
725
0
        self.sunday_week_number = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value)));
726
0
        Some(self)
727
0
    }
728
729
    /// Set the `monday_week_number` component and return `self`.
730
0
    pub const fn with_monday_week_number(mut self, value: u8) -> Option<Self> {
731
0
        self.monday_week_number = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value)));
732
0
        Some(self)
733
0
    }
734
735
    /// Set the `iso_week_number` component and return `self`.
736
0
    pub const fn with_iso_week_number(mut self, value: NonZeroU8) -> Option<Self> {
737
0
        self.iso_week_number = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value.get())));
738
0
        Some(self)
739
0
    }
740
741
    /// Set the `weekday` component and return `self`.
742
0
    pub const fn with_weekday(mut self, value: Weekday) -> Option<Self> {
743
0
        self.weekday = Some(value);
744
0
        Some(self)
745
0
    }
746
747
    /// Set the `ordinal` component and return `self`.
748
0
    pub const fn with_ordinal(mut self, value: NonZeroU16) -> Option<Self> {
749
0
        self.ordinal = OptionRangedU16::Some(const_try_opt!(RangedU16::new(value.get())));
750
0
        Some(self)
751
0
    }
752
753
    /// Set the `day` component and return `self`.
754
0
    pub const fn with_day(mut self, value: NonZeroU8) -> Option<Self> {
755
0
        self.day = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value.get())));
756
0
        Some(self)
757
0
    }
758
759
    /// Set the `hour_24` component and return `self`.
760
0
    pub const fn with_hour_24(mut self, value: u8) -> Option<Self> {
761
0
        self.hour_24 = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value)));
762
0
        Some(self)
763
0
    }
764
765
    /// Set the `hour_12` component and return `self`.
766
0
    pub const fn with_hour_12(mut self, value: NonZeroU8) -> Option<Self> {
767
0
        self.hour_12 = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value.get())));
768
0
        Some(self)
769
0
    }
770
771
    /// Set the `hour_12_is_pm` component and return `self`.
772
0
    pub const fn with_hour_12_is_pm(mut self, value: bool) -> Option<Self> {
773
0
        self.hour_12_is_pm = Some(value);
774
0
        Some(self)
775
0
    }
776
777
    /// Set the `minute` component and return `self`.
778
0
    pub const fn with_minute(mut self, value: u8) -> Option<Self> {
779
0
        self.minute = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value)));
780
0
        Some(self)
781
0
    }
782
783
    /// Set the `second` component and return `self`.
784
0
    pub const fn with_second(mut self, value: u8) -> Option<Self> {
785
0
        self.second = OptionRangedU8::Some(const_try_opt!(RangedU8::new(value)));
786
0
        Some(self)
787
0
    }
788
789
    /// Set the `subsecond` component and return `self`.
790
0
    pub const fn with_subsecond(mut self, value: u32) -> Option<Self> {
791
0
        self.subsecond = OptionRangedU32::Some(const_try_opt!(RangedU32::new(value)));
792
0
        Some(self)
793
0
    }
794
795
    /// Set the `offset_hour` component and return `self`.
796
0
    pub const fn with_offset_hour(mut self, value: i8) -> Option<Self> {
797
0
        self.offset_hour = OptionRangedI8::Some(const_try_opt!(RangedI8::new(value)));
798
0
        Some(self)
799
0
    }
800
801
    /// Set the `offset_minute` component and return `self`.
802
    #[doc(hidden)]
803
    #[deprecated(
804
        since = "0.3.8",
805
        note = "use `parsed.with_offset_minute_signed()` instead"
806
    )]
807
0
    pub const fn with_offset_minute(self, value: u8) -> Option<Self> {
808
0
        if value > i8::MAX as u8 {
809
0
            None
810
        } else {
811
0
            self.with_offset_minute_signed(value as _)
812
        }
813
0
    }
814
815
    /// Set the `offset_minute` component and return `self`.
816
0
    pub const fn with_offset_minute_signed(mut self, value: i8) -> Option<Self> {
817
0
        self.offset_minute = OptionRangedI8::Some(const_try_opt!(RangedI8::new(value)));
818
0
        Some(self)
819
0
    }
820
821
    /// Set the `offset_minute` component and return `self`.
822
    #[doc(hidden)]
823
    #[deprecated(
824
        since = "0.3.8",
825
        note = "use `parsed.with_offset_second_signed()` instead"
826
    )]
827
0
    pub const fn with_offset_second(self, value: u8) -> Option<Self> {
828
0
        if value > i8::MAX as u8 {
829
0
            None
830
        } else {
831
0
            self.with_offset_second_signed(value as _)
832
        }
833
0
    }
834
835
    /// Set the `offset_second` component and return `self`.
836
0
    pub const fn with_offset_second_signed(mut self, value: i8) -> Option<Self> {
837
0
        self.offset_second = OptionRangedI8::Some(const_try_opt!(RangedI8::new(value)));
838
0
        Some(self)
839
0
    }
840
841
    /// Set the `unix_timestamp_nanos` component and return `self`.
842
0
    pub const fn with_unix_timestamp_nanos(mut self, value: i128) -> Option<Self> {
843
0
        self.unix_timestamp_nanos = OptionRangedI128::Some(const_try_opt!(RangedI128::new(value)));
844
0
        Some(self)
845
0
    }
846
}
847
848
impl TryFrom<Parsed> for Date {
849
    type Error = error::TryFromParsed;
850
851
0
    fn try_from(mut parsed: Parsed) -> Result<Self, Self::Error> {
852
        /// Match on the components that need to be present.
853
        macro_rules! match_ {
854
            (_ => $catch_all:expr $(,)?) => {
855
                $catch_all
856
            };
857
            (($($name:ident),* $(,)?) => $arm:expr, $($rest:tt)*) => {
858
                if let ($(Some($name)),*) = ($(parsed.$name()),*) {
859
                    $arm
860
                } else {
861
                    match_!($($rest)*)
862
                }
863
            };
864
        }
865
866
        /// Get the value needed to adjust the ordinal day for Sunday and Monday-based week
867
        /// numbering.
868
0
        const fn adjustment(year: i32) -> i16 {
869
            // Safety: `ordinal` is not zero.
870
0
            match unsafe { Date::__from_ordinal_date_unchecked(year, 1) }.weekday() {
871
0
                Weekday::Monday => 7,
872
0
                Weekday::Tuesday => 1,
873
0
                Weekday::Wednesday => 2,
874
0
                Weekday::Thursday => 3,
875
0
                Weekday::Friday => 4,
876
0
                Weekday::Saturday => 5,
877
0
                Weekday::Sunday => 6,
878
            }
879
0
        }
880
881
        // If we do not have the year but we have *both* the century and the last two digits, we can
882
        // construct the year. Likewise for the ISO year.
883
0
        if let (None, Some(century), Some(is_negative), Some(last_two)) = (
884
0
            parsed.year(),
885
0
            parsed.year_century(),
886
0
            parsed.year_century_is_negative(),
887
0
            parsed.year_last_two(),
888
        ) {
889
0
            let year = if is_negative {
890
0
                100 * century.extend::<i32>() - last_two.cast_signed().extend::<i32>()
891
            } else {
892
0
                100 * century.extend::<i32>() + last_two.cast_signed().extend::<i32>()
893
            };
894
0
            parsed.year = OptionRangedI32::from(RangedI32::new(year));
895
0
        }
896
0
        if let (None, Some(century), Some(is_negative), Some(last_two)) = (
897
0
            parsed.iso_year(),
898
0
            parsed.iso_year_century(),
899
0
            parsed.iso_year_century_is_negative(),
900
0
            parsed.iso_year_last_two(),
901
        ) {
902
0
            let iso_year = if is_negative {
903
0
                100 * century.extend::<i32>() - last_two.cast_signed().extend::<i32>()
904
            } else {
905
0
                100 * century.extend::<i32>() + last_two.cast_signed().extend::<i32>()
906
            };
907
0
            parsed.iso_year = OptionRangedI32::from(RangedI32::new(iso_year));
908
0
        }
909
910
0
        match_! {
911
0
            (year, ordinal) => Ok(Self::from_ordinal_date(year, ordinal.get())?),
912
0
            (year, month, day) => Ok(Self::from_calendar_date(year, month, day.get())?),
913
0
            (iso_year, iso_week_number, weekday) => Ok(Self::from_iso_week_date(
914
0
                iso_year,
915
0
                iso_week_number.get(),
916
0
                weekday,
917
0
            )?),
918
0
            (year, sunday_week_number, weekday) => Ok(Self::from_ordinal_date(
919
0
                year,
920
0
                (sunday_week_number.cast_signed().extend::<i16>() * 7
921
0
                    + weekday.number_days_from_sunday().cast_signed().extend::<i16>()
922
0
                    - adjustment(year)
923
0
                    + 1).cast_unsigned(),
924
0
            )?),
925
0
            (year, monday_week_number, weekday) => Ok(Self::from_ordinal_date(
926
0
                year,
927
0
                (monday_week_number.cast_signed().extend::<i16>() * 7
928
0
                    + weekday.number_days_from_monday().cast_signed().extend::<i16>()
929
0
                    - adjustment(year)
930
0
                    + 1).cast_unsigned(),
931
0
            )?),
932
0
            _ => Err(InsufficientInformation),
933
        }
934
0
    }
935
}
936
937
impl TryFrom<Parsed> for Time {
938
    type Error = error::TryFromParsed;
939
940
0
    fn try_from(parsed: Parsed) -> Result<Self, Self::Error> {
941
0
        let hour = match (parsed.hour_24(), parsed.hour_12(), parsed.hour_12_is_pm()) {
942
0
            (Some(hour), _, _) => hour,
943
0
            (_, Some(hour), Some(false)) if hour.get() == 12 => 0,
944
0
            (_, Some(hour), Some(true)) if hour.get() == 12 => 12,
945
0
            (_, Some(hour), Some(false)) => hour.get(),
946
0
            (_, Some(hour), Some(true)) => hour.get() + 12,
947
0
            _ => return Err(InsufficientInformation),
948
        };
949
950
0
        if parsed.hour_24().is_none()
951
0
            && parsed.hour_12().is_some()
952
0
            && parsed.hour_12_is_pm().is_some()
953
0
            && parsed.minute().is_none()
954
0
            && parsed.second().is_none()
955
0
            && parsed.subsecond().is_none()
956
        {
957
0
            return Ok(Self::from_hms_nano(hour, 0, 0, 0)?);
958
0
        }
959
960
        // Reject combinations such as hour-second with minute omitted.
961
0
        match (parsed.minute(), parsed.second(), parsed.subsecond()) {
962
0
            (None, None, None) => Ok(Self::from_hms_nano(hour, 0, 0, 0)?),
963
0
            (Some(minute), None, None) => Ok(Self::from_hms_nano(hour, minute, 0, 0)?),
964
0
            (Some(minute), Some(second), None) => Ok(Self::from_hms_nano(hour, minute, second, 0)?),
965
0
            (Some(minute), Some(second), Some(subsecond)) => {
966
0
                Ok(Self::from_hms_nano(hour, minute, second, subsecond)?)
967
            }
968
0
            _ => Err(InsufficientInformation),
969
        }
970
0
    }
971
}
972
973
impl TryFrom<Parsed> for UtcOffset {
974
    type Error = error::TryFromParsed;
975
976
0
    fn try_from(parsed: Parsed) -> Result<Self, Self::Error> {
977
0
        let hour = parsed.offset_hour().ok_or(InsufficientInformation)?;
978
0
        let minute = parsed.offset_minute_signed().unwrap_or(0);
979
0
        let second = parsed.offset_second_signed().unwrap_or(0);
980
981
0
        Self::from_hms(hour, minute, second).map_err(|mut err| {
982
            // Provide the user a more accurate error.
983
0
            if err.name == "hours" {
984
0
                err.name = "offset hour";
985
0
            } else if err.name == "minutes" {
986
0
                err.name = "offset minute";
987
0
            } else if err.name == "seconds" {
988
0
                err.name = "offset second";
989
0
            }
990
0
            err.into()
991
0
        })
992
0
    }
993
}
994
995
impl TryFrom<Parsed> for PrimitiveDateTime {
996
    type Error = error::TryFromParsed;
997
998
0
    fn try_from(parsed: Parsed) -> Result<Self, Self::Error> {
999
0
        Ok(Self::new(parsed.try_into()?, parsed.try_into()?))
1000
0
    }
1001
}
1002
1003
impl TryFrom<Parsed> for OffsetDateTime {
1004
    type Error = error::TryFromParsed;
1005
1006
0
    fn try_from(mut parsed: Parsed) -> Result<Self, Self::Error> {
1007
0
        if let Some(timestamp) = parsed.unix_timestamp_nanos() {
1008
0
            let mut value = Self::from_unix_timestamp_nanos(timestamp)?;
1009
0
            if let Some(subsecond) = parsed.subsecond() {
1010
0
                value = value.replace_nanosecond(subsecond)?;
1011
0
            }
1012
0
            return Ok(value);
1013
0
        }
1014
1015
        // Some well-known formats explicitly allow leap seconds. We don't currently support them,
1016
        // so treat it as the nearest preceding moment that can be represented. Because leap seconds
1017
        // always fall at the end of a month UTC, reject any that are at other times.
1018
0
        let leap_second_input = if parsed.leap_second_allowed && parsed.second() == Some(60) {
1019
0
            if parsed.set_second(59).is_none() {
1020
0
                bug!("59 is a valid second");
1021
0
            }
1022
0
            if parsed.set_subsecond(999_999_999).is_none() {
1023
0
                bug!("999_999_999 is a valid subsecond");
1024
0
            }
1025
0
            true
1026
        } else {
1027
0
            false
1028
        };
1029
1030
0
        let dt = Self::new_in_offset(
1031
0
            Date::try_from(parsed)?,
1032
0
            Time::try_from(parsed)?,
1033
0
            UtcOffset::try_from(parsed)?,
1034
        );
1035
1036
0
        if leap_second_input && !dt.is_valid_leap_second_stand_in() {
1037
0
            return Err(error::TryFromParsed::ComponentRange(
1038
0
                error::ComponentRange {
1039
0
                    name: "second",
1040
0
                    minimum: 0,
1041
0
                    maximum: 59,
1042
0
                    value: 60,
1043
0
                    conditional_range: true,
1044
0
                },
1045
0
            ));
1046
0
        }
1047
0
        Ok(dt)
1048
0
    }
1049
}