Coverage Report

Created: 2025-07-11 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/icu_datetime-1.5.1/src/datetime.rs
Line
Count
Source (jump to first uncovered line)
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
//! The collection of code that is needed for handling formatting operations for DateTimes.
6
//! Central to this is the [`TypedDateTimeFormatter`].
7
8
#[cfg(feature = "experimental")]
9
use crate::provider::date_time::UnsupportedOptionsOrDataOrPatternError;
10
use crate::{
11
    helpers::size_test,
12
    options::{length, preferences, DateTimeFormatterOptions},
13
    provider::{
14
        calendar::{TimeLengthsV1Marker, TimeSymbolsV1Marker},
15
        date_time::{PatternForLengthError, PatternSelector},
16
    },
17
    raw,
18
};
19
use alloc::string::String;
20
use core::marker::PhantomData;
21
use icu_calendar::provider::WeekDataV1Marker;
22
use icu_decimal::provider::DecimalSymbolsV1Marker;
23
use icu_plurals::provider::OrdinalV1Marker;
24
use icu_provider::prelude::*;
25
use writeable::Writeable;
26
27
use crate::{
28
    calendar, calendar::CldrCalendar, input::DateInput, input::DateTimeInput, input::IsoTimeInput,
29
    DateTimeError, FormattedDateTime,
30
};
31
32
size_test!(TimeFormatter, time_formatter_size, 1200);
33
34
/// [`TimeFormatter`] is a structure of the [`icu::datetime`] component that provides time formatting only.
35
/// When constructed, it uses data from the [data provider], selected locale and provided preferences to
36
/// collect all data necessary to format any time into that locale.
37
///
38
/// For that reason, one should think of the process of formatting a time in two steps - first, a computational
39
/// heavy construction of [`TimeFormatter`], and then fast formatting of [`DateTimeInput`] data using the instance.
40
#[doc = time_formatter_size!()]
41
///
42
/// [`icu::datetime`]: crate
43
/// [`TypedDateTimeFormatter`]: crate::datetime::TimeFormatter
44
///
45
/// # Examples
46
///
47
/// ```
48
/// use icu::calendar::DateTime;
49
/// use icu::datetime::{options::length::Time, TimeFormatter};
50
/// use icu::locid::locale;
51
/// use writeable::assert_writeable_eq;
52
///
53
/// let tf =
54
///     TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
55
///         .expect("Failed to create TimeFormatter instance.");
56
///
57
/// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
58
///     .expect("Failed to construct DateTime.");
59
///
60
/// assert_writeable_eq!(tf.format(&datetime), "12:34 PM");
61
/// ```
62
///
63
/// This model replicates that of `ICU` and `ECMA402`.
64
///
65
/// [data provider]: icu_provider
66
#[derive(Debug)]
67
pub struct TimeFormatter(pub(super) raw::TimeFormatter);
68
69
impl TimeFormatter {
70
    /// Constructor that takes a selected locale and a list of preferences, then collects all
71
    /// compiled data necessary to format date and time values into the given locale,
72
    /// using the given style.
73
    ///
74
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
75
    ///
76
    /// [📚 Help choosing a constructor](icu_provider::constructors)
77
    ///
78
    /// # Examples
79
    ///
80
    /// ```
81
    /// use icu::datetime::{options::length::Time, TimeFormatter};
82
    /// use icu::locid::locale;
83
    ///
84
    /// TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
85
    ///     .unwrap();
86
    /// ```
87
    #[cfg(feature = "compiled_data")]
88
0
    pub fn try_new_with_length(
89
0
        locale: &DataLocale,
90
0
        length: length::Time,
91
0
    ) -> Result<Self, DateTimeError> {
92
0
        let preferences = Some(preferences::Bag::from_data_locale(locale));
93
0
94
0
        Ok(Self(raw::TimeFormatter::try_new(
95
0
            locale,
96
0
            length,
97
0
            preferences,
98
0
        )?))
99
0
    }
100
101
    icu_provider::gen_any_buffer_data_constructors!(
102
        locale: include,
103
        length: length::Time,
104
        error: DateTimeError,
105
        #[cfg(skip)]
106
        functions: [
107
            try_new_with_length,
108
            try_new_with_length_with_any_provider,
109
            try_new_with_length_with_buffer_provider,
110
            try_new_with_length_unstable,
111
            Self,
112
        ]
113
    );
114
115
    #[inline]
116
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_with_length)]
117
0
    pub fn try_new_with_length_unstable<D>(
118
0
        provider: &D,
119
0
        locale: &DataLocale,
120
0
        length: length::Time,
121
0
    ) -> Result<Self, DateTimeError>
