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

zbraniecki / icu4x / 13958601093

19 Mar 2025 04:17PM UTC coverage: 74.164% (-1.5%) from 75.71%
13958601093

push

github

web-flow
Clean up properties docs (#6315)

58056 of 78281 relevant lines covered (74.16%)

819371.32 hits per line

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

89.95
/components/datetime/src/pattern/formatter.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
use super::names::RawDateTimeNamesBorrowed;
6
use super::pattern::DateTimePatternBorrowed;
7
use crate::format::datetime::try_write_pattern_items;
8
use crate::format::DateTimeInputUnchecked;
9
use crate::scaffold::*;
10
use crate::scaffold::{
11
    AllInputMarkers, DateInputMarkers, DateTimeMarkers, InFixedCalendar, TimeMarkers,
12
    TypedDateDataMarkers, ZoneMarkers,
13
};
14
use crate::DateTimeWriteError;
15
use core::fmt;
16
use core::marker::PhantomData;
17
use writeable::TryWriteable;
18

19
/// A formatter for a specific [`DateTimePattern`].
20
///
21
/// ❗ This type forgoes most internationalization functionality of the datetime crate.
22
/// It assumes that the pattern is already localized for the customer's locale. Most clients
23
/// should use [`DateTimeFormatter`] instead of directly formatting with patterns.
24
///
25
/// Create one of these via factory methods on [`FixedCalendarDateTimeNames`].
26
///
27
/// [`DateTimePattern`]: super::DateTimePattern
28
/// [`FixedCalendarDateTimeNames`]: super::FixedCalendarDateTimeNames
29
/// [`DateTimeFormatter`]: crate::DateTimeFormatter
30
#[derive(Debug, Copy, Clone)]
31
pub struct DateTimePatternFormatter<'a, C: CldrCalendar, FSet> {
32
    inner: RawDateTimePatternFormatter<'a>,
33
    _calendar: PhantomData<C>,
34
    _marker: PhantomData<FSet>,
35
}
36

37
#[derive(Debug, Copy, Clone)]
×
38
pub(crate) struct RawDateTimePatternFormatter<'a> {
39
    pattern: DateTimePatternBorrowed<'a>,
×
40
    names: RawDateTimeNamesBorrowed<'a>,
×
41
}
42

43
impl<'a, C: CldrCalendar, FSet> DateTimePatternFormatter<'a, C, FSet> {
44
    pub(crate) fn new(
36✔
45
        pattern: DateTimePatternBorrowed<'a>,
46
        names: RawDateTimeNamesBorrowed<'a>,
47
    ) -> Self {
48
        Self {
36✔
49
            inner: RawDateTimePatternFormatter { pattern, names },
36✔
50
            _calendar: PhantomData,
51
            _marker: PhantomData,
52
        }
53
    }
36✔
54
}
55

56
impl<'a, C: CldrCalendar, FSet: DateTimeMarkers> DateTimePatternFormatter<'a, C, FSet>
57
where
58
    FSet::D: TypedDateDataMarkers<C> + DateInputMarkers,
59
    FSet::T: TimeMarkers,
60
    FSet::Z: ZoneMarkers,
