• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zbraniecki / icu4x / 8219362155

08 Mar 2024 01:21PM UTC coverage: 75.985% (+3.0%) from 73.009%
8219362155

push

github

web-flow
Bump diplomat (#4671)

And fix some Dart renames

49581 of 65251 relevant lines covered (75.99%)

519628.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

37.5
/components/datetime/src/datetime.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
//! The collection of code that is needed for handling formatting operations for DateTimes.
6
//! Central to this is the [`TypedDateTimeFormatter`].
7

8
use crate::{
9
    helpers::size_test,
10
    options::{length, preferences, DateTimeFormatterOptions},
11
    provider::calendar::{TimeLengthsV1Marker, TimeSymbolsV1Marker},
12
    provider::date_time::PatternSelector,
13
    raw,
14
};
15
use alloc::string::String;
16
use core::marker::PhantomData;
17
use icu_calendar::provider::WeekDataV1Marker;
18
use icu_decimal::provider::DecimalSymbolsV1Marker;
19
use icu_plurals::provider::OrdinalV1Marker;
20
use icu_provider::prelude::*;
21
use writeable::Writeable;
22

23
use crate::{
24
    calendar, calendar::CldrCalendar, input::DateInput, input::DateTimeInput, input::IsoTimeInput,
25
    DateTimeError, FormattedDateTime,
26
};
27

28
size_test!(TimeFormatter, time_formatter_size, 1200);
29

30
/// [`TimeFormatter`] is a structure of the [`icu_datetime`] component that provides time formatting only.
31
/// When constructed, it uses data from the [data provider], selected locale and provided preferences to
32
/// collect all data necessary to format any time into that locale.
33
///
34
/// For that reason, one should think of the process of formatting a time in two steps - first, a computational
35
/// heavy construction of [`TimeFormatter`], and then fast formatting of [`DateTimeInput`] data using the instance.
36
///
37
#[doc = time_formatter_size!()]
38
///
39
/// [`icu_datetime`]: crate
40
/// [`TypedDateTimeFormatter`]: crate::datetime::TimeFormatter
41
///
42
/// # Examples
43
///
44
/// ```
45
/// use icu::calendar::DateTime;
46
/// use icu::datetime::{options::length::Time, TimeFormatter};
47
/// use icu::locid::locale;
48
/// use writeable::assert_writeable_eq;
49
///
50
/// let tf =
51
///     TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
52
///         .expect("Failed to create TimeFormatter instance.");
53
///
54
/// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
55
///     .expect("Failed to construct DateTime.");
56
///
57
/// assert_writeable_eq!(tf.format(&datetime), "12:34 PM");
58
/// ```
59
///
60
/// This model replicates that of `ICU` and `ECMA402`.
61
///
62
/// [data provider]: icu_provider
63
#[derive(Debug)]
×
64
pub struct TimeFormatter(pub(super) raw::TimeFormatter);
×
65

66
impl TimeFormatter {
67
    /// Constructor that takes a selected locale and a list of preferences, then collects all
68
    /// compiled data necessary to format date and time values into the given locale,
69
    /// using the given style.
70
    ///
71
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
72
    ///
73
    /// [📚 Help choosing a constructor](icu_provider::constructors)
74
    ///
75
    /// # Examples
76
    ///
77
    /// ```
78
    /// use icu::datetime::{options::length::Time, TimeFormatter};
79
    /// use icu::locid::locale;
80
    ///
81
    /// TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
82
    ///     .unwrap();
83
    /// ```
84
    #[cfg(feature = "compiled_data")]
85
    pub fn try_new_with_length(
22✔
86
        locale: &DataLocale,
87
        length: length::Time,
88
    ) -> Result<Self, DateTimeError> {
89
        let preferences = Some(preferences::Bag::from_data_locale(locale));
22✔
90

91
        Ok(Self(raw::TimeFormatter::try_new(
22✔
92
            locale,
93
            length,
94
            preferences,
22✔
95
        )?))
×
96
    }
22✔
97

98
    icu_provider::gen_any_buffer_data_constructors!(
99
        locale: include,
100
        length: length::Time,
101
        error: DateTimeError,
102
        #[cfg(skip)]
103
        functions: [
104
            try_new_with_length,
105
            try_new_with_length_with_any_provider,
106
            try_new_with_length_with_buffer_provider,
107
            try_new_with_length_unstable,
108
            Self,
109
        ]
110
    );
111

112
    #[inline]
113
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_with_length)]
114
    pub fn try_new_with_length_unstable<D>(
×
115
        provider: &D,
116
        locale: &DataLocale,
117
        length: length::Time,
118
    ) -> Result<Self, DateTimeError>