122
0
    where
123
0
        D: DataProvider<TimeLengthsV1Marker>
124
0
            + DataProvider<TimeSymbolsV1Marker>
125
0
            + DataProvider<DecimalSymbolsV1Marker>
126
0
            + ?Sized,
127
0
    {
128
0
        let preferences = Some(preferences::Bag::from_data_locale(locale));
129
0
130
0
        Ok(Self(raw::TimeFormatter::try_new_unstable(
131
0
            provider,
132
0
            locale,
133
0
            length,
134
0
            preferences,
135
0
        )?))
136
0
    }
Unexecuted instantiation: <icu_datetime::datetime::TimeFormatter>::try_new_with_length_unstable::<icu_provider::any::DowncastingAnyProvider<icu_provider_adapters::empty::EmptyDataProvider>>
Unexecuted instantiation: <icu_datetime::datetime::TimeFormatter>::try_new_with_length_unstable::<_>
137
138
    /// Takes a [`IsoTimeInput`] implementer and returns an instance of a [`FormattedDateTime`]
139
    /// that contains all information necessary to display a formatted date and operate on it.
140
    ///
141
    /// # Examples
142
    ///
143
    /// ```
144
    /// use icu::calendar::DateTime;
145
    /// use icu::datetime::{options::length::Time, TimeFormatter};
146
    /// use icu::locid::locale;
147
    /// use writeable::assert_writeable_eq;
148
    ///
149
    /// let tf =
150
    ///     TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
151
    ///         .expect("Failed to create TimeFormatter instance.");
152
    ///
153
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
154
    ///     .expect("Failed to construct DateTime.");
155
    ///
156
    /// assert_writeable_eq!(tf.format(&datetime), "12:34 PM");
157
    /// ```
158
    #[inline]
159
0
    pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
160
0
    where
161
0
        T: IsoTimeInput,
162
0
    {
163
0
        self.0.format(value)
164
0
    }
Unexecuted instantiation: <icu_datetime::datetime::TimeFormatter>::format::<icu_calendar::datetime::DateTime<alloc::sync::Arc<icu_calendar::any_calendar::AnyCalendar>>>
Unexecuted instantiation: <icu_datetime::datetime::TimeFormatter>::format::<icu_calendar::datetime::DateTime<icu_calendar::iso::Iso>>
Unexecuted instantiation: <icu_datetime::datetime::TimeFormatter>::format::<icu_calendar::types::Time>
Unexecuted instantiation: <icu_datetime::datetime::TimeFormatter>::format::<_>
165
166
    /// Takes a [`IsoTimeInput`] implementer and returns it formatted as a string.
167
    ///
168
    /// # Examples
169
    ///
170
    /// ```
171
    /// use icu::calendar::DateTime;
172
    /// use icu::datetime::{options::length::Time, TimeFormatter};
173
    /// use icu::locid::locale;
174
    /// let tf =
175
    ///     TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
176
    ///         .expect("Failed to create TimeFormatter instance.");
177
    ///
178
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
179
    ///     .expect("Failed to construct DateTime.");
180
    ///
181
    /// assert_eq!(tf.format_to_string(&datetime), "12:34 PM");
182
    /// ```
183
    #[inline]
184
0
    pub fn format_to_string(&self, value: &impl IsoTimeInput) -> String {
185
0
        self.format(value).write_to_string().into_owned()
186
0
    }
