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

zbraniecki / icu4x / 9014530096

08 May 2024 07:27PM UTC coverage: 76.402% (+0.2%) from 76.234%
9014530096

push

github

web-flow
Add missing std pointer-like impls for DataProvider, DynamicDataProvider (#4880)

0 of 3 new or added lines in 1 file covered. (0.0%)

3218 existing lines in 167 files now uncovered.

53328 of 69799 relevant lines covered (76.4%)

504343.42 hits per line

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

34.62
/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
#[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
///
41
#[doc = time_formatter_size!()]
42
///
43
/// [`icu_datetime`]: crate
44
/// [`TypedDateTimeFormatter`]: crate::datetime::TimeFormatter
45
///
46
/// # Examples
47
///
48
/// ```
49
/// use icu::calendar::DateTime;
50
/// use icu::datetime::{options::length::Time, TimeFormatter};
51
/// use icu::locid::locale;
52
/// use writeable::assert_writeable_eq;
53
///
54
/// let tf =
55
///     TimeFormatter::try_new_with_length(&locale!("en").into(), Time::Short)
56
///         .expect("Failed to create TimeFormatter instance.");
57
///
58
/// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
59
///     .expect("Failed to construct DateTime.");
60
///
61
/// assert_writeable_eq!(tf.format(&datetime), "12:34 PM");
62
/// ```
63
///
64
/// This model replicates that of `ICU` and `ECMA402`.
65
///
66
/// [data provider]: icu_provider
UNCOV
67
#[derive(Debug)]
×
UNCOV
68
pub struct TimeFormatter(pub(super) raw::TimeFormatter);
×
69

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

95
        Ok(Self(raw::TimeFormatter::try_new(
22✔
96
            locale,
97
            length,
98
            preferences,
22✔
UNCOV
99
        )?))
×
100
    }
22✔
101

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

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

131
        Ok(Self(raw::TimeFormatter::try_new_unstable(
×
132
            provider,
133
            locale,
134
            length,
UNCOV
135
            preferences,
×
UNCOV
136
        )?))
×
UNCOV
137
    }
×
138

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

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

190
size_test!(
191
    TypedDateFormatter<icu_calendar::Gregorian>,
192
    typed_date_formatter_size,
193
    4400
194
);
195

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

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

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

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

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

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

410
size_test!(
411
    TypedDateTimeFormatter<icu_calendar::Gregorian>,
412
    typed_date_time_formatter_size,
413
    5152
414
);
415

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

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

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

570
    icu_provider::gen_any_buffer_data_constructors!(
571
        locale: include,
572
        options: DateTimeFormatterOptions,
573
        error: DateTimeError,
574
        #[cfg(skip)]
575
        functions: [
576
            try_new,
577
            try_new_with_any_provider,
578
            try_new_with_buffer_provider,
579
            try_new_unstable,
580
            Self
581
        ]
582
    );
583

584
    #[inline]
585
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
UNCOV
586
    pub fn try_new_unstable<D>(
×
587
        provider: &D,
588
        locale: &DataLocale,
589
        options: DateTimeFormatterOptions,
590
    ) -> Result<Self, DateTimeError>
591
    where
592
        D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
593
            + DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
594
            + DataProvider<TimeSymbolsV1Marker>
595
            + DataProvider<TimeLengthsV1Marker>
596
            + DataProvider<DecimalSymbolsV1Marker>
597
            + DataProvider<OrdinalV1Marker>
598
            + DataProvider<WeekDataV1Marker>
599
            + ?Sized,
600
    {
UNCOV
601
        let patterns = PatternSelector::for_options(
×
602
            provider,
603
            calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
×
604
            locale,
605
            &options,
606
        )
UNCOV
607
        .map_err(|e| match e {
×
608
            PatternForLengthError::Data(e) => DateTimeError::Data(e),
×
UNCOV
609
            PatternForLengthError::Pattern(e) => DateTimeError::Pattern(e),
×
UNCOV
610
        })?;
×
UNCOV
611
        Ok(Self(
×
UNCOV
612
            raw::DateTimeFormatter::try_new_unstable(
×
613
                provider,
UNCOV
614
                patterns,
×
UNCOV
615
                || calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
×
616
                locale,
UNCOV
617
            )?,
×
618
            PhantomData,
619
        ))
UNCOV
620
    }
×
621

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

700
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_experimental)]
701
    #[cfg(feature = "experimental")]
702
    #[inline]
703
    pub fn try_new_experimental_unstable<D>(
704
        provider: &D,
705
        locale: &DataLocale,
706
        options: DateTimeFormatterOptions,
707
    ) -> Result<Self, DateTimeError>
708
    where
709
        D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
710
            + DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
711
            + DataProvider<TimeSymbolsV1Marker>
712
            + DataProvider<TimeLengthsV1Marker>
713
            + DataProvider<crate::provider::calendar::DateSkeletonPatternsV1Marker>
714
            + DataProvider<DecimalSymbolsV1Marker>
715
            + DataProvider<OrdinalV1Marker>
716
            + DataProvider<WeekDataV1Marker>
717
            + ?Sized,