119
    where
120
        D: DataProvider<TimeLengthsV1Marker>
121
            + DataProvider<TimeSymbolsV1Marker>
122
            + DataProvider<DecimalSymbolsV1Marker>
123
            + ?Sized,
124
    {
125
        let preferences = Some(preferences::Bag::from_data_locale(locale));
×
126

127
        Ok(Self(raw::TimeFormatter::try_new_unstable(
×
128
            provider,
129
            locale,
130
            length,
131
            preferences,
×
132
        )?))
×
133
    }
×
134

135
    /// Takes a [`IsoTimeInput`] implementer and returns an instance of a [`FormattedDateTime`]
136
    /// that contains all information necessary to display a formatted date and operate on it.
137
    ///
138
    /// # Examples
139
    ///
140
    /// ```
141
    /// use icu::calendar::DateTime;
142
    /// use icu::datetime::{options::length::Time, TimeFormatter};
143
    /// use icu::locid::locale;
144
    /// use writeable::assert_writeable_eq;
145
    ///
146
    /// let tf =
147
    ///     TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
148
    ///         .expect("Failed to create TimeFormatter instance.");
149
    ///
150
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
151
    ///     .expect("Failed to construct DateTime.");
152
    ///
153
    /// assert_writeable_eq!(tf.format(&datetime), "12:34 PM");
154
    /// ```
155
    #[inline]
156
    pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
×
157
    where
158
        T: IsoTimeInput,
159
    {
160
        self.0.format(value)
×
161
    }
×
162

163
    /// Takes a [`IsoTimeInput`] implementer and returns it formatted as a string.
164
    ///
165
    /// # Examples
166
    ///
167
    /// ```
168
    /// use icu::calendar::DateTime;
169
    /// use icu::datetime::{options::length::Time, TimeFormatter};
170
    /// use icu::locid::locale;
171
    /// let tf =
172
    ///     TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
173
    ///         .expect("Failed to create TimeFormatter instance.");
174
    ///
175
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
176
    ///     .expect("Failed to construct DateTime.");
177
    ///
178
    /// assert_eq!(tf.format_to_string(&datetime), "12:34 PM");
179
    /// ```
180
    #[inline]
181
    pub fn format_to_string(&self, value: &impl IsoTimeInput) -> String {
182
        self.format(value).write_to_string().into_owned()
183
    }
184
}
185

186
size_test!(
187
    TypedDateFormatter<icu_calendar::Gregorian>,
188
    typed_date_formatter_size,
189
    4400
190
);
191

