icu_datetime/format/
input.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

//! A collection of utilities for representing and working with dates as an input to
//! formatting operations.

use crate::scaffold::*;
use icu_calendar::types::DayOfYearInfo;
use icu_calendar::{AsCalendar, Calendar, Iso};
use icu_time::scaffold::IntoOption;
use icu_time::{zone::TimeZoneVariant, Hour, Minute, Nanosecond, Second};

use icu_calendar::Date;
use icu_time::{zone::UtcOffset, Time, TimeZone};

// TODO(#2630) fix up imports to directly import from icu_calendar
pub(crate) use icu_calendar::types::{DayOfMonth, MonthInfo, Weekday, YearInfo};

#[cfg(doc)]
use crate::input::*;

/// An input bag with all possible datetime input fields.
///
/// Each input field may or may not be required, depending on the field set
/// and the options.
#[derive(Debug, Copy, Clone, Default)]
#[non_exhaustive]
pub struct DateTimeInputUnchecked {
    /// The year, required for field sets with years (`Y`).
    pub(crate) year: Option<YearInfo>,
    /// The month, required for field sets with months (`M`)
    pub(crate) month: Option<MonthInfo>,
    /// The day-of-month, required for field sets with days (`D`).
    pub(crate) day_of_month: Option<DayOfMonth>,
    /// The weekday, required for field sets with weekdays (`E`).
    pub(crate) iso_weekday: Option<Weekday>,
    /// The day-of-year, required for field sets with weeks.
    pub(crate) day_of_year: Option<DayOfYearInfo>,
    /// The hour, required for field sets with times (`T`).
    pub(crate) hour: Option<Hour>,
    /// The minute, required for field sets with times (`T`).
    pub(crate) minute: Option<Minute>,
    /// The second, required for field sets with times (`T`).
    pub(crate) second: Option<Second>,
    /// The subsecond, required for field sets with times (`T`).
    pub(crate) subsecond: Option<Nanosecond>,
    /// The time zone ID, required for field sets with
    /// certain time zone styles.
    pub(crate) time_zone_id: Option<TimeZone>,
    /// The time zone UTC offset, required for field sets with
    /// certain time zone styles.
    pub(crate) offset: Option<UtcOffset>,
    /// The time zone variant, required for field sets with
    /// certain time zone styles.
    pub(crate) zone_variant: Option<TimeZoneVariant>,
    /// The local ISO time, required for field sets with
    /// certain time zone styles.
    pub(crate) local_time: Option<(Date<Iso>, Time)>,
}

impl DateTimeInputUnchecked {
    /// Sets all fields from a [`Date`] input.
    pub fn set_date_fields<C: Calendar, A: AsCalendar<Calendar = C>>(&mut self, input: Date<A>) {
        self.year = Some(input.year());
        self.month = Some(input.month());
        self.day_of_month = Some(input.day_of_month());
        self.iso_weekday = Some(input.day_of_week());
        self.day_of_year = Some(input.day_of_year_info());
    }

    /// Sets all fields from a [`Time`] input.
    pub fn set_time_fields(&mut self, input: Time) {
        self.hour = Some(input.hour);
        self.minute = Some(input.minute);
        self.second = Some(input.second);
        self.subsecond = Some(input.subsecond);
    }

    /// Sets the time zone UTC offset.
    pub fn set_time_zone_utc_offset(&mut self, offset: UtcOffset) {
        self.offset = Some(offset);
    }

    /// Sets the time zone ID.
    pub fn set_time_zone_id(&mut self, id: TimeZone) {
        self.time_zone_id = Some(id);
    }

    /// Sets the local time for time zone name resolution.
    pub fn set_time_zone_local_time(&mut self, local_time: (Date<Iso>, Time)) {
        self.local_time = Some(local_time);
    }

    /// Sets the time zone variant.
    pub fn set_time_zone_variant(&mut self, zone_variant: TimeZoneVariant) {
        self.zone_variant = Some(zone_variant);
    }

    /// Construct given neo date input instances.
    pub(crate) fn extract_from_neo_input<D, T, Z, I>(input: &I) -> Self
    where
        D: DateInputMarkers,
        T: TimeMarkers,
        Z: ZoneMarkers,
        I: ?Sized
            + GetField<D::YearInput>
            + GetField<D::MonthInput>
            + GetField<D::DayOfMonthInput>
            + GetField<D::DayOfWeekInput>
            + GetField<D::DayOfYearInput>
            + GetField<T::HourInput>
            + GetField<T::MinuteInput>
            + GetField<T::SecondInput>
            + GetField<T::NanosecondInput>
            + GetField<Z::TimeZoneIdInput>
            + GetField<Z::TimeZoneOffsetInput>
            + GetField<Z::TimeZoneVariantInput>
            + GetField<Z::TimeZoneLocalTimeInput>,
    {
        Self {
            year: GetField::<D::YearInput>::get_field(input).into_option(),
            month: GetField::<D::MonthInput>::get_field(input).into_option(),
            day_of_month: GetField::<D::DayOfMonthInput>::get_field(input).into_option(),
            iso_weekday: GetField::<D::DayOfWeekInput>::get_field(input).into_option(),
            day_of_year: GetField::<D::DayOfYearInput>::get_field(input).into_option(),
            hour: GetField::<T::HourInput>::get_field(input).into_option(),
            minute: GetField::<T::MinuteInput>::get_field(input).into_option(),
            second: GetField::<T::SecondInput>::get_field(input).into_option(),
            subsecond: GetField::<T::NanosecondInput>::get_field(input).into_option(),
            time_zone_id: GetField::<Z::TimeZoneIdInput>::get_field(input).into_option(),
            offset: GetField::<Z::TimeZoneOffsetInput>::get_field(input).into_option(),
            zone_variant: GetField::<Z::TimeZoneVariantInput>::get_field(input).into_option(),
            local_time: GetField::<Z::TimeZoneLocalTimeInput>::get_field(input).into_option(),
        }
    }
}