61
{
62
    /// Formats a date and time of day with a custom date/time pattern.
63
    ///
64
    /// # Examples
65
    ///
66
    /// Format a date:
67
    ///
68
    /// ```
69
    /// use icu::calendar::Gregorian;
70
    /// use icu::datetime::fieldsets::enums::DateFieldSet;
71
    /// use icu::datetime::input::Date;
72
    /// use icu::datetime::pattern::DateTimePattern;
73
    /// use icu::datetime::pattern::FixedCalendarDateTimeNames;
74
    /// use icu::datetime::pattern::MonthNameLength;
75
    /// use icu::datetime::pattern::YearNameLength;
76
    /// use icu::locale::locale;
77
    /// use writeable::assert_try_writeable_eq;
78
    ///
79
    /// // Create an instance that can format wide month and era names:
80
    /// let mut names: FixedCalendarDateTimeNames<Gregorian, DateFieldSet> =
81
    ///     FixedCalendarDateTimeNames::try_new(locale!("en-GB").into()).unwrap();
82
    /// names
83
    ///     .include_month_names(MonthNameLength::Wide)
84
    ///     .unwrap()
85
    ///     .include_year_names(YearNameLength::Wide)
86
    ///     .unwrap();
87
    ///
88
    /// // Create a pattern from a pattern string:
89
    /// let pattern_str = "'The date is:' MMMM d, y GGGG";
90
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
91
    ///
92
    /// // Test it with some different dates:
93
    /// // Note: extended year -50 is year 51 BCE
94
    /// let date_bce = Date::try_new_gregorian(-50, 3, 15).unwrap();
95
    /// let date_ce = Date::try_new_gregorian(1700, 11, 20).unwrap();
96
    /// assert_try_writeable_eq!(
97
    ///     names.with_pattern_unchecked(&pattern).format(&date_bce),
98
    ///     "The date is: March 15, 51 Before Christ"
99
    /// );
100
    /// assert_try_writeable_eq!(
101
    ///     names.with_pattern_unchecked(&pattern).format(&date_ce),
102
    ///     "The date is: November 20, 1700 Anno Domini"
103
    /// );
104
    /// ```
105
    ///
106
    /// Format a time:
107
    ///
108
    /// ```
109
    /// use icu::calendar::Gregorian;
110
    /// use icu::datetime::fieldsets::enums::TimeFieldSet;
111
    /// use icu::datetime::input::Time;
112
    /// use icu::datetime::pattern::DateTimePattern;
113
    /// use icu::datetime::pattern::DayPeriodNameLength;
114
    /// use icu::datetime::pattern::FixedCalendarDateTimeNames;
115
    /// use icu::locale::locale;
116
    /// use writeable::assert_try_writeable_eq;
117
    ///
118
    /// // Create an instance that can format abbreviated day periods:
119
    /// let mut names: FixedCalendarDateTimeNames<Gregorian, TimeFieldSet> =
120
    ///     FixedCalendarDateTimeNames::try_new(locale!("en-US").into()).unwrap();
121
    /// names
122
    ///     .include_day_period_names(DayPeriodNameLength::Abbreviated)
123
    ///     .unwrap();
124
    ///
125
    /// // Create a pattern from a pattern string:
126
    /// let pattern_str = "'The time is:' h:mm b";
127
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
128
    ///
129
    /// // Test it with different times of day:
130
    /// let time_am = Time::try_new(11, 4, 14, 0).unwrap();
131
    /// let time_pm = Time::try_new(13, 41, 28, 0).unwrap();
132
    /// let time_noon = Time::try_new(12, 0, 0, 0).unwrap();
133
    /// let time_midnight = Time::try_new(0, 0, 0, 0).unwrap();
134
    /// assert_try_writeable_eq!(
135
    ///     names.with_pattern_unchecked(&pattern).format(&time_am),
136
    ///     "The time is: 11:04 AM"
137
    /// );
138
    /// assert_try_writeable_eq!(
139
    ///     names.with_pattern_unchecked(&pattern).format(&time_pm),
140
    ///     "The time is: 1:41 PM"
141
    /// );
142
    /// assert_try_writeable_eq!(
143
    ///     names.with_pattern_unchecked(&pattern).format(&time_noon),
144
    ///     "The time is: 12:00 noon"
145
    /// );
146
    /// assert_try_writeable_eq!(
147
    ///     names
148
    ///         .with_pattern_unchecked(&pattern)
149
    ///         .format(&time_midnight),
150
    ///     "The time is: 12:00 midnight"
151
    /// );
152
    /// ```
153
    ///
154
    /// Format a time zone:
155
    ///
156
    /// ```
157
    /// use icu::calendar::Gregorian;
158
    /// use icu::datetime::fieldsets::enums::ZoneFieldSet;
159
    /// use icu::datetime::input::ZonedDateTime;
160
    /// use icu::datetime::pattern::DateTimePattern;
161
    /// use icu::datetime::pattern::FixedCalendarDateTimeNames;
162
    /// use icu::locale::locale;
163
    /// use icu::time::zone::{IanaParser, VariantOffsetsCalculator};
164
    /// use writeable::assert_try_writeable_eq;
165
    ///
166
    /// let mut london_winter = ZonedDateTime::try_from_str(
167
    ///     "2024-01-01T00:00:00+00:00[Europe/London]",
168
    ///     Gregorian,
169
    ///     IanaParser::new(),
170
    ///     VariantOffsetsCalculator::new(),
171
    /// )
172
    /// .unwrap();
173
    /// let mut london_summer = ZonedDateTime::try_from_str(
174
    ///     "2024-07-01T00:00:00+01:00[Europe/London]",
175
    ///     Gregorian,
176
    ///     IanaParser::new(),
177
    ///     VariantOffsetsCalculator::new(),
178
    /// )
179
    /// .unwrap();
180
    ///
181
    /// let mut names =
182
    ///     FixedCalendarDateTimeNames::<Gregorian, ZoneFieldSet>::try_new(
183
    ///         locale!("en-GB").into(),
184
    ///     )
185
    ///     .unwrap();
186
    ///
187
    /// names.include_time_zone_essentials().unwrap();
188
    /// names.include_time_zone_specific_short_names().unwrap();
189
    ///
190
    /// // Create a pattern with symbol `z`:
191
    /// let pattern_str = "'Your time zone is:' z";
192
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
193
    ///
194
    /// assert_try_writeable_eq!(
195
    ///     names
196
    ///         .with_pattern_unchecked(&pattern)
197
    ///         .format(&london_winter),
198
    ///     "Your time zone is: GMT",
199
    /// );
200
    /// assert_try_writeable_eq!(
201
    ///     names
202
    ///         .with_pattern_unchecked(&pattern)
203
    ///         .format(&london_summer),
204
    ///     "Your time zone is: BST",
205
    /// );
206
    /// ```
207
    pub fn format<I>(&self, datetime: &I) -> FormattedDateTimePattern<'a>
34✔
208
    where
209
        I: ?Sized + InFixedCalendar<C> + AllInputMarkers<FSet>,
210
    {
211
        FormattedDateTimePattern {
34✔
212
            pattern: self.inner.pattern,
34✔
213
            input: DateTimeInputUnchecked::extract_from_neo_input::<FSet::D, FSet::T, FSet::Z, I>(
34✔
214
                datetime,
215
            ),
216
            names: self.inner.names,
34✔
217
        }
218
    }
34✔
219
}
220