192
/// [`TypedDateFormatter`] is a formatter capable of formatting
193
/// dates from a calendar selected at compile time. For the difference between this
194
/// and [`DateFormatter`](crate::DateFormatter), please read the [crate root docs][crate].
195
///
196
/// When constructed, it uses data from the [data provider], selected locale and provided options to
197
/// collect all data necessary to format any dates into that locale.
198
///
199
/// For that reason, one should think of the process of formatting a date in two steps - first, a computational
200
/// heavy construction of [`TypedDateFormatter`], and then fast formatting of [`DateInput`] data using the instance.
201
///
202
#[doc = typed_date_formatter_size!()]
203
///
204
/// [`icu_datetime`]: crate
205
///
206
/// # Examples
207
///
208
/// ```
209
/// use icu::calendar::{Date, Gregorian};
210
/// use icu::datetime::{options::length, TypedDateFormatter};
211
/// use icu::locid::locale;
212
/// use writeable::assert_writeable_eq;
213
///
214
/// let df = TypedDateFormatter::<Gregorian>::try_new_with_length(
215
///     &locale!("en").into(),
216
///     length::Date::Full,
217
/// )
218
/// .expect("Failed to create TypedDateFormatter instance.");
219
///
220
/// let date = Date::try_new_gregorian_date(2020, 9, 1)
221
///     .expect("Failed to construct Date.");
222
///
223
/// assert_writeable_eq!(df.format(&date), "Tuesday, September 1, 2020");
224
/// ```
225
///
226
/// This model replicates that of `ICU` and `ECMA402`.
227
///
228
/// [data provider]: icu_provider
229
#[derive(Debug)]
230
pub struct TypedDateFormatter<C>(pub(super) raw::DateFormatter, PhantomData<C>);
231

232
impl<C: CldrCalendar> TypedDateFormatter<C> {
233
    /// Constructor that takes a selected locale and a list of options, then collects all
234
    /// compiled data necessary to format date and time values into the given locale.
235
    ///
236
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
237
    ///
238
    /// [📚 Help choosing a constructor](icu_provider::constructors)
239
    ///
240
    /// # Examples
241
    ///
242
    /// ```
243
    /// use icu::calendar::Date;
244
    /// use icu::calendar::Gregorian;
245
    /// use icu::datetime::{options::length, TypedDateFormatter};
246
    /// use icu::locid::locale;
247
    /// use writeable::assert_writeable_eq;
248
    ///
249
    /// let formatter = TypedDateFormatter::<Gregorian>::try_new_with_length(
250
    ///     &locale!("en").into(),
251
    ///     length::Date::Full,
252
    /// )
253
    /// .unwrap();
254
    ///
255
    /// assert_writeable_eq!(
256
    ///     formatter.format(&Date::try_new_gregorian_date(2022, 8, 29).unwrap()),
257
    ///     "Monday, August 29, 2022",
258
    /// );
259
    /// ```
260
    ///
261
    /// If the locale has a calendar keyword, the keyword is ignored in favor of the
262
    /// type parameter on the [`TypedDateFormatter`]. To obey the calendar keyword,
263
    /// use [`DateFormatter`] instead.
264
    ///
265
    /// ```
266
    /// use icu::calendar::indian::Indian;
267
    /// use icu::calendar::Date;
268
    /// use icu::datetime::{options::length, TypedDateFormatter};
269
    /// use icu::locid::locale;
270
    /// use writeable::assert_writeable_eq;
271
    ///
272
    /// let formatter = TypedDateFormatter::<Indian>::try_new_with_length(
273
    ///     &locale!("en-u-ca-japanese").into(),
274
    ///     length::Date::Full,
275
    /// )
276
    /// .unwrap();
277
    ///
278
    /// // Indian format from type wins over locale keyword
279
    /// assert_writeable_eq!(
280
    ///     formatter.format(&Date::try_new_indian_date(1944, 6, 7).unwrap()),
281
    ///     "Monday, Bhadra 7, 1944 Saka",
282
    /// );
283
    /// ```
284
    ///
285
    /// [`DateFormatter`]: crate::DateFormatter
286
    #[cfg(feature = "compiled_data")]
287
    pub fn try_new_with_length(
×
288
        locale: &DataLocale,
289
        length: length::Date,
290
    ) -> Result<Self, DateTimeError>
291
    where
292
        crate::provider::Baked: icu_provider::DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
293
            + icu_provider::DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
294
    {
295
        Ok(Self(
×
296
            raw::DateFormatter::try_new(
×
297
                calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
×
298
                || {
×
299
                    calendar::load_symbols_for_cldr_calendar::<C, _>(
×
300
                        &crate::provider::Baked,
301
                        locale,
×
302
                    )
303
                },
×
304
                locale,
305
                length,
306
            )?,
×
307
            PhantomData,
308
        ))
309
    }
×
310

311
    icu_provider::gen_any_buffer_data_constructors!(
312
        locale: include,
313
        length: length::Date,
314
        error: DateTimeError,
315
        #[cfg(skip)]
316
        functions: [
317
            try_new_with_length,
318
            try_new_with_length_with_any_provider,
319
            try_new_with_length_with_buffer_provider,
320
            try_new_with_length_unstable,
321
            Self,
322
        ]
323
    );
324

325
    #[inline]
326
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_with_length)]
327
    pub fn try_new_with_length_unstable<D>(
×
328
        provider: &D,
329
        locale: &DataLocale,
330
        length: length::Date,
331
    ) -> Result<Self, DateTimeError>
