icu_datetime/combo.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
5use crate::{provider::neo::*, scaffold::*};
6
7/// Struct for combining date/time fields with zone fields.
8///
9/// This struct produces "composite field sets" as defined in UTS 35.
10/// See [`fieldsets`](crate::fieldsets).
11///
12/// # Examples
13///
14/// The only way to construct a combo field set (in this case, weekday with location-based zone):
15///
16/// ```
17/// use icu::datetime::fieldsets::{zone::Location, Combo, E};
18///
19/// let field_set = E::long().with_zone(Location);
20/// ```
21///
22/// Format the weekday, hour, and location-based zone:
23///
24/// ```
25/// use icu::datetime::fieldsets::{self, zone, Combo};
26/// use icu::datetime::input::ZonedDateTime;
27/// use icu::datetime::DateTimeFormatter;
28/// use icu::locale::locale;
29/// use icu::time::zone::IanaParser;
30/// use writeable::assert_writeable_eq;
31///
32/// // Note: Combo type can be elided, but it is shown here for demonstration
33/// let formatter =
34/// DateTimeFormatter::<Combo<fieldsets::ET, zone::Location>>::try_new(
35/// locale!("en-US").into(),
36/// fieldsets::E::short()
37/// .with_time_hm()
38/// .with_zone(zone::Location),
39/// )
40/// .unwrap();
41///
42/// let zdt = ZonedDateTime::try_location_only_from_str(
43/// "2024-10-18T15:44[America/Los_Angeles]",
44/// formatter.calendar(),
45/// IanaParser::new(),
46/// )
47/// .unwrap();
48///
49/// assert_writeable_eq!(
50/// formatter.format(&zdt),
51/// "Fri, 3:44 PM Los Angeles Time"
52/// );
53/// ```
54///
55/// Same thing with a fixed calendar formatter:
56///
57/// ```
58/// use icu::calendar::Gregorian;
59/// use icu::datetime::fieldsets::{self, zone, Combo};
60/// use icu::datetime::input::ZonedDateTime;
61/// use icu::datetime::FixedCalendarDateTimeFormatter;
62/// use icu::locale::locale;
63/// use icu::time::zone::IanaParser;
64/// use writeable::assert_writeable_eq;
65///
66/// // Note: Combo type can be elided, but it is shown here for demonstration
67/// let formatter = FixedCalendarDateTimeFormatter::<
68/// _,
69/// Combo<fieldsets::ET, zone::Location>,
70/// >::try_new(
71/// locale!("en-US").into(),
72/// fieldsets::E::short()
73/// .with_time_hm()
74/// .with_zone(zone::Location),
75/// )
76/// .unwrap();
77///
78/// let zdt = ZonedDateTime::try_location_only_from_str(
79/// "2024-10-18T15:44[America/Los_Angeles]",
80/// Gregorian,
81/// IanaParser::new(),
82/// )
83/// .unwrap();
84///
85/// assert_writeable_eq!(
86/// formatter.format(&zdt),
87/// "Fri, 3:44 PM Los Angeles Time"
88/// );
89/// ```
90///
91/// Mix a dynamic [`DateFieldSet`](crate::fieldsets::enums::DateFieldSet)
92/// with a static time zone:
93///
94/// ```
95/// use icu::datetime::fieldsets::{
96/// enums::DateFieldSet, zone::GenericShort, Combo, YMD,
97/// };
98/// use icu::datetime::input::ZonedDateTime;
99/// use icu::datetime::DateTimeFormatter;
100/// use icu::locale::locale;
101/// use icu::time::zone::IanaParser;
102/// use writeable::assert_writeable_eq;
103///
104/// // Note: Combo type can be elided, but it is shown here for demonstration
105/// let formatter =
106/// DateTimeFormatter::<Combo<DateFieldSet, GenericShort>>::try_new(
107/// locale!("en-US").into(),
108/// DateFieldSet::YMD(YMD::long()).with_zone(GenericShort),
109/// )
110/// .unwrap();
111///
112/// let zdt = ZonedDateTime::try_location_only_from_str(
113/// "2024-10-18T15:44[America/Los_Angeles]",
114/// formatter.calendar(),
115/// IanaParser::new(),
116/// )
117/// .unwrap();
118///
119/// assert_writeable_eq!(formatter.format(&zdt), "October 18, 2024 PT");
120/// ```
121///
122/// Format with a time of day and long time zone:
123///
124/// ```
125/// use icu::calendar::Gregorian;
126/// use icu::datetime::fieldsets::{zone::SpecificLong, T};
127/// use icu::datetime::input::ZonedDateTime;
128/// use icu::datetime::FixedCalendarDateTimeFormatter;
129/// use icu::locale::locale;
130/// use icu::time::zone::IanaParser;
131/// use writeable::assert_writeable_eq;
132///
133/// let formatter = FixedCalendarDateTimeFormatter::try_new(
134/// locale!("en-US").into(),
135/// T::medium().with_zone(SpecificLong),
136/// )
137/// .unwrap();
138///
139/// let zdt = ZonedDateTime::try_strict_from_str(
140/// "2024-10-18T15:44-0700[America/Los_Angeles]",
141/// Gregorian,
142/// IanaParser::new(),
143/// )
144/// .unwrap();
145///
146/// assert_writeable_eq!(
147/// formatter.format(&zdt),
148/// "3:44:00 PM Pacific Daylight Time"
149/// );
150/// ```
151#[derive(Debug, Copy, Clone, PartialEq, Eq)]
152pub struct Combo<DT, Z> {
153 date_time_field_set: DT,
154 zone_field_set: Z,
155}
156
157impl<DT, Z> Combo<DT, Z> {
158 #[inline]
159 pub(crate) const fn new(date_time_field_set: DT, zone_field_set: Z) -> Self {
160 Self {
161 date_time_field_set,
162 zone_field_set,
163 }
164 }
165}
166
167impl<DT, Z> UnstableSealed for Combo<DT, Z> {}
168
169impl<DT, Z> Combo<DT, Z> {
170 #[inline]
171 pub(crate) fn dt(self) -> DT {
172 self.date_time_field_set
173 }
174 #[inline]
175 pub(crate) fn z(self) -> Z {
176 self.zone_field_set
177 }
178}
179
180impl<DT, Z> DateTimeNamesMarker for Combo<DT, Z>
181where
182 DT: DateTimeNamesMarker,
183 Z: DateTimeNamesMarker,
184{
185 type YearNames = DT::YearNames;
186 type MonthNames = DT::MonthNames;
187 type WeekdayNames = DT::WeekdayNames;
188 type DayPeriodNames = DT::DayPeriodNames;
189 type ZoneEssentials = Z::ZoneEssentials;
190 type ZoneLocations = Z::ZoneLocations;
191 type ZoneLocationsRoot = Z::ZoneLocationsRoot;
192 type ZoneExemplars = Z::ZoneExemplars;
193 type ZoneExemplarsRoot = Z::ZoneExemplarsRoot;
194 type ZoneGenericLong = Z::ZoneGenericLong;
195 type ZoneGenericShort = Z::ZoneGenericShort;
196 type ZoneStandardLong = Z::ZoneStandardLong;
197 type ZoneSpecificLong = Z::ZoneSpecificLong;
198 type ZoneSpecificShort = Z::ZoneSpecificShort;
199 type MetazoneLookup = Z::MetazoneLookup;
200}
201
202impl<DT, Z> DateTimeMarkers for Combo<DT, Z>
203where
204 DT: DateTimeMarkers,
205 Z: DateTimeMarkers,
206{
207 type D = DT::D;
208 type T = DT::T;
209 type Z = Z::Z;
210 type GluePatternV1 = datetime_marker_helper!(@glue, yes);
211}