221
/// A pattern that has been interpolated and implements [`TryWriteable`].
222
#[derive(Debug)]
×
223
pub struct FormattedDateTimePattern<'a> {
224
    pattern: DateTimePatternBorrowed<'a>,
×
225
    input: DateTimeInputUnchecked,
×
226
    names: RawDateTimeNamesBorrowed<'a>,
×
227
}
228

229
impl TryWriteable for FormattedDateTimePattern<'_> {
230
    type Error = DateTimeWriteError;
231
    fn try_write_to_parts<S: writeable::PartsWrite + ?Sized>(
357✔
232
        &self,
233
        sink: &mut S,
234
    ) -> Result<Result<(), Self::Error>, fmt::Error> {
235
        try_write_pattern_items(
357✔
236
            self.pattern.0.as_borrowed().metadata,
357✔
237
            self.pattern.0.as_borrowed().items.iter(),
357✔
238
            &self.input,
357✔
239
            &self.names,
240
            self.names.decimal_formatter,
357✔
241
            sink,
242
        )
243
    }
357✔
244

245
    // TODO(#489): Implement writeable_length_hint
246
}
247

248
#[cfg(test)]
249
#[cfg(feature = "compiled_data")]
250
mod tests {
251
    use super::super::*;
252
    use icu_calendar::{Date, Gregorian};
253
    use icu_locale_core::locale;
254
    use icu_time::{DateTime, Time};
255
    use writeable::assert_try_writeable_eq;
256

257
    #[test]
258
    fn test_basic_pattern_formatting() {
2✔
259
        let locale = locale!("en").into();
1✔
260
        let mut names: FixedCalendarDateTimeNames<Gregorian> =
261
            FixedCalendarDateTimeNames::try_new(locale).unwrap();
1✔
262
        names
1✔
263
            .load_month_names(&crate::provider::Baked, MonthNameLength::Wide)
1✔
264
            .unwrap()
265
            .load_weekday_names(&crate::provider::Baked, WeekdayNameLength::Abbreviated)
1✔
266
            .unwrap()
267
            .load_year_names(&crate::provider::Baked, YearNameLength::Narrow)
1✔
268
            .unwrap()
269
            .load_day_period_names(&crate::provider::Baked, DayPeriodNameLength::Abbreviated)
1✔
270
            .unwrap();
271
        let pattern: DateTimePattern = "'It is' E, MMMM d, y GGGGG 'at' hh:mm a'!'"
1✔
272
            .parse()
273
            .unwrap();
274
        let datetime = DateTime {
1✔
275
            date: Date::try_new_gregorian(2023, 10, 25).unwrap(),
3✔
276
            time: Time::try_new(15, 0, 55, 0).unwrap(),
1✔
277
        };
278
        let formatted_pattern = names.with_pattern_unchecked(&pattern).format(&datetime);
1✔
279

280
        assert_try_writeable_eq!(
2✔
281
            formatted_pattern,
282
            "It is Wed, October 25, 2023 A at 03:00 PM!",
283
            Ok(()),
284
        );
285
    }
2✔
286

287
    #[test]
288
    fn test_era_coverage() {
2✔
289
        let locale = locale!("uk").into();
1✔
290
        #[derive(Debug)]
×
291
        struct TestCase {
292
            pattern: &'static str,
293
            length: YearNameLength,
×
294
            expected: &'static str,
×
295
        }
296
        let cases = [
1✔
297
            TestCase {
1✔
298
                pattern: "<G>",
299
                length: YearNameLength::Abbreviated,
1✔
300
                expected: "<н. е.>",
301
            },
302
            TestCase {
1✔
303
                pattern: "<GG>",
304
                length: YearNameLength::Abbreviated,
1✔
305
                expected: "<н. е.>",
306
            },
307
            TestCase {
1✔
308
                pattern: "<GGG>",
309
                length: YearNameLength::Abbreviated,
1✔
310
                expected: "<н. е.>",
311
            },
312
            TestCase {
1✔
313
                pattern: "<GGGG>",
314
                length: YearNameLength::Wide,
1✔
315
                expected: "<нашої ери>",
316
            },
317
            TestCase {
1✔
318
                pattern: "<GGGGG>",
319
                length: YearNameLength::Narrow,
1✔
320
                expected: "<н.е.>",
321
            },
322
        ];
323
        for cas in cases {
1✔
324
            let TestCase {
325
                pattern,
5✔
326
                length,
5✔
327
                expected,
5✔
328
            } = cas;
329
            let mut names: FixedCalendarDateTimeNames<Gregorian> =
330
                FixedCalendarDateTimeNames::try_new(locale).unwrap();
5✔
331
            names
15✔
332
                .load_year_names(&crate::provider::Baked, length)
333
                .unwrap();
334
            let pattern: DateTimePattern = pattern.parse().unwrap();
5✔
335
            let datetime = DateTime {
5✔
336
                date: Date::try_new_gregorian(2023, 11, 17).unwrap(),
15✔
337
                time: Time::try_new(13, 41, 28, 0).unwrap(),
5✔
338
            };
339
            let formatted_pattern = names.with_pattern_unchecked(&pattern).format(&datetime);
5✔
340

341
            assert_try_writeable_eq!(formatted_pattern, expected, Ok(()), "{cas:?}");
10✔
342
        }
14✔
343
    }
10✔
344

345
    #[test]
346
    fn test_month_coverage() {
2✔
347
        // Ukrainian has different values for format and standalone
348
        let locale = locale!("uk").into();
1✔
349
        #[derive(Debug)]
×
350
        struct TestCase {
351
            pattern: &'static str,
352
            length: MonthNameLength,
×
353
            expected: &'static str,
×
354
        }
355
        let cases = [
1✔
356
            // 'M' and 'MM' are numeric
357
            TestCase {
1✔
358
                pattern: "<MMM>",
359
                length: MonthNameLength::Abbreviated,
1✔
360
                expected: "<лист.>",
361
            },
362
            TestCase {
1✔
363
                pattern: "<MMMM>",
364
                length: MonthNameLength::Wide,
1✔
365
                expected: "<листопада>",
366
            },
367
            TestCase {
1✔
368
                pattern: "<MMMMM>",
369
                length: MonthNameLength::Narrow,
1✔
370
                expected: "<л>",
371
            },
372
            // 'L' and 'LL' are numeric
373
            TestCase {
1✔
374
                pattern: "<LLL>",
375
                length: MonthNameLength::StandaloneAbbreviated,
1✔
376
                expected: "<лист.>",
377
            },
378
            TestCase {
1✔
379
                pattern: "<LLLL>",
380
                length: MonthNameLength::StandaloneWide,
1✔
381
                expected: "<листопад>",
382
            },
383
            TestCase {
1✔
384
                pattern: "<LLLLL>",
385
                length: MonthNameLength::StandaloneNarrow,
1✔
386
                expected: "<Л>",
387
            },
388
        ];
389
        for cas in cases {
1✔
390
            let TestCase {
391
                pattern,
6✔
392
                length,
6✔
393
                expected,
6✔
394
            } = cas;
395
            let mut names: FixedCalendarDateTimeNames<Gregorian> =
396
                FixedCalendarDateTimeNames::try_new(locale).unwrap();
6✔
397
            names
18✔
398
                .load_month_names(&crate::provider::Baked, length)
399
                .unwrap();
400
            let pattern: DateTimePattern = pattern.parse().unwrap();
6✔
401
            let datetime = DateTime {
6✔
402
                date: Date::try_new_gregorian(2023, 11, 17).unwrap(),
18✔
403
                time: Time::try_new(13, 41, 28, 0).unwrap(),
6✔
404
            };
405
            let formatted_pattern = names.with_pattern_unchecked(&pattern).format(&datetime);
6✔
406

407
            assert_try_writeable_eq!(formatted_pattern, expected, Ok(()), "{cas:?}");
12✔
408
        }
17✔
409
    }
12✔
410

411
    #[test]
412
    fn test_weekday_coverage() {
2✔
413
        let locale = locale!("uk").into();
1✔
414
        #[derive(Debug)]
×
415
        struct TestCase {
416
            pattern: &'static str,
417
            length: WeekdayNameLength,
×
418
            expected: &'static str,
×
419
        }
420
        let cases = [
1✔
421
            TestCase {
1✔
422
                pattern: "<E>",
423
                length: WeekdayNameLength::Abbreviated,
1✔
424
                expected: "<пт>",
425
            },
426
            TestCase {
1✔
427
                pattern: "<EE>",
428
                length: WeekdayNameLength::Abbreviated,
1✔
429
                expected: "<пт>",
430
            },
431
            TestCase {
1✔
432
                pattern: "<EEE>",
433
                length: WeekdayNameLength::Abbreviated,
1✔
434
                expected: "<пт>",
435
            },
436
            TestCase {
1✔
437
                pattern: "<EEEE>",
438
                length: WeekdayNameLength::Wide,
1✔
439
                expected: "<пʼятниця>",
440
            },
441
            TestCase {
1✔
442
                pattern: "<EEEEE>",
443
                length: WeekdayNameLength::Narrow,
1✔
444
                expected: "<П>",
445
            },
446
            TestCase {
1✔
447
                pattern: "<EEEEEE>",
448
                length: WeekdayNameLength::Short,
1✔
449
                expected: "<пт>",
450
            },
451
            // 'e' and 'ee' are numeric
452
            TestCase {
1✔
453
                pattern: "<eee>",
454
                length: WeekdayNameLength::Abbreviated,
1✔
455
                expected: "<пт>",
456
            },
457
            TestCase {
1✔
458
                pattern: "<eeee>",
459
                length: WeekdayNameLength::Wide,
1✔
460
                expected: "<пʼятниця>",
461
            },
462
            TestCase {
1✔
463
                pattern: "<eeeee>",
464
                length: WeekdayNameLength::Narrow,
1✔
465
                expected: "<П>",
466
            },
467
            TestCase {
1✔
468
                pattern: "<eeeeee>",
469
                length: WeekdayNameLength::Short,
1✔
470
                expected: "<пт>",
471
            },
472
            // 'c' and 'cc' are numeric
473
            TestCase {
1✔
474
                pattern: "<ccc>",
475
                length: WeekdayNameLength::StandaloneAbbreviated,
1✔
476
                expected: "<пт>",
477
            },
478
            TestCase {
1✔
479
                pattern: "<cccc>",
480
                length: WeekdayNameLength::StandaloneWide,
1✔
481
                expected: "<пʼятниця>",
482
            },
483
            TestCase {
1✔
484
                pattern: "<ccccc>",
485
                length: WeekdayNameLength::StandaloneNarrow,
1✔
486
                expected: "<П>",
487
            },
488
            TestCase {
1✔
489
                pattern: "<cccccc>",
490
                length: WeekdayNameLength::StandaloneShort,
1✔
491
                expected: "<пт>",
492
            },
493
        ];
494
        for cas in cases {
1✔
495
            let TestCase {
496
                pattern,
14✔
497
                length,
14✔
498
                expected,
14✔
499
            } = cas;
500
            let mut names: FixedCalendarDateTimeNames<Gregorian> =
501
                FixedCalendarDateTimeNames::try_new(locale).unwrap();
14✔
502
            names
42✔
503
                .load_weekday_names(&crate::provider::Baked, length)
504
                .unwrap();
505
            let pattern: DateTimePattern = pattern.parse().unwrap();
14✔
506
            let datetime = DateTime {
14✔
507
                date: Date::try_new_gregorian(2023, 11, 17).unwrap(),
42✔
508
                time: Time::try_new(13, 41, 28, 0).unwrap(),
14✔
509
            };
510
            let formatted_pattern = names.with_pattern_unchecked(&pattern).format(&datetime);
14✔
511

512
            assert_try_writeable_eq!(formatted_pattern, expected, Ok(()), "{cas:?}");
28✔
513
        }
41✔
514
    }
28✔
515

516
    #[test]
517
    fn test_dayperiod_coverage() {
2✔
518
        // Thai has different values for different lengths of day periods
519
        // TODO(#487): Support flexible day periods, too
520
        let locale = locale!("th").into();
1✔
521
        #[derive(Debug)]
×
522
        struct TestCase {
523
            pattern: &'static str,
524
            length: DayPeriodNameLength,
×
525
            expected: &'static str,
×
526
        }
527
        let cases = [
1✔
528
            TestCase {
1✔
529
                pattern: "<a>",
530
                length: DayPeriodNameLength::Abbreviated,
1✔
531
                expected: "<PM>",
532
            },
533
            TestCase {
1✔
534
                pattern: "<aa>",
535
                length: DayPeriodNameLength::Abbreviated,
1✔
536
                expected: "<PM>",
537
            },
538
            TestCase {
1✔
539
                pattern: "<aaa>",
540
                length: DayPeriodNameLength::Abbreviated,
1✔
541
                expected: "<PM>",
542
            },
543
            TestCase {
1✔
544
                pattern: "<aaaa>",
545
                length: DayPeriodNameLength::Wide,
1✔
546
                expected: "<หลังเที่ยง>",
547
            },
548
            TestCase {
1✔
549
                pattern: "<aaaaa>",
550
                length: DayPeriodNameLength::Narrow,
1✔
551
                expected: "<p>",
552
            },
553
            TestCase {
1✔
554
                pattern: "<b>",
555
                length: DayPeriodNameLength::Abbreviated,
1✔
556
                expected: "<PM>",
557
            },
558
            TestCase {
1✔
559
                pattern: "<bb>",
560
                length: DayPeriodNameLength::Abbreviated,
1✔
561
                expected: "<PM>",
562
            },
563
            TestCase {
1✔
564
                pattern: "<bbb>",
565
                length: DayPeriodNameLength::Abbreviated,
1✔
566
                expected: "<PM>",
567
            },
568
            TestCase {
1✔
569
                pattern: "<bbbb>",
570
                length: DayPeriodNameLength::Wide,
1✔
571
                expected: "<หลังเที่ยง>",
572
            },
573
            TestCase {
1✔
574
                pattern: "<bbbbb>",
575
                length: DayPeriodNameLength::Narrow,
1✔
576
                expected: "<p>",
577
            },
578
        ];
579
        for cas in cases {
1✔
580
            let TestCase {
581
                pattern,
10✔
582
                length,
10✔
583
                expected,
10✔
584
            } = cas;
585
            let mut names: FixedCalendarDateTimeNames<Gregorian> =
586
                FixedCalendarDateTimeNames::try_new(locale).unwrap();
10✔
587
            names
30✔
588
                .load_day_period_names(&crate::provider::Baked, length)
589
                .unwrap();
590
            let pattern: DateTimePattern = pattern.parse().unwrap();
10✔
591
            let datetime = DateTime {
10✔
592
                date: Date::try_new_gregorian(2023, 11, 17).unwrap(),
30✔
593
                time: Time::try_new(13, 41, 28, 0).unwrap(),
10✔
594
            };
595
            let formatted_pattern = names.with_pattern_unchecked(&pattern).format(&datetime);
10✔
596

597
            assert_try_writeable_eq!(formatted_pattern, expected, Ok(()), "{cas:?}");
20✔
598
        }
29✔
599
    }
20✔
600
}
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