332
    where
333
        D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
334
            + DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
335
            + DataProvider<DecimalSymbolsV1Marker>
336
            + DataProvider<OrdinalV1Marker>
337
            + DataProvider<WeekDataV1Marker>
338
            + ?Sized,
339
    {
340
        Ok(Self(
×
341
            raw::DateFormatter::try_new_unstable(
×
342
                provider,
343
                calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
×
344
                || calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
×
345
                locale,
346
                length,
347
            )?,
×
348
            PhantomData,
349
        ))
350
    }
×
351

352
    /// Takes a [`DateTimeInput`] implementer and returns an instance of a [`FormattedDateTime`]
353
    /// that contains all information necessary to display a formatted date and operate on it.
354
    ///
355
    /// # Examples
356
    ///
357
    /// ```
358
    /// use icu::calendar::{Date, Gregorian};
359
    /// use icu::datetime::{options::length, TypedDateFormatter};
360
    /// use icu::locid::locale;
361
    /// use writeable::assert_writeable_eq;
362
    /// let df = TypedDateFormatter::<Gregorian>::try_new_with_length(
363
    ///     &locale!("en").into(),
364
    ///     length::Date::Full,
365
    /// )
366
    /// .expect("Failed to create TypedDateFormatter instance.");
367
    ///
368
    /// let date = Date::try_new_gregorian_date(2020, 9, 1)
369
    ///     .expect("Failed to construct Date.");
370
    ///
371
    /// assert_writeable_eq!(df.format(&date), "Tuesday, September 1, 2020");
372
    /// ```
373
    #[inline]
374
    pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
×
375
    where
376
        T: DateInput<Calendar = C>,
377
    {
378
        self.0.format(value)
×
379
    }
×
380

381
    /// Takes a [`DateTimeInput`] implementer and returns it formatted as a string.
382
    ///
383
    /// # Examples
384
    ///
385
    /// ```
386
    /// use icu::calendar::{Date, Gregorian};
387
    /// use icu::datetime::{options::length, TypedDateFormatter};
388
    /// use icu::locid::locale;
389
    /// let df = TypedDateFormatter::<Gregorian>::try_new_with_length(
390
    ///     &locale!("en").into(),
391
    ///     length::Date::Short,
392
    /// )
393
    /// .expect("Failed to create TypedDateTimeFormatter instance.");
394
    ///
395
    /// let date = Date::try_new_gregorian_date(2020, 9, 1)
396
    ///     .expect("Failed to construct Date.");
397
    ///
398
    /// assert_eq!(df.format_to_string(&date), "9/1/20");
399
    /// ```
400
    #[inline]
401
    pub fn format_to_string(&self, value: &impl DateInput<Calendar = C>) -> String {
402
        self.format(value).write_to_string().into_owned()
403
    }
404
}
405

