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

zbraniecki / icu4x / 12020603084

23 Nov 2024 08:43PM UTC coverage: 75.71% (+0.2%) from 75.477%
12020603084

push

github

sffc
Touch Cargo.lock

55589 of 73424 relevant lines covered (75.71%)

644270.14 hits per line

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

89.76
/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::input::ExtractedInput;
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 [`TypedDateTimeNames`].
26
///
27
/// [`DateTimePattern`]: super::DateTimePattern
28
/// [`TypedDateTimeNames`]: super::TypedDateTimeNames
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::Date;
70
    /// use icu::calendar::Gregorian;
71
    /// use icu::datetime::fields;
72
    /// use icu::datetime::fields::FieldLength;
73
    /// use icu::datetime::fieldsets::enums::DateFieldSet;
74
    /// use icu::datetime::pattern::DateTimePattern;
75
    /// use icu::datetime::pattern::TypedDateTimeNames;
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: TypedDateTimeNames<Gregorian, DateFieldSet> =
81
    ///     TypedDateTimeNames::try_new(locale!("en-GB").into()).unwrap();
82
    /// names
83
    ///     .include_month_names(fields::Month::Format, FieldLength::Four)
84
    ///     .unwrap()
85
    ///     .include_year_names(FieldLength::Four)
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::calendar::Time;
111
    /// use icu::datetime::fields::FieldLength;
112
    /// use icu::datetime::fieldsets::enums::TimeFieldSet;
113
    /// use icu::datetime::pattern::DateTimePattern;
114
    /// use icu::datetime::pattern::TypedDateTimeNames;
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: TypedDateTimeNames<Gregorian, TimeFieldSet> =
120
    ///     TypedDateTimeNames::try_new(locale!("en-US").into()).unwrap();
121
    /// names.include_day_period_names(FieldLength::Three).unwrap();
122
    ///
123
    /// // Create a pattern from a pattern string:
124
    /// let pattern_str = "'The time is:' h:mm b";
125
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
126
    ///
127
    /// // Test it with different times of day:
128
    /// let time_am = Time::try_new(11, 4, 14, 0).unwrap();
129
    /// let time_pm = Time::try_new(13, 41, 28, 0).unwrap();
130
    /// let time_noon = Time::try_new(12, 0, 0, 0).unwrap();
131
    /// let time_midnight = Time::try_new(0, 0, 0, 0).unwrap();
132
    /// assert_try_writeable_eq!(
133
    ///     names.with_pattern_unchecked(&pattern).format(&time_am),
134
    ///     "The time is: 11:04 AM"
135
    /// );
136
    /// assert_try_writeable_eq!(
137
    ///     names.with_pattern_unchecked(&pattern).format(&time_pm),
138
    ///     "The time is: 1:41 PM"
139
    /// );
140
    /// assert_try_writeable_eq!(
141
    ///     names.with_pattern_unchecked(&pattern).format(&time_noon),
142
    ///     "The time is: 12:00 noon"
143
    /// );
144
    /// assert_try_writeable_eq!(
145
    ///     names
146
    ///         .with_pattern_unchecked(&pattern)
147
    ///         .format(&time_midnight),
148
    ///     "The time is: 12:00 midnight"
149
    /// );
150
    /// ```
151
    ///
152
    /// Format a time zone:
153
    ///
154
    /// ```
155
    /// use icu::calendar::Gregorian;
156
    /// use icu::datetime::fieldsets::enums::ZoneFieldSet;
157
    /// use icu::datetime::pattern::DateTimePattern;
158
    /// use icu::datetime::pattern::TypedDateTimeNames;
159
    /// use icu::locale::locale;
160
    /// use icu::timezone::IxdtfParser;
161
    /// use writeable::assert_try_writeable_eq;
162
    ///
163
    /// let mut london_winter = IxdtfParser::new()
164
    ///     .try_from_str("2024-01-01T00:00:00+00:00[Europe/London]")
165
    ///     .unwrap()
166
    ///     .to_calendar(Gregorian);
167
    /// let mut london_summer = IxdtfParser::new()
168
    ///     .try_from_str("2024-07-01T00:00:00+01:00[Europe/London]")
169
    ///     .unwrap()
170
    ///     .to_calendar(Gregorian);
171
    ///
172
    /// let mut names = TypedDateTimeNames::<Gregorian, ZoneFieldSet>::try_new(
173
    ///     locale!("en-GB").into(),
174
    /// )
175
    /// .unwrap();
176
    ///
177
    /// names.include_time_zone_essentials().unwrap();
178
    /// names.include_time_zone_specific_short_names().unwrap();
179
    ///
180
    /// // Create a pattern with symbol `z`:
181
    /// let pattern_str = "'Your time zone is:' z";
182
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
183
    ///