187
}
188
189
size_test!(
190
    TypedDateFormatter<icu_calendar::Gregorian>,
191
    typed_date_formatter_size,
192
    4400
193
);
194
195
/// [`TypedDateFormatter`] is a formatter capable of formatting
196
/// dates from a calendar selected at compile time. For the difference between this
197
/// and [`DateFormatter`](crate::DateFormatter), please read the [crate root docs][crate].
198
///
199
/// When constructed, it uses data from the [data provider], selected locale and provided options to
200
/// collect all data necessary to format any dates into that locale.
201
///
202
/// For that reason, one should think of the process of formatting a date in two steps - first, a computational
203
/// heavy construction of [`TypedDateFormatter`], and then fast formatting of [`DateInput`] data using the instance.
204
#[doc = typed_date_formatter_size!()]
205
///
206
/// [`icu::datetime`]: crate
207
///
208
/// # Examples
209
///
210
/// ```
211
/// use icu::calendar::{Date, Gregorian};
212
/// use icu::datetime::{options::length, TypedDateFormatter};
213
/// use icu::locid::locale;
214
/// use writeable::assert_writeable_eq;
215
///
216
/// let df = TypedDateFormatter::<Gregorian>::try_new_with_length(
217
///     &locale!("en").into(),
218
///     length::Date::Full,
219
/// )
220
/// .expect("Failed to create TypedDateFormatter instance.");
221
///
222
/// let date = Date::try_new_gregorian_date(2020, 9, 1)
223
///     .expect("Failed to construct Date.");
224
///
225
/// assert_writeable_eq!(df.format(&date), "Tuesday, September 1, 2020");
226
/// ```
227
///
228
/// This model replicates that of `ICU` and `ECMA402`.
229
///
230
/// [data provider]: icu_provider
231
#[derive(Debug)]
232
pub struct TypedDateFormatter<C>(pub(super) raw::DateFormatter, PhantomData<C>);
233
234
impl<C: CldrCalendar> TypedDateFormatter<C> {
235
    /// Constructor that takes a selected locale and a list of options, then collects all
236
    /// compiled data necessary to format date and time values into the given locale.
237
    ///
238
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
239
    ///
240
    /// [📚 Help choosing a constructor](icu_provider::constructors)
241
    ///
242
    /// # Examples
243
    ///
244
    /// ```
245
    /// use icu::calendar::Date;
246
    /// use icu::calendar::Gregorian;
247
    /// use icu::datetime::{options::length, TypedDateFormatter};
248
    /// use icu::locid::locale;
249
    /// use writeable::assert_writeable_eq;
250
    ///
251
    /// let formatter = TypedDateFormatter::<Gregorian>::try_new_with_length(
252
    ///     &locale!("en").into(),
253
    ///     length::Date::Full,
254
    /// )
255
    /// .unwrap();
256
    ///
257
    /// assert_writeable_eq!(
258
    ///     formatter.format(&Date::try_new_gregorian_date(2022, 8, 29).unwrap()),
259
    ///     "Monday, August 29, 2022",
260
    /// );
261
    /// ```
262
    ///
263
    /// If the locale has a calendar keyword, the keyword is ignored in favor of the
264
    /// type parameter on the [`TypedDateFormatter`]. To obey the calendar keyword,
265
    /// use [`DateFormatter`] instead.
266
    ///
267
    /// ```
268
    /// use icu::calendar::indian::Indian;
269
    /// use icu::calendar::Date;
270
    /// use icu::datetime::{options::length, TypedDateFormatter};
271
    /// use icu::locid::locale;
272
    /// use writeable::assert_writeable_eq;
273
    ///
274
    /// let formatter = TypedDateFormatter::<Indian>::try_new_with_length(
275
    ///     &locale!("en-u-ca-japanese").into(),
276
    ///     length::Date::Full,
277
    /// )
278
    /// .unwrap();
279
    ///
280
    /// // Indian format from type wins over locale keyword
281
    /// assert_writeable_eq!(
282
    ///     formatter.format(&Date::try_new_indian_date(1944, 6, 7).unwrap()),
283
    ///     "Monday, Bhadra 7, 1944 Saka",
284
    /// );
285
    /// ```
286
    ///
287
    /// [`DateFormatter`]: crate::DateFormatter
288
    #[cfg(feature = "compiled_data")]
289
0
    pub fn try_new_with_length(
290
0
        locale: &DataLocale,
291
0
        length: length::Date,
292
0
    ) -> Result<Self, DateTimeError>
293
0
    where
294
0
        crate::provider::Baked: icu_provider::DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
295
0
            + icu_provider::DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
296
0
    {
297
0
        Ok(Self(
298
0
            raw::DateFormatter::try_new(
299
0
                calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
300
0
                || {
301
0
                    calendar::load_symbols_for_cldr_calendar::<C, _>(
302
0
                        &crate::provider::Baked,
303
0
                        locale,
304
0
                    )
305
0
                },
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<icu_calendar::gregorian::Gregorian>>::try_new_with_length::{closure#0}
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<_>>::try_new_with_length::{closure#0}
306
0
                locale,
307
0
                length,
308
0
            )?,
309
0
            PhantomData,
310
        ))
311
0
    }
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<icu_calendar::gregorian::Gregorian>>::try_new_with_length
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<_>>::try_new_with_length
312
313
    icu_provider::gen_any_buffer_data_constructors!(
314
        locale: include,
315
        length: length::Date,
316
        error: DateTimeError,
317
        #[cfg(skip)]
318
        functions: [
319
            try_new_with_length,
320
            try_new_with_length_with_any_provider,
321
            try_new_with_length_with_buffer_provider,
322
            try_new_with_length_unstable,
323
            Self,
324
        ]
325
    );
326
327
    #[inline]
328
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_with_length)]
329
0
    pub fn try_new_with_length_unstable<D>(
330
0
        provider: &D,
331
0
        locale: &DataLocale,
332
0
        length: length::Date,
333
0
    ) -> Result<Self, DateTimeError>
334
0
    where
335
0
        D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
336
0
            + DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
337
0
            + DataProvider<DecimalSymbolsV1Marker>
338
0
            + DataProvider<OrdinalV1Marker>
339
0
            + DataProvider<WeekDataV1Marker>
340
0
            + ?Sized,
341
0
    {
342
0
        Ok(Self(
343
0
            raw::DateFormatter::try_new_unstable(
344
0
                provider,
345
0
                calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
346
0
                || calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<icu_calendar::gregorian::Gregorian>>::try_new_with_length_unstable::<icu_provider::any::DowncastingAnyProvider<icu_provider_adapters::empty::EmptyDataProvider>>::{closure#0}
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<_>>::try_new_with_length_unstable::<_>::{closure#0}
347
0
                locale,
348
0
                length,
349
0
            )?,
350
0
            PhantomData,
351
        ))
352
0
    }
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<icu_calendar::gregorian::Gregorian>>::try_new_with_length_unstable::<icu_provider::any::DowncastingAnyProvider<icu_provider_adapters::empty::EmptyDataProvider>>
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<_>>::try_new_with_length_unstable::<_>
353
354
    /// Takes a [`DateTimeInput`] implementer and returns an instance of a [`FormattedDateTime`]
355
    /// that contains all information necessary to display a formatted date and operate on it.
356
    ///
357
    /// # Examples
358
    ///
359
    /// ```
360
    /// use icu::calendar::{Date, Gregorian};
361
    /// use icu::datetime::{options::length, TypedDateFormatter};
362
    /// use icu::locid::locale;
363
    /// use writeable::assert_writeable_eq;
364
    /// let df = TypedDateFormatter::<Gregorian>::try_new_with_length(
365
    ///     &locale!("en").into(),
366
    ///     length::Date::Full,
367
    /// )
368
    /// .expect("Failed to create TypedDateFormatter instance.");
369
    ///
370
    /// let date = Date::try_new_gregorian_date(2020, 9, 1)
371
    ///     .expect("Failed to construct Date.");
372
    ///
373
    /// assert_writeable_eq!(df.format(&date), "Tuesday, September 1, 2020");
374
    /// ```
375
    #[inline]
376
0
    pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
377
0
    where
378
0
        T: DateInput<Calendar = C>,
379
0
    {
380
0
        self.0.format(value)
381
0
    }
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<icu_calendar::gregorian::Gregorian>>::format::<icu_calendar::date::Date<icu_calendar::gregorian::Gregorian>>
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<icu_calendar::gregorian::Gregorian>>::format::<icu_calendar::datetime::DateTime<icu_calendar::gregorian::Gregorian>>
Unexecuted instantiation: <icu_datetime::datetime::TypedDateFormatter<_>>::format::<_>
382
383
    /// Takes a [`DateTimeInput`] implementer and returns it formatted as a string.
384
    ///
385
    /// # Examples
386
    ///
387
    /// ```
388
    /// use icu::calendar::{Date, Gregorian};
389
    /// use icu::datetime::{options::length, TypedDateFormatter};
390
    /// use icu::locid::locale;
391
    /// let df = TypedDateFormatter::<Gregorian>::try_new_with_length(
392
    ///     &locale!("en").into(),
393
    ///     length::Date::Short,
394
    /// )
395
    /// .expect("Failed to create TypedDateTimeFormatter instance.");
396
    ///
397
    /// let date = Date::try_new_gregorian_date(2020, 9, 1)
398
    ///     .expect("Failed to construct Date.");
399
    ///
400
    /// assert_eq!(df.format_to_string(&date), "9/1/20");
401
    /// ```
402
    #[inline]
403
0
    pub fn format_to_string(&self, value: &impl DateInput<Calendar = C>) -> String {
404
0
        self.format(value).write_to_string().into_owned()
405
0
    }
406
}
407
408
size_test!(
409
    TypedDateTimeFormatter<icu_calendar::Gregorian>,
410
    typed_date_time_formatter_size,
411
    5152
412
);
413
414
/// [`TypedDateTimeFormatter`] is a formatter capable of formatting
415
/// date/times from a calendar selected at compile time. For the difference between this
416
///  and [`DateTimeFormatter`](crate::DateTimeFormatter), please read the [crate root docs][crate].
417
///
418
/// When constructed, it uses data from the [data provider], selected locale and provided options to
419
/// collect all data necessary to format any dates into that locale.
420
///
421
/// For that reason, one should think of the process of formatting a date in two steps - first, a computational
422
/// heavy construction of [`TypedDateTimeFormatter`], and then fast formatting of [`DateInput`] data using the instance.
423
#[doc = typed_date_time_formatter_size!()]
424
///
425
/// [`icu::datetime`]: crate
426
/// [`TypedDateTimeFormatter`]: crate::datetime::TypedDateTimeFormatter
427
///
428
/// # Examples
429
///
430
/// ```
431
/// use icu::calendar::{DateTime, Gregorian};
432
/// use icu::datetime::{options::length, TypedDateTimeFormatter};
433
/// use icu::locid::locale;
434
/// use writeable::assert_writeable_eq;
435
///
436
/// let mut options = length::Bag::from_date_time_style(
437
///     length::Date::Medium,
438
///     length::Time::Short,
439
/// );
440
///
441
/// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
442
///     &locale!("en").into(),
443
///     options.into(),
444
/// )
445
/// .expect("Failed to create TypedDateTimeFormatter instance.");
446
///
447
/// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
448
///     .expect("Failed to construct DateTime.");
449
///
450
/// assert_writeable_eq!(dtf.format(&datetime), "Sep 1, 2020, 12:34 PM");
451
/// ```
452
///
453
/// This model replicates that of `ICU` and `ECMA402`.
454
///
455
/// [data provider]: icu_provider
456
#[derive(Debug)]
457
pub struct TypedDateTimeFormatter<C>(pub(super) raw::DateTimeFormatter, PhantomData<C>);
458
459
impl<C: CldrCalendar> TypedDateTimeFormatter<C> {
460
    /// Constructor that takes a [`TimeFormatter`] and [`TypedDateFormatter`] and combines them into a [`TypedDateTimeFormatter`].
461
    ///
462
    /// # Examples
463
    ///
464
    /// ```
465
    /// use icu::calendar::Gregorian;
466
    /// use icu::datetime::{
467
    ///     options::length, TimeFormatter, TypedDateFormatter,
468
    ///     TypedDateTimeFormatter,
469
    /// };
470
    /// use icu::locid::locale;
471
    ///
472
    /// let tf = TimeFormatter::try_new_with_length(
473
    ///     &locale!("en").into(),
474
    ///     length::Time::Short,
475
    /// )
476
    /// .expect("Failed to create TimeFormatter instance.");
477
    /// let df = TypedDateFormatter::<Gregorian>::try_new_with_length(
478
    ///     &locale!("en").into(),
479
    ///     length::Date::Short,
480
    /// )
481
    /// .expect("Failed to create TypedDateFormatter instance.");
482
    ///
483
    /// TypedDateTimeFormatter::<Gregorian>::try_from_date_and_time(df, tf)
484
    ///     .unwrap();
485
    /// ```
486
    ///
487
    /// [data provider]: icu_provider
488
    #[inline]
489
0
    pub fn try_from_date_and_time(
490
0
        date: TypedDateFormatter<C>,
491
0
        time: TimeFormatter,
492
0
    ) -> Result<Self, DateTimeError>
493
0
where {
494
0
        Ok(Self(
495
0
            raw::DateTimeFormatter::try_from_date_and_time(date.0, time.0)?,
496
0
            PhantomData,
497
        ))
498
0
    }
499
500
    /// Constructor that takes a selected locale, then collects all
501
    /// compiled data necessary to format date and time values into the given locale.
502
    ///
503
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
504
    ///
505
    /// [📚 Help choosing a constructor](icu_provider::constructors)
506
    ///
507
    /// # Examples
508
    ///
509
    /// ```
510
    /// use icu::calendar::{DateTime, Gregorian};
511
    /// use icu::datetime::{options::length, TypedDateTimeFormatter};
512
    /// use icu::locid::locale;
513
    /// use writeable::assert_writeable_eq;
514
    ///
515
    /// let options = length::Bag::from_date_time_style(
516
    ///     length::Date::Medium,
517
    ///     length::Time::Medium,
518
    /// );
519
    ///
520
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
521
    ///     &locale!("en").into(),
522
    ///     options.into(),
523
    /// )
524
    /// .unwrap();
525
    ///
526
    /// let datetime =
527
    ///     DateTime::try_new_gregorian_datetime(2022, 8, 31, 1, 2, 3).unwrap();
528
    ///
529
    /// assert_writeable_eq!(dtf.format(&datetime), "Aug 31, 2022, 1:02:03 AM");
530
    /// ```
531
    ///
532
    /// [data provider]: icu_provider
533
    #[cfg(feature = "compiled_data")]
534
0
    pub fn try_new(
535
0
        locale: &DataLocale,
536
0
        options: DateTimeFormatterOptions,
537
0
    ) -> Result<Self, DateTimeError>
538
0
    where
539
0
        crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>,
540
0
        crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
541
0
    {
542
0
        let patterns = PatternSelector::for_options(
543
0
            &crate::provider::Baked,
544
0
            calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
545
0
            locale,
546
0
            &options,
547
0
        )
548
0
        .map_err(|e| match e {
549
0
            PatternForLengthError::Data(e) => DateTimeError::Data(e),
550
0
            PatternForLengthError::Pattern(e) => DateTimeError::Pattern(e),
551
0
        })?;
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<icu_calendar::gregorian::Gregorian>>::try_new::{closure#0}
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<_>>::try_new::{closure#0}
552
        Ok(Self(
553
0
            raw::DateTimeFormatter::try_new(
554
0
                patterns,
555
0
                || {
556
0
                    calendar::load_symbols_for_cldr_calendar::<C, _>(
557
0
                        &crate::provider::Baked,
558
0
                        locale,
559
0
                    )
560
0
                },
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<icu_calendar::gregorian::Gregorian>>::try_new::{closure#1}
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<_>>::try_new::{closure#1}
561
0
                locale,
562
0
            )?,
563
0
            PhantomData,
564
        ))
565
0
    }
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<icu_calendar::gregorian::Gregorian>>::try_new
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<_>>::try_new
566
567
    icu_provider::gen_any_buffer_data_constructors!(
568
        locale: include,
569
        options: DateTimeFormatterOptions,
570
        error: DateTimeError,
571
        #[cfg(skip)]
572
        functions: [
573
            try_new,
574
            try_new_with_any_provider,
575
            try_new_with_buffer_provider,
576
            try_new_unstable,
577
            Self
578
        ]
579
    );
580
581
    #[inline]
582
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
583
0
    pub fn try_new_unstable<D>(
584
0
        provider: &D,
585
0
        locale: &DataLocale,
586
0
        options: DateTimeFormatterOptions,
587
0
    ) -> Result<Self, DateTimeError>
588
0
    where
589
0
        D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
590
0
            + DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
591
0
            + DataProvider<TimeSymbolsV1Marker>
592
0
            + DataProvider<TimeLengthsV1Marker>
593
0
            + DataProvider<DecimalSymbolsV1Marker>
594
0
            + DataProvider<OrdinalV1Marker>
595
0
            + DataProvider<WeekDataV1Marker>
596
0
            + ?Sized,
597
0
    {
598
0
        let patterns = PatternSelector::for_options(
599
0
            provider,
600
0
            calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
601
0
            locale,
602
0
            &options,
603
0
        )
604
0
        .map_err(|e| match e {
605
0
            PatternForLengthError::Data(e) => DateTimeError::Data(e),
606
0
            PatternForLengthError::Pattern(e) => DateTimeError::Pattern(e),
607
0
        })?;
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<icu_calendar::gregorian::Gregorian>>::try_new_unstable::<icu_provider::any::DowncastingAnyProvider<icu_provider_adapters::empty::EmptyDataProvider>>::{closure#0}
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<_>>::try_new_unstable::<_>::{closure#0}
608
        Ok(Self(
609
0
            raw::DateTimeFormatter::try_new_unstable(
610
0
                provider,
611
0
                patterns,
612
0
                || calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<icu_calendar::gregorian::Gregorian>>::try_new_unstable::<icu_provider::any::DowncastingAnyProvider<icu_provider_adapters::empty::EmptyDataProvider>>::{closure#1}
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<_>>::try_new_unstable::<_>::{closure#1}
613
0
                locale,
614
0
            )?,
615
0
            PhantomData,
616
        ))
617
0
    }
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<icu_calendar::gregorian::Gregorian>>::try_new_unstable::<icu_provider::any::DowncastingAnyProvider<icu_provider_adapters::empty::EmptyDataProvider>>
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<_>>::try_new_unstable::<_>
618
619
    /// Constructor that supports experimental options using compiled data.
620
    ///
621
    /// ✨ *Enabled with the `compiled_data` and `experimental` Cargo features.*
622
    ///
623
    /// [📚 Help choosing a constructor](icu_provider::constructors)
624
    ///
625
    /// <div class="stab unstable">
626
    /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
627
    /// including in SemVer minor releases. It can be enabled with the "experimental" Cargo feature
628
    /// of the icu meta-crate. Use with caution.
629
    /// <a href="https://github.com/unicode-org/icu4x/issues/1317">#1317</a>
630
    /// </div>
631
    ///
632
    /// # Examples
633
    ///
634
    /// ```
635
    /// use icu::calendar::{DateTime, Gregorian};
636
    /// use icu::datetime::{options::components, TypedDateTimeFormatter};
637
    /// use icu::locid::locale;
638
    /// use writeable::assert_writeable_eq;
639
    ///
640
    /// let mut options = components::Bag::default();
641
    /// options.year = Some(components::Year::Numeric);
642
    /// options.month = Some(components::Month::Long);
643
    ///
644
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new_experimental(
645
    ///     &locale!("en").into(),
646
    ///     options.into(),
647
    /// )
648
    /// .unwrap();
649
    ///
650
    /// let datetime =
651
    ///     DateTime::try_new_gregorian_datetime(2022, 8, 31, 1, 2, 3).unwrap();
652
    ///
653
    /// assert_writeable_eq!(dtf.format(&datetime), "August 2022");
654
    /// ```
655
    ///
656
    /// [data provider]: icu_provider
657
    #[cfg(feature = "experimental")]
658
    #[inline]
659
    #[cfg(feature = "compiled_data")]
660
    pub fn try_new_experimental(
661
        locale: &DataLocale,
662
        options: DateTimeFormatterOptions,
663
    ) -> Result<Self, DateTimeError>
664
    where
665
        crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>,
666
        crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
667
    {
668
        let patterns = PatternSelector::for_options_experimental(
669
            &crate::provider::Baked,
670
            calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
671
            locale,
672
            &C::DEFAULT_BCP_47_IDENTIFIER,
673
            &options,
674
        )
675
        .map_err(|e| match e {
676
            UnsupportedOptionsOrDataOrPatternError::UnsupportedOptions => {
677
                DateTimeError::UnsupportedOptions
678
            }
679
            UnsupportedOptionsOrDataOrPatternError::Data(e) => DateTimeError::Data(e),
680
            UnsupportedOptionsOrDataOrPatternError::Pattern(e) => DateTimeError::Pattern(e),
681
        })?;
682
        Ok(Self(
683
            raw::DateTimeFormatter::try_new(
684
                patterns,
685
                || {
686
                    calendar::load_symbols_for_cldr_calendar::<C, _>(
687
                        &crate::provider::Baked,
688
                        locale,
689
                    )
690
                },
691
                locale,
692
            )?,
693
            PhantomData,
694
        ))
695
    }
696
697
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_experimental)]
698
    #[cfg(feature = "experimental")]
699
    #[inline]
700
    pub fn try_new_experimental_unstable<D>(
701
        provider: &D,
702
        locale: &DataLocale,
703
        options: DateTimeFormatterOptions,
704
    ) -> Result<Self, DateTimeError>
705
    where
706
        D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
707
            + DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
708
            + DataProvider<TimeSymbolsV1Marker>
709
            + DataProvider<TimeLengthsV1Marker>
710
            + DataProvider<crate::provider::calendar::DateSkeletonPatternsV1Marker>
711
            + DataProvider<DecimalSymbolsV1Marker>
712
            + DataProvider<OrdinalV1Marker>
713
            + DataProvider<WeekDataV1Marker>
714
            + ?Sized,
715
    {
716
        let patterns = PatternSelector::for_options_experimental(
717
            provider,
718
            calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
719
            locale,
720
            &C::DEFAULT_BCP_47_IDENTIFIER,
721
            &options,
722
        )
723
        .map_err(|e| match e {
724
            UnsupportedOptionsOrDataOrPatternError::UnsupportedOptions => {
725
                DateTimeError::UnsupportedOptions
726
            }
727
            UnsupportedOptionsOrDataOrPatternError::Data(e) => DateTimeError::Data(e),
728
            UnsupportedOptionsOrDataOrPatternError::Pattern(e) => DateTimeError::Pattern(e),
729
        })?;
730
731
        Ok(Self(
732
            raw::DateTimeFormatter::try_new_unstable(
733
                provider,
734
                patterns,
735
                || calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
736
                locale,
737
            )?,
738
            PhantomData,
739
        ))
740
    }
741
742
    /// Takes a [`DateTimeInput`] implementer and returns an instance of a [`FormattedDateTime`]
743
    /// that contains all information necessary to display a formatted date and operate on it.
744
    ///
745
    /// # Examples
746
    ///
747
    /// ```
748
    /// use icu::calendar::{DateTime, Gregorian};
749
    /// use icu::datetime::TypedDateTimeFormatter;
750
    /// use writeable::assert_writeable_eq;
751
    /// use icu::locid::locale;
752
    /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium);
753
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(&locale!("en").into(), options.into())
754
    ///     .expect("Failed to create TypedDateTimeFormatter instance.");
755
    ///
756
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
757
    ///     .expect("Failed to construct DateTime.");
758
    ///
759
    /// assert_writeable_eq!(dtf.format(&datetime), "12:34:28 PM");
760
    /// ```
761
    #[inline]
762
0
    pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
763
0
    where
764
0
        T: DateTimeInput<Calendar = C>,
765
0
    {
766
0
        self.0.format(value)
767
0
    }
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<icu_calendar::gregorian::Gregorian>>::format::<icu_calendar::datetime::DateTime<icu_calendar::gregorian::Gregorian>>
Unexecuted instantiation: <icu_datetime::datetime::TypedDateTimeFormatter<_>>::format::<_>
768
769
    /// Takes a [`DateTimeInput`] implementer and returns it formatted as a string.
770
    ///
771
    /// # Examples
772
    ///
773
    /// ```
774
    /// use icu::calendar::{DateTime, Gregorian};
775
    /// use icu::datetime::TypedDateTimeFormatter;
776
    /// use icu::locid::locale;
777
    /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium);
778
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(&locale!("en").into(), options.into())
779
    ///     .expect("Failed to create TypedDateTimeFormatter instance.");
780
    ///
781
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
782
    ///     .expect("Failed to construct DateTime.");
783
    ///
784
    /// assert_eq!(dtf.format_to_string(&datetime), "12:34:28 PM");
785
    /// ```
786
    #[inline]
787
0
    pub fn format_to_string(&self, value: &impl DateTimeInput<Calendar = C>) -> String {
788
0
        self.format(value).write_to_string().into_owned()
789
0
    }
790
791
    /// Returns a [`components::Bag`](crate::options::components::Bag) that represents the resolved components for the
792
    /// options that were provided to the [`TypedDateTimeFormatter`]. The developer may request
793
    /// a certain set of options for a [`TypedDateTimeFormatter`] but the locale and resolution
794
    /// algorithm may change certain details of what actually gets resolved.
795
    ///
796
    /// # Examples
797
    ///
798
    /// ```
799
    /// use icu::calendar::Gregorian;
800
    /// use icu::datetime::{
801
    ///     options::{components, length},
802
    ///     TypedDateTimeFormatter,
803
    /// };
804
    /// use icu::locid::locale;
805
    ///
806
    /// let options = length::Bag::from_date_style(length::Date::Medium).into();
807
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
808
    ///     &locale!("en").into(),
809
    ///     options,
810
    /// )
811
    /// .expect("Failed to create TypedDateTimeFormatter instance.");
812
    ///
813
    /// let mut expected_components_bag = components::Bag::default();
814
    /// expected_components_bag.year = Some(components::Year::Numeric);
815
    /// expected_components_bag.month = Some(components::Month::Short);
816
    /// expected_components_bag.day = Some(components::Day::NumericDayOfMonth);
817
    ///
818
    /// assert_eq!(dtf.resolve_components(), expected_components_bag);
819
    /// ```
820
    #[cfg(feature = "experimental")]
821
    pub fn resolve_components(&self) -> crate::options::components::Bag {
822
        self.0.resolve_components()
823
    }
824
}
825
826
#[cfg(test)]
827
#[cfg(feature = "serde")]
828
#[cfg(feature = "compiled_data")]
829
mod tests {
830
    use super::*;
831
    use icu_calendar::DateTime;
832
    use icu_calendar::Gregorian;
833
834
    #[test]
835
    fn works_with_default_options() {
836
        assert_eq!(
837
            TypedDateTimeFormatter::<Gregorian>::try_new(Default::default(), Default::default(),)
838
                .unwrap()
839
                .format_to_string(
840
                    &DateTime::try_new_gregorian_datetime(2022, 9, 20, 0, 0, 0).unwrap()
841
                ),
842
            "2022 M09 20 00:00:00"
843
        );
844
    }
845
}