406
size_test!(
407
    TypedDateTimeFormatter<icu_calendar::Gregorian>,
408
    typed_date_time_formatter_size,
409
    5152
410
);
411

412
/// [`TypedDateTimeFormatter`] is a formatter capable of formatting
413
/// date/times from a calendar selected at compile time. For the difference between this
414
///  and [`DateTimeFormatter`](crate::DateTimeFormatter), please read the [crate root docs][crate].
415
///
416
/// When constructed, it uses data from the [data provider], selected locale and provided options to
417
/// collect all data necessary to format any dates into that locale.
418
///
419
/// For that reason, one should think of the process of formatting a date in two steps - first, a computational
420
/// heavy construction of [`TypedDateTimeFormatter`], and then fast formatting of [`DateInput`] data using the instance.
421
///
422
#[doc = typed_date_time_formatter_size!()]
423
///
424
/// [`icu_datetime`]: crate
425
/// [`TypedDateTimeFormatter`]: crate::datetime::TypedDateTimeFormatter
426
///
427
/// # Examples
428
///
429
/// ```
430
/// use icu::calendar::{DateTime, Gregorian};
431
/// use icu::datetime::{options::length, TypedDateTimeFormatter};
432
/// use icu::locid::locale;
433
/// use writeable::assert_writeable_eq;
434
///
435
/// let mut options = length::Bag::from_date_time_style(
436
///     length::Date::Medium,
437
///     length::Time::Short,
438
/// );
439
///
440
/// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
441
///     &locale!("en").into(),
442
///     options.into(),
443
/// )
444
/// .expect("Failed to create TypedDateTimeFormatter instance.");
445
///
446
/// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
447
///     .expect("Failed to construct DateTime.");
448
///
449
/// assert_writeable_eq!(dtf.format(&datetime), "Sep 1, 2020, 12:34 PM");
450
/// ```
451
///
452
/// This model replicates that of `ICU` and `ECMA402`.
453
///
454
/// [data provider]: icu_provider
455
#[derive(Debug)]
456
pub struct TypedDateTimeFormatter<C>(pub(super) raw::DateTimeFormatter, PhantomData<C>);
457

