icu_datetime/format/
input.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5//! A collection of utilities for representing and working with dates as an input to
6//! formatting operations.
7
8use crate::scaffold::*;
9use icu_calendar::types::DayOfYear;
10use icu_calendar::{AsCalendar, Calendar};
11use icu_time::scaffold::IntoOption;
12use icu_time::zone::ZoneNameTimestamp;
13use icu_time::{zone::TimeZoneVariant, Hour, Minute, Nanosecond, Second};
14
15use icu_calendar::Date;
16use icu_time::{zone::UtcOffset, Time, TimeZone};
17
18// TODO(#2630) fix up imports to directly import from icu_calendar
19pub(crate) use icu_calendar::types::{DayOfMonth, MonthInfo, Weekday, YearInfo};
20
21#[cfg(doc)]
22use crate::input::*;
23
24/// An input bag with all possible datetime input fields.
25///
26/// Each input field may or may not be required, depending on the field set
27/// and the options.
28#[derive(Debug, Copy, Clone, Default)]
29#[non_exhaustive]
30pub struct DateTimeInputUnchecked {
31    /// The year, required for field sets with years (`Y`).
32    pub(crate) year: Option<YearInfo>,
33    /// The month, required for field sets with months (`M`)
34    pub(crate) month: Option<MonthInfo>,
35    /// The day-of-month, required for field sets with days (`D`).
36    pub(crate) day_of_month: Option<DayOfMonth>,
37    /// The weekday, required for field sets with weekdays (`E`).
38    pub(crate) iso_weekday: Option<Weekday>,
39    /// The day-of-year, required for field sets with weeks.
40    pub(crate) day_of_year: Option<DayOfYear>,
41    /// The hour, required for field sets with times (`T`).
42    pub(crate) hour: Option<Hour>,
43    /// The minute, required for field sets with times (`T`).
44    pub(crate) minute: Option<Minute>,
45    /// The second, required for field sets with times (`T`).
46    pub(crate) second: Option<Second>,
47    /// The subsecond, required for field sets with times (`T`).
48    pub(crate) subsecond: Option<Nanosecond>,
49    /// The time zone ID, required for field sets with
50    /// certain time zone styles.
51    pub(crate) zone_id: Option<TimeZone>,
52    /// The time zone UTC offset, required for field sets with
53    /// certain time zone styles.
54    pub(crate) zone_offset: Option<UtcOffset>,
55    /// The time zone variant, required for field sets with
56    /// certain time zone styles.
57    pub(crate) zone_variant: Option<TimeZoneVariant>,
58    /// The local ISO time, required for field sets with
59    /// certain time zone styles.
60    pub(crate) zone_name_timestamp: Option<ZoneNameTimestamp>,
61}
62
63impl DateTimeInputUnchecked {
64    /// Sets all fields from a [`Date`] input.
65    ///
66    /// This method does not check the calendar of the date! The caller is
67    /// responsible for making sure the calendar matches the formatter.
68    pub fn set_date_fields_unchecked<C: Calendar, A: AsCalendar<Calendar = C>>(
69        &mut self,
70        date_in_calendar: Date<A>,
71    ) {
72        self.year = Some(date_in_calendar.year());
73        self.month = Some(date_in_calendar.month());
74        self.day_of_month = Some(date_in_calendar.day_of_month());
75        self.iso_weekday = Some(date_in_calendar.day_of_week());
76        self.day_of_year = Some(date_in_calendar.day_of_year());
77    }
78
79    /// Sets all fields from a [`Time`] input.
80    pub fn set_time_fields(&mut self, time: Time) {
81        self.hour = Some(time.hour);
82        self.minute = Some(time.minute);
83        self.second = Some(time.second);
84        self.subsecond = Some(time.subsecond);
85    }
86
87    /// Sets the time zone UTC offset.
88    pub fn set_time_zone_utc_offset(&mut self, utc_offset: UtcOffset) {
89        self.zone_offset = Some(utc_offset);
90    }
91
92    /// Sets the time zone ID.
93    pub fn set_time_zone_id(&mut self, id: TimeZone) {
94        self.zone_id = Some(id);
95    }
96
97    /// Sets the local time for time zone name resolution.
98    pub fn set_time_zone_name_timestamp(&mut self, local_time: ZoneNameTimestamp) {
99        self.zone_name_timestamp = Some(local_time);
100    }
101
102    /// Sets the time zone variant.
103    pub fn set_time_zone_variant(&mut self, zone_variant: TimeZoneVariant) {
104        self.zone_variant = Some(zone_variant);
105    }
106
107    /// Construct given neo date input instances.
108    pub(crate) fn extract_from_neo_input<D, T, Z, I>(input: &I) -> Self
109    where
110        D: DateInputMarkers,
111        T: TimeMarkers,
112        Z: ZoneMarkers,
113        I: ?Sized
114            + GetField<D::YearInput>
115            + GetField<D::MonthInput>
116            + GetField<D::DayOfMonthInput>
117            + GetField<D::DayOfWeekInput>
118            + GetField<D::DayOfYearInput>
119            + GetField<T::HourInput>
120            + GetField<T::MinuteInput>
121            + GetField<T::SecondInput>
122            + GetField<T::NanosecondInput>
123            + GetField<Z::TimeZoneIdInput>
124            + GetField<Z::TimeZoneOffsetInput>
125            + GetField<Z::TimeZoneVariantInput>
126            + GetField<Z::TimeZoneNameTimestampInput>,
127    {
128        Self {
129            year: GetField::<D::YearInput>::get_field(input).into_option(),
130            month: GetField::<D::MonthInput>::get_field(input).into_option(),
131            day_of_month: GetField::<D::DayOfMonthInput>::get_field(input).into_option(),
132            iso_weekday: GetField::<D::DayOfWeekInput>::get_field(input).into_option(),
133            day_of_year: GetField::<D::DayOfYearInput>::get_field(input).into_option(),
134            hour: GetField::<T::HourInput>::get_field(input).into_option(),
135            minute: GetField::<T::MinuteInput>::get_field(input).into_option(),
136            second: GetField::<T::SecondInput>::get_field(input).into_option(),
137            subsecond: GetField::<T::NanosecondInput>::get_field(input).into_option(),
138            zone_id: GetField::<Z::TimeZoneIdInput>::get_field(input).into_option(),
139            zone_offset: GetField::<Z::TimeZoneOffsetInput>::get_field(input).into_option(),
140            zone_variant: GetField::<Z::TimeZoneVariantInput>::get_field(input).into_option(),
141            zone_name_timestamp: GetField::<Z::TimeZoneNameTimestampInput>::get_field(input)
142                .into_option(),
143        }
144    }
145}