718
    {
719
        let patterns = PatternSelector::for_options_experimental(
720
            provider,
721
            calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
722
            locale,
723
            &C::DEFAULT_BCP_47_IDENTIFIER,
724
            &options,
725
        )
726
        .map_err(|e| match e {
727
            UnsupportedOptionsOrDataOrPatternError::UnsupportedOptions => {
728
                DateTimeError::UnsupportedOptions
729
            }
730
            UnsupportedOptionsOrDataOrPatternError::Data(e) => DateTimeError::Data(e),
731
            UnsupportedOptionsOrDataOrPatternError::Pattern(e) => DateTimeError::Pattern(e),
732
        })?;
733

734
        Ok(Self(
735
            raw::DateTimeFormatter::try_new_unstable(
736
                provider,
737
                patterns,
738
                || calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
739
                locale,
740
            )?,
741
            PhantomData,
742
        ))
743
    }
744

745
    /// Takes a [`DateTimeInput`] implementer and returns an instance of a [`FormattedDateTime`]
746
    /// that contains all information necessary to display a formatted date and operate on it.
747
    ///
748
    /// # Examples
749
    ///
750
    /// ```
751
    /// use icu::calendar::{DateTime, Gregorian};
752
    /// use icu::datetime::TypedDateTimeFormatter;
753
    /// use writeable::assert_writeable_eq;
754
    /// use icu::locid::locale;
755
    /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium);
756
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(&locale!("en").into(), options.into())
757
    ///     .expect("Failed to create TypedDateTimeFormatter instance.");
758
    ///
759
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
760
    ///     .expect("Failed to construct DateTime.");
761
    ///
762
    /// assert_writeable_eq!(dtf.format(&datetime), "12:34:28 PM");
763
    /// ```
764
    #[inline]
765
    pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
1✔
766
    where
767
        T: DateTimeInput<Calendar = C>,
768
    {
769
        self.0.format(value)
1✔
770
    }
1✔
771

772
    /// Takes a [`DateTimeInput`] implementer and returns it formatted as a string.
773
    ///
774
    /// # Examples
775
    ///
776
    /// ```
777
    /// use icu::calendar::{DateTime, Gregorian};
778
    /// use icu::datetime::TypedDateTimeFormatter;
779
    /// use icu::locid::locale;
780
    /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium);
781
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(&locale!("en").into(), options.into())
782
    ///     .expect("Failed to create TypedDateTimeFormatter instance.");
783
    ///
784
    /// let datetime = DateTime::try_new_gregorian_datetime(2020, 9, 1, 12, 34, 28)
785
    ///     .expect("Failed to construct DateTime.");
786
    ///
787
    /// assert_eq!(dtf.format_to_string(&datetime), "12:34:28 PM");
788
    /// ```
789
    #[inline]
790
    pub fn format_to_string(&self, value: &impl DateTimeInput<Calendar = C>) -> String {
1✔
791
        self.format(value).write_to_string().into_owned()
1✔
792
    }
1✔
793

794
    /// Returns a [`components::Bag`](crate::options::components::Bag) that represents the resolved components for the
795
    /// options that were provided to the [`TypedDateTimeFormatter`]. The developer may request
796
    /// a certain set of options for a [`TypedDateTimeFormatter`] but the locale and resolution
797
    /// algorithm may change certain details of what actually gets resolved.
798
    ///
799
    /// # Examples
800
    ///
801
    /// ```
802
    /// use icu::calendar::Gregorian;
803
    /// use icu::datetime::{
804
    ///     options::{components, length}, TypedDateTimeFormatter,
805
    /// };
806
    /// use icu::locid::locale;
807
    ///
808
    /// let options = length::Bag::from_date_style(length::Date::Medium).into();
809
    /// let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
810
    ///     &locale!("en").into(),
811
    ///     options,
812
    /// )
813
    /// .expect("Failed to create TypedDateTimeFormatter instance.");
814
    ///
815
    /// let mut expected_components_bag = components::Bag::default();
816
    /// expected_components_bag.year = Some(components::Year::Numeric);
817
    /// expected_components_bag.month = Some(components::Month::Short);
818
    /// expected_components_bag.day = Some(components::Day::NumericDayOfMonth);
819
    ///
820
    /// assert_eq!(dtf.resolve_components(), expected_components_bag);
821
    /// ```
822
    #[cfg(feature = "experimental")]
823
    pub fn resolve_components(&self) -> crate::options::components::Bag {
824
        self.0.resolve_components()
825
    }
826
}
827

828
#[cfg(test)]
829
#[cfg(feature = "serde")]
830
#[cfg(feature = "compiled_data")]
831
mod tests {
832
    use super::*;
833
    use icu_calendar::DateTime;
834
    use icu_calendar::Gregorian;
835

836
    #[test]
837
    fn works_with_default_options() {
2✔
838
        assert_eq!(
1✔
839
            TypedDateTimeFormatter::<Gregorian>::try_new(Default::default(), Default::default(),)
2✔
840
                .unwrap()
841
                .format_to_string(
842
                    &DateTime::try_new_gregorian_datetime(2022, 9, 20, 0, 0, 0).unwrap()
1✔
843
                ),
844
            "2022 M09 20 00:00:00"
845
        );
846
    }
2✔
847
}
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