458
impl<C: CldrCalendar> TypedDateTimeFormatter<C> {
459
    /// Constructor that takes a [`TimeFormatter`] and [`TypedDateFormatter`] and combines them into a [`TypedDateTimeFormatter`].
460
    ///
461
    /// # Examples
462
    ///
463
    /// ```
464
    /// use icu::calendar::Gregorian;
465
    /// use icu::datetime::{
466
    ///     options::length, TimeFormatter, TypedDateFormatter,
467
    ///     TypedDateTimeFormatter,
468
    /// };
469
    /// use icu::locid::locale;
470
    ///
471
    /// let tf = TimeFormatter::try_new_with_length(
472
    ///     &locale!("en").into(),
473
    ///     length::Time::Short,
474
    /// )
475
    /// .expect("Failed to create TimeFormatter instance.");
476
    /// let df = TypedDateFormatter::<Gregorian>::try_new_with_length(
477
    ///     &locale!("en").into(),
478
    ///     length::Date::Short,
479
    /// )
480
    /// .expect("Failed to create TypedDateFormatter instance.");
481
    ///
482
    /// TypedDateTimeFormatter::<Gregorian>::try_from_date_and_time(df, tf)
483
    ///     .unwrap();
484
    /// ```
485
    ///
486
    /// [data provider]: icu_provider
487
    #[inline]
488
    pub fn try_from_date_and_time(
489
        date: TypedDateFormatter<C>,
490
        time: TimeFormatter,
491
    ) -> Result<Self, DateTimeError>
492
where {
493
        Ok(Self(
494
            raw::DateTimeFormatter::try_from_date_and_time(date.0, time.0)?,
495
            PhantomData,
496
        ))
497
    }
498

499
    /// Constructor that takes a selected locale, then collects all
500
    /// compiled data necessary to format date and time values into the given locale.
501
    ///
502
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
503
    ///
504
    /// [📚 Help choosing a constructor](icu_provider::constructors)
505
    ///
506
    /// # Examples
507
    ///
508
    /// ```
509
    /// use icu::calendar::{DateTime, Gregorian};
510
    /// use icu::datetime::{options::length, TypedDateTimeFormatter};
511
    /// use icu::locid::locale;
512
    /// use writeable::assert_writeable_eq;
513
    ///
514
    /// let options = length::Bag::from_date_time_style(
515
    ///     length::Date::Medium,
516
    ///     length::Time::Medium,
517
    /// );
518
    ///
519
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
520
    ///     &locale!("en").into(),
521
    ///     options.into(),
522
    /// )
523
    /// .unwrap();
524
    ///
525
    /// let datetime =
526
    ///     DateTime::try_new_gregorian_datetime(2022, 8, 31, 1, 2, 3).unwrap();
527
    ///
528
    /// assert_writeable_eq!(dtf.format(&datetime), "Aug 31, 2022, 1:02:03 AM");
529
    /// ```
530
    ///
531
    /// [data provider]: icu_provider
532
    #[cfg(feature = "compiled_data")]
533
    pub fn try_new(
1✔
534
        locale: &DataLocale,
535
        options: DateTimeFormatterOptions,
536
    ) -> Result<Self, DateTimeError>
537
    where
538
        crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>,
539
        crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
540
    {
541
        let patterns = PatternSelector::for_options(
1✔
542
            &crate::provider::Baked,
543
            calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
1✔
544
            locale,
545
            &options,
546
        )?;
×
547
        Ok(Self(
1✔
548
            raw::DateTimeFormatter::try_new(
1✔
549
                patterns,
1✔
550
                || {
2✔
551
                    calendar::load_symbols_for_cldr_calendar::<C, _>(
1✔
552
                        &crate::provider::Baked,
553
                        locale,
1✔
554
                    )
555
                },
1✔
556
                locale,
557
            )?,
×
558
            PhantomData,
559
        ))
560
    }
1✔
561

562
    icu_provider::gen_any_buffer_data_constructors!(
563
        locale: include,
564
        options: DateTimeFormatterOptions,
565
        error: DateTimeError,
566
        #[cfg(skip)]
567
        functions: [
568
            try_new,
569
            try_new_with_any_provider,
570
            try_new_with_buffer_provider,
571
            try_new_unstable,
572
            Self
573
        ]
574
    );
575

576
    #[inline]
577
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
578
    pub fn try_new_unstable<D>(
×
579
        provider: &D,
580
        locale: &DataLocale,
581
        options: DateTimeFormatterOptions,
582
    ) -> Result<Self, DateTimeError>
583
    where
584
        D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
585
            + DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
586
            + DataProvider<TimeSymbolsV1Marker>
587
            + DataProvider<TimeLengthsV1Marker>
588
            + DataProvider<DecimalSymbolsV1Marker>
589
            + DataProvider<OrdinalV1Marker>
590
            + DataProvider<WeekDataV1Marker>
591
            + ?Sized,
592
    {
593
        let patterns = PatternSelector::for_options(
×
594
            provider,
595
            calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
×
596
            locale,
597
            &options,
598
        )?;
×
599
        Ok(Self(
×
600
            raw::DateTimeFormatter::try_new_unstable(
×
601
                provider,
602
                patterns,
×
603
                || calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
×
604
                locale,
605
            )?,
×
606
            PhantomData,
607
        ))
608
    }
×
609

610
    /// Constructor that supports experimental options using compiled data.
611
    ///
612
    /// ✨ *Enabled with the `compiled_data` and `experimental` Cargo features.*
613
    ///
614
    /// [📚 Help choosing a constructor](icu_provider::constructors)
615
    ///
616
    /// <div class="stab unstable">
617
    /// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
618
    /// including in SemVer minor releases. It can be enabled with the "experimental" Cargo feature
619
    /// of the icu meta-crate. Use with caution.
620
    /// <a href="https://github.com/unicode-org/icu4x/issues/1317">#1317</a>
621
    /// </div>
622
    ///
623
    /// # Examples
624
    ///
625
    /// ```
626
    /// use icu::calendar::{DateTime, Gregorian};
627
    /// use icu::datetime::{options::components, TypedDateTimeFormatter};
628
    /// use icu::locid::locale;
629
    /// use writeable::assert_writeable_eq;
630
    ///
631
    /// let mut options = components::Bag::default();
632
    /// options.year = Some(components::Year::Numeric);
633
    /// options.month = Some(components::Month::Long);
634
    ///
635
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new_experimental(
636
    ///     &locale!("en").into(),
637
    ///     options.into(),
638
    /// )
639
    /// .unwrap();
640
    ///
641
    /// let datetime =
642
    ///     DateTime::try_new_gregorian_datetime(2022, 8, 31, 1, 2, 3).unwrap();
643
    ///
644
    /// assert_writeable_eq!(dtf.format(&datetime), "August 2022");
645
    /// ```
646
    ///
647
    /// [data provider]: icu_provider
648
    #[cfg(feature = "experimental")]
649
    #[inline]
650
    #[cfg(feature = "compiled_data")]
651
    pub fn try_new_experimental(
652
        locale: &DataLocale,
653
        options: DateTimeFormatterOptions,
654
    ) -> Result<Self, DateTimeError>
655
    where
656
        crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>,
657
        crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
658
    {
659
        let patterns = PatternSelector::for_options_experimental(
660
            &crate::provider::Baked,
661
            calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
662
            locale,
663
            &C::DEFAULT_BCP_47_IDENTIFIER,
664
            &options,
665
        )?;
666
        Ok(Self(
667
            raw::DateTimeFormatter::try_new(
668
                patterns,
669
                || {
670
                    calendar::load_symbols_for_cldr_calendar::<C, _>(
671
                        &crate::provider::Baked,
672
                        locale,
673
                    )
674
                },
675
                locale,
676
            )?,
677
            PhantomData,
678
        ))
679
    }
680

681
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_experimental)]
682
    #[cfg(feature = "experimental")]