184
    /// assert_try_writeable_eq!(
185
    ///     names
186
    ///         .with_pattern_unchecked(&pattern)
187
    ///         .format(&london_winter),
188
    ///     "Your time zone is: GMT",
189
    /// );
190
    /// assert_try_writeable_eq!(
191
    ///     names
192
    ///         .with_pattern_unchecked(&pattern)
193
    ///         .format(&london_summer),
194
    ///     "Your time zone is: BST",
195
    /// );
196
    /// ```
197
    pub fn format<I>(&self, datetime: &I) -> FormattedDateTimePattern<'a>
36✔
198
    where
199
        I: ?Sized + InFixedCalendar<C> + AllInputMarkers<FSet>,
200
    {
201
        FormattedDateTimePattern {
36✔
202
            pattern: self.inner.pattern,
36✔
203
            input: ExtractedInput::extract_from_neo_input::<FSet::D, FSet::T, FSet::Z, I>(datetime),
36✔
204
            names: self.inner.names,
36✔
205
        }
206
    }
36✔
207
}
208

209
/// A pattern that has been interpolated and implements [`TryWriteable`].
210
#[derive(Debug)]
×
211
pub struct FormattedDateTimePattern<'a> {
212
    pattern: DateTimePatternBorrowed<'a>,
×
213
    input: ExtractedInput,
×
214
    names: RawDateTimeNamesBorrowed<'a>,
×
215
}
216

217
impl TryWriteable for FormattedDateTimePattern<'_> {
218
    type Error = DateTimeWriteError;
219
    fn try_write_to_parts<S: writeable::PartsWrite + ?Sized>(
350✔
220
        &self,
221
        sink: &mut S,
222
    ) -> Result<Result<(), Self::Error>, fmt::Error> {
223
        try_write_pattern_items(
350✔
224
            self.pattern.0.as_borrowed().metadata,
350✔
225
            self.pattern.0.as_borrowed().items.iter(),
350✔
226
            &self.input,
350✔
227
            &self.names,
228
            self.names.fixed_decimal_formatter,
350✔
229
            sink,
230
        )
231
    }
350✔
232

233
    // TODO(#489): Implement writeable_length_hint
234
}
235

236
#[cfg(test)]
237
#[cfg(feature = "compiled_data")]
238
mod tests {
239
    use super::super::*;
240
    use crate::fields::{self, FieldLength};
241
    use icu_calendar::{DateTime, Gregorian};
242
    use icu_locale_core::locale;
243
    use writeable::assert_try_writeable_eq;
244

245
    #[test]
246
    fn test_basic_pattern_formatting() {
2✔
247
        let locale = locale!("en").into();
1✔
248
        let mut names: TypedDateTimeNames<Gregorian> = TypedDateTimeNames::try_new(locale).unwrap();
1✔
249
        names
1✔
250
            .load_month_names(
251
                &crate::provider::Baked,
252
                fields::Month::Format,
1✔
253
                fields::FieldLength::Four,
1✔
254
            )
255
            .unwrap()
256
            .load_weekday_names(
257
                &crate::provider::Baked,
258
                fields::Weekday::Format,
1✔
259
                fields::FieldLength::Three,
1✔
260
            )
261
            .unwrap()
262
            .load_year_names(&crate::provider::Baked, FieldLength::Five)
1✔
263
            .unwrap()
264
            .load_day_period_names(&crate::provider::Baked, FieldLength::Three)
1✔
265
            .unwrap();
266
        let pattern: DateTimePattern = "'It is' E, MMMM d, y GGGGG 'at' hh:mm a'!'"
1✔
267
            .parse()
268
            .unwrap();
269
        let datetime = DateTime::try_new_gregorian(2023, 10, 25, 15, 0, 55).unwrap();
3✔
270
        let formatted_pattern = names.with_pattern_unchecked(&pattern).format(&datetime);
1✔
271

272
        assert_try_writeable_eq!(
2✔
273
            formatted_pattern,
274
            "It is Wed, October 25, 2023 A at 03:00 PM!",
275
            Ok(()),
276
        );
277
    }
2✔
278

279
    #[test]
280
    fn test_era_coverage() {
2✔
281
        let locale = locale!("uk").into();
1✔
282
        #[derive(Debug)]
×
283
        struct TestCase {
284
            pattern: &'static str,
285
            field_length: FieldLength,
×
286
            expected: &'static str,
×
287
        }
288
        let cases = [
1✔
289
            TestCase {
1✔
290
                pattern: "<G>",
291
                field_length: FieldLength::Three,
1✔
292
                expected: "<н. е.>",
293
            },
294
            TestCase {
1✔
295
                pattern: "<GG>",
296
                field_length: FieldLength::Three,
1✔
297
                expected: "<н. е.>",
298
            },
299
            TestCase {
1✔
300
                pattern: "<GGG>",
301
                field_length: FieldLength::Three,
1✔
302
                expected: "<н. е.>",
303
            },
304
            TestCase {
1✔
305
                pattern: "<GGGG>",
306
                field_length: FieldLength::Four,
1✔
307
                expected: "<нашої ери>",
308
            },
309
            TestCase {
1✔
310
                pattern: "<GGGGG>",
311
                field_length: FieldLength::Five,
1✔
312
                expected: "<н.е.>",
313
            },
314
        ];
315
        for cas in cases {
1✔
316
            let TestCase {
317
                pattern,
5✔
318
                field_length,
5✔
319
                expected,
5✔
320
            } = cas;
321
            let mut names: TypedDateTimeNames<Gregorian> =
322
                TypedDateTimeNames::try_new(locale).unwrap();
5✔
323
            names
15✔
324
                .load_year_names(&crate::provider::Baked, field_length)
325
                .unwrap();
326
            let pattern: DateTimePattern = pattern.parse().unwrap();
5✔
327
            let datetime = DateTime::try_new_gregorian(2023, 11, 17, 13, 41, 28).unwrap();
15✔
328
            let formatted_pattern = names.with_pattern_unchecked(&pattern).format(&datetime);
5✔
329

330
            assert_try_writeable_eq!(formatted_pattern, expected, Ok(()), "{cas:?}");
10✔
331
        }
14✔
332
    }
10✔
333

334
    #[test]
335
    fn test_month_coverage() {
2✔
336
        // Ukrainian has different values for format and standalone
337
        let locale = locale!("uk").into();
1✔
338
        #[derive(Debug)]
×
339
        struct TestCase {
340
            pattern: &'static str,
341
            field_symbol: fields::Month,
×
342
            field_length: FieldLength,
×
343
            expected: &'static str,
×
344
        }
345
        let cases = [
1✔
346
            // 'M' and 'MM' are numeric
347
            TestCase {
1✔
348
                pattern: "<MMM>",
349
                field_symbol: fields::Month::Format,
1✔
350
                field_length: FieldLength::Three,
1✔
351
                expected: "<лист.>",
352
            },
353
            TestCase {
1✔
354
                pattern: "<MMMM>",
355
                field_symbol: fields::Month::Format,
1✔
356
                field_length: FieldLength::Four,
1✔
357
                expected: "<листопада>",
358
            },
359
            TestCase {
1✔
360
                pattern: "<MMMMM>",
361
                field_symbol: fields::Month::Format,
1✔
362
                field_length: FieldLength::Five,
1✔
363
                expected: "<л>",
364
            },
365
            // 'L' and 'LL' are numeric
366
            TestCase {
1✔
367
                pattern: "<LLL>",
368
                field_symbol: fields::Month::StandAlone,
1✔
369
                field_length: FieldLength::Three,
1✔
370
                expected: "<лист.>",
371
            },
372
            TestCase {
1✔
373
                pattern: "<LLLL>",
374
                field_symbol: fields::Month::StandAlone,
1✔
375
                field_length: FieldLength::Four,
1✔
376
                expected: "<листопад>",
377
            },
378
            TestCase {
1✔
379
                pattern: "<LLLLL>",
380
                field_symbol: fields::Month::StandAlone,
1✔
381
                field_length: FieldLength::Five,
1✔
382
                expected: "<Л>",
383
            },
384
        ];
385
        for cas in cases {
1✔
386
            let TestCase {
387
                pattern,
6✔
388
                field_symbol,
6✔
389
                field_length,
6✔
390
                expected,
6✔
391
            } = cas;
392
            let mut names: TypedDateTimeNames<Gregorian> =
393
                TypedDateTimeNames::try_new(locale).unwrap();
6✔
394
            names
18✔
395
                .load_month_names(&crate::provider::Baked, field_symbol, field_length)
396
                .unwrap();
397
            let pattern: DateTimePattern = pattern.parse().unwrap();
6✔
398
            let datetime = DateTime::try_new_gregorian(2023, 11, 17, 13, 41, 28).unwrap();
18✔
399
            let formatted_pattern = names.with_pattern_unchecked(&pattern).format(&datetime);
6✔
400

401
            assert_try_writeable_eq!(formatted_pattern, expected, Ok(()), "{cas:?}");
12✔
402
        }
17✔
403
    }
12✔
404

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

519
            assert_try_writeable_eq!(formatted_pattern, expected, Ok(()), "{cas:?}");
28✔
520
        }
41✔
521
    }
28✔
522

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

601
            assert_try_writeable_eq!(formatted_pattern, expected, Ok(()), "{cas:?}");
20✔
602
        }
29✔
603
    }
20✔
604
}
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