683
    #[inline]
684
    pub fn try_new_experimental_unstable<D>(
685
        provider: &D,
686
        locale: &DataLocale,
687
        options: DateTimeFormatterOptions,
688
    ) -> Result<Self, DateTimeError>
689
    where
690
        D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
691
            + DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
692
            + DataProvider<TimeSymbolsV1Marker>
693
            + DataProvider<TimeLengthsV1Marker>
694
            + DataProvider<crate::provider::calendar::DateSkeletonPatternsV1Marker>
695
            + DataProvider<DecimalSymbolsV1Marker>
696
            + DataProvider<OrdinalV1Marker>
697
            + DataProvider<WeekDataV1Marker>
698
            + ?Sized,
699
    {
700
        let patterns = PatternSelector::for_options_experimental(
701
            provider,
702
            calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
703
            locale,
704
            &C::DEFAULT_BCP_47_IDENTIFIER,
705
            &options,
706
        )?;
707
        Ok(Self(
708
            raw::DateTimeFormatter::try_new_unstable(
709
                provider,
710
                patterns,
711
                || calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
712
                locale,
713
            )?,
714
            PhantomData,
715
        ))
716
    }
717

718
    /// Takes a [`DateTimeInput`] implementer and returns an instance of a [`FormattedDateTime`]
719
    /// that contains all information necessary to display a formatted date and operate on it.
720
    ///
721
    /// # Examples
722
    ///
723
    /// ```
724
    /// use icu::calendar::{DateTime, Gregorian};
725
    /// use icu::datetime::TypedDateTimeFormatter;
726
    /// use writeable::assert_writeable_eq;
727
    /// use icu::locid::locale;
728
    /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium);
729
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(&locale!("en").into(), options.into())
730
    ///     .expect("Failed to create TypedDateTimeFormatter instance.");
731
    ///
732
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
733
    ///     .expect("Failed to construct DateTime.");
734
    ///
735
    /// assert_writeable_eq!(dtf.format(&datetime), "12:34:28 PM");
736
    /// ```
737
    #[inline]
738
    pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
1✔
739
    where
740
        T: DateTimeInput<Calendar = C>,
741
    {
742
        self.0.format(value)
1✔
743
    }
1✔
744

745
    /// Takes a [`DateTimeInput`] implementer and returns it formatted as a string.
746
    ///
747
    /// # Examples
748
    ///
749
    /// ```
750
    /// use icu::calendar::{DateTime, Gregorian};
751
    /// use icu::datetime::TypedDateTimeFormatter;
752
    /// use icu::locid::locale;
753
    /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium);
754
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(&locale!("en").into(), options.into())
755
    ///     .expect("Failed to create TypedDateTimeFormatter instance.");
756
    ///
757
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
758
    ///     .expect("Failed to construct DateTime.");
759
    ///
760
    /// assert_eq!(dtf.format_to_string(&datetime), "12:34:28 PM");
761
    /// ```
762
    #[inline]
763
    pub fn format_to_string(&self, value: &impl DateTimeInput<Calendar = C>) -> String {
1✔
764
        self.format(value).write_to_string().into_owned()
1✔
765
    }
1✔
766

767
    /// Returns a [`components::Bag`](crate::options::components::Bag) that represents the resolved components for the
768
    /// options that were provided to the [`TypedDateTimeFormatter`]. The developer may request
769
    /// a certain set of options for a [`TypedDateTimeFormatter`] but the locale and resolution
770
    /// algorithm may change certain details of what actually gets resolved.
771
    ///
772
    /// # Examples
773
    ///
774
    /// ```
775
    /// use icu::calendar::Gregorian;
776
    /// use icu::datetime::{
777
    ///     options::{components, length}, TypedDateTimeFormatter,
778
    /// };
779
    /// use icu::locid::locale;
780
    ///
781
    /// let options = length::Bag::from_date_style(length::Date::Medium).into();
782
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
783
    ///     &locale!("en").into(),
784
    ///     options,
785
    /// )
786
    /// .expect("Failed to create TypedDateTimeFormatter instance.");
787
    ///
788
    /// let mut expected_components_bag = components::Bag::default();
789
    /// expected_components_bag.year = Some(components::Year::Numeric);
790
    /// expected_components_bag.month = Some(components::Month::Short);
791
    /// expected_components_bag.day = Some(components::Day::NumericDayOfMonth);
792
    ///
793
    /// assert_eq!(dtf.resolve_components(), expected_components_bag);
794
    /// ```
795
    #[cfg(feature = "experimental")]
796
    pub fn resolve_components(&self) -> crate::options::components::Bag {
797
        self.0.resolve_components()
798
    }
799
}
800

801
#[cfg(test)]
802
#[cfg(feature = "serde")]
803
#[cfg(feature = "compiled_data")]
804
mod tests {
805
    use super::*;
806
    use icu_calendar::DateTime;
807
    use icu_calendar::Gregorian;
808

809
    #[test]
810
    fn works_with_default_options() {
2✔
811
        assert_eq!(
1✔
812
            TypedDateTimeFormatter::<Gregorian>::try_new(Default::default(), Default::default(),)
2✔
813
                .unwrap()
814
                .format_to_string(
815
                    &DateTime::try_new_gregorian_datetime(2022, 9, 20, 0, 0, 0).unwrap()
1✔
816
                ),
817
            "2022 M09 20 00:00:00"
818
        );
819
    }
2✔
820
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc