Coverage Report

Created: 2025-08-13 21:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/a220/proj/radnelac/src/display/prelude.rs
Line
Count
Source
1
// This Source Code Form is subject to the terms of the Mozilla Public
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5
use crate::display::private::Case;
6
use crate::display::private::Content;
7
use crate::display::private::DisplayItem;
8
use crate::display::private::DisplayOptions;
9
use crate::display::private::Item;
10
use crate::display::private::NumericContent;
11
use crate::display::private::Sign;
12
use crate::display::private::TextContent;
13
pub use crate::display::text::prelude::Language;
14
15
const O_LITERAL: DisplayOptions = DisplayOptions {
16
    numerals: None,
17
    width: None,
18
    align: None,
19
    padding: None,
20
    case: None,
21
    sign: Sign::OnlyNegative,
22
};
23
24
const O_YEAR_IN_ERA: DisplayOptions = DisplayOptions {
25
    numerals: None,
26
    width: None,
27
    align: None,
28
    padding: None,
29
    case: None,
30
    sign: Sign::Never,
31
};
32
33
const O_N1: DisplayOptions = DisplayOptions {
34
    numerals: None,
35
    width: Some(1),
36
    align: None,
37
    padding: None,
38
    case: Some(Case::Upper),
39
    sign: Sign::Never,
40
};
41
42
const O_N2: DisplayOptions = DisplayOptions {
43
    numerals: None,
44
    width: Some(2),
45
    align: None,
46
    padding: Some('0'),
47
    case: Some(Case::Upper),
48
    sign: Sign::Never,
49
};
50
51
const O_N3: DisplayOptions = DisplayOptions {
52
    numerals: None,
53
    width: Some(3),
54
    align: None,
55
    padding: None,
56
    case: Some(Case::Upper),
57
    sign: Sign::Never,
58
};
59
60
macro_rules! NumericDateItems {
61
    ($name: ident, $sep: literal, $prefix: ident, $n_prefix: literal, $stem: ident, $n_stem: literal) => {
62
        const $name: [Item<'_>; 3] = [
63
            Item::new(
64
                Content::Numeric(NumericContent::$prefix),
65
                DisplayOptions {
66
                    numerals: None,
67
                    width: Some($n_prefix),
68
                    align: None,
69
                    padding: Some('0'),
70
                    case: None,
71
                    sign: Sign::OnlyNegative,
72
                },
73
            ),
74
            Item::new(Content::Literal($sep), O_LITERAL),
75
            Item::new(
76
                Content::Numeric(NumericContent::$stem),
77
                DisplayOptions {
78
                    numerals: None,
79
                    width: Some($n_stem),
80
                    align: None,
81
                    padding: Some('0'),
82
                    case: None,
83
                    sign: Sign::OnlyNegative,
84
                },
85
            ),
86
        ];
87
    };
88
    ($name: ident, $sep: literal, $prefix: ident, $n_prefix: literal, $stem: ident, $n_stem: literal, $suffix: ident, $n_suffix: literal) => {
89
        const $name: [Item<'_>; 5] = [
90
            Item::new(
91
                Content::Numeric(NumericContent::$prefix),
92
                DisplayOptions {
93
                    numerals: None,
94
                    width: Some($n_prefix),
95
                    align: None,
96
                    padding: Some('0'),
97
                    case: None,
98
                    sign: Sign::OnlyNegative,
99
                },
100
            ),
101
            Item::new(Content::Literal($sep), O_LITERAL),
102
            Item::new(
103
                Content::Numeric(NumericContent::$stem),
104
                DisplayOptions {
105
                    numerals: None,
106
                    width: Some($n_stem),
107
                    align: None,
108
                    padding: Some('0'),
109
                    case: None,
110
                    sign: Sign::OnlyNegative,
111
                },
112
            ),
113
            Item::new(Content::Literal($sep), O_LITERAL),
114
            Item::new(
115
                Content::Numeric(NumericContent::$suffix),
116
                DisplayOptions {
117
                    numerals: None,
118
                    width: Some($n_suffix),
119
                    align: None,
120
                    padding: Some('0'),
121
                    case: None,
122
                    sign: Sign::OnlyNegative,
123
                },
124
            ),
125
        ];
126
    };
127
}
128
129
const I_HHMM_COLON_AMPM: [Item<'_>; 5] = [
130
    Item::new(
131
        Content::Numeric(NumericContent::Hour1to12),
132
        DisplayOptions {
133
            numerals: None,
134
            width: Some(2),
135
            align: None,
136
            padding: Some('0'),
137
            case: None,
138
            sign: Sign::OnlyNegative,
139
        },
140
    ),
141
    Item::new(Content::Literal(":"), O_LITERAL),
142
    Item::new(
143
        Content::Numeric(NumericContent::Minute),
144
        DisplayOptions {
145
            numerals: None,
146
            width: Some(2),
147
            align: None,
148
            padding: Some('0'),
149
            case: None,
150
            sign: Sign::OnlyNegative,
151
        },
152
    ),
153
    Item::new(Content::Literal(" "), O_LITERAL),
154
    Item::new(Content::Text(TextContent::HalfDayAbbrev), O_LITERAL),
155
];
156
157
NumericDateItems!(I_HHMMSS_COLON, ":", Hour0to23, 2, Minute, 2, Second, 2);
158
NumericDateItems!(I_YYYYMMDD_DASH, "-", Year, 4, Month, 2, DayOfMonth, 2);
159
NumericDateItems!(I_YYYYYMMDD_DASH, "-", Year, 5, Month, 2, DayOfMonth, 2);
160
NumericDateItems!(I_YYYYMMDD_SLASH, "/", Year, 4, Month, 2, DayOfMonth, 2);
161
NumericDateItems!(I_DDMMYYYY_SLASH, "/", DayOfMonth, 2, Month, 2, Year, 4);
162
NumericDateItems!(I_DDMMYYYY_DOT, ".", DayOfMonth, 2, Month, 2, Year, 4);
163
NumericDateItems!(I_MMDDYYYY_SLASH, "/", Month, 2, DayOfMonth, 2, Year, 4);
164
NumericDateItems!(I_YYYYOOO_DASH, "-", Year, 4, DayOfYear, 3);
165
NumericDateItems!(I_YYYYYOOO_DASH, "-", Year, 5, DayOfYear, 3);
166
167
const I_LONG_DATE: [Item<'_>; 9] = [
168
    Item::new(Content::Text(TextContent::DayOfWeekName), O_LITERAL),
169
    Item::new(Content::Literal(" "), O_LITERAL),
170
    Item::new(Content::Text(TextContent::MonthName), O_LITERAL),
171
    Item::new(Content::Literal(" "), O_LITERAL),
172
    Item::new(Content::Numeric(NumericContent::DayOfMonth), O_LITERAL),
173
    Item::new(Content::Literal(", "), O_LITERAL),
174
    Item::new(Content::Numeric(NumericContent::Year), O_YEAR_IN_ERA),
175
    Item::new(Content::Literal(" "), O_LITERAL),
176
    Item::new(Content::Text(TextContent::EraName), O_LITERAL),
177
];
178
179
const I_LONG_DAY_OF_MONTH: [Item<'_>; 9] = [
180
    Item::new(Content::Text(TextContent::DayOfWeekName), O_LITERAL),
181
    Item::new(Content::Literal(" "), O_LITERAL),
182
    Item::new(Content::Text(TextContent::MonthName), O_LITERAL),
183
    Item::new(Content::Literal(" "), O_LITERAL),
184
    Item::new(Content::Text(TextContent::DayOfMonthName), O_LITERAL),
185
    Item::new(Content::Literal(", "), O_LITERAL),
186
    Item::new(Content::Numeric(NumericContent::Year), O_YEAR_IN_ERA),
187
    Item::new(Content::Literal(" "), O_LITERAL),
188
    Item::new(Content::Text(TextContent::EraName), O_LITERAL),
189
];
190
191
const I_LONG_COMPL: [Item<'_>; 5] = [
192
    Item::new(Content::Text(TextContent::ComplementaryDayName), O_LITERAL),
193
    Item::new(Content::Literal(", "), O_LITERAL),
194
    Item::new(Content::Numeric(NumericContent::Year), O_YEAR_IN_ERA),
195
    Item::new(Content::Literal(" "), O_LITERAL),
196
    Item::new(Content::Text(TextContent::EraName), O_LITERAL),
197
];
198
199
const I_LONG_DATE_ERA_ABBR: [Item<'_>; 9] = [
200
    Item::new(Content::Text(TextContent::DayOfWeekName), O_LITERAL),
201
    Item::new(Content::Literal(" "), O_LITERAL),
202
    Item::new(Content::Text(TextContent::MonthName), O_LITERAL),
203
    Item::new(Content::Literal(" "), O_LITERAL),
204
    Item::new(Content::Numeric(NumericContent::DayOfMonth), O_LITERAL),
205
    Item::new(Content::Literal(", "), O_LITERAL),
206
    Item::new(Content::Numeric(NumericContent::Year), O_YEAR_IN_ERA),
207
    Item::new(Content::Literal(" "), O_LITERAL),
208
    Item::new(Content::Text(TextContent::EraAbbreviation), O_LITERAL),
209
];
210
211
const I_LONG_DAY_OF_MONTH_ERA_ABBR: [Item<'_>; 9] = [
212
    Item::new(Content::Text(TextContent::DayOfWeekName), O_LITERAL),
213
    Item::new(Content::Literal(" "), O_LITERAL),
214
    Item::new(Content::Text(TextContent::MonthName), O_LITERAL),
215
    Item::new(Content::Literal(" "), O_LITERAL),
216
    Item::new(Content::Text(TextContent::DayOfMonthName), O_LITERAL),
217
    Item::new(Content::Literal(", "), O_LITERAL),
218
    Item::new(Content::Numeric(NumericContent::Year), O_YEAR_IN_ERA),
219
    Item::new(Content::Literal(" "), O_LITERAL),
220
    Item::new(Content::Text(TextContent::EraAbbreviation), O_LITERAL),
221
];
222
223
const I_LONG_COMPL_ERA_ABBR: [Item<'_>; 5] = [
224
    Item::new(Content::Text(TextContent::ComplementaryDayName), O_LITERAL),
225
    Item::new(Content::Literal(", "), O_LITERAL),
226
    Item::new(Content::Numeric(NumericContent::Year), O_YEAR_IN_ERA),
227
    Item::new(Content::Literal(" "), O_LITERAL),
228
    Item::new(Content::Text(TextContent::EraAbbreviation), O_LITERAL),
229
];
230
231
const I_YEAR_WEEK_DAY: [Item<'_>; 5] = [
232
    Item::new(Content::Numeric(NumericContent::Year), O_LITERAL),
233
    Item::new(Content::Literal("-W"), O_LITERAL),
234
    Item::new(Content::Numeric(NumericContent::WeekOfYear), O_N2),
235
    Item::new(Content::Literal("-"), O_LITERAL),
236
    Item::new(Content::Numeric(NumericContent::DayOfWeek), O_N1),
237
];
238
239
const I_YEAR_MDD: [Item<'_>; 4] = [
240
    Item::new(Content::Numeric(NumericContent::Year), O_LITERAL),
241
    Item::new(Content::Literal("-"), O_LITERAL),
242
    Item::new(Content::Text(TextContent::MonthName), O_N1),
243
    Item::new(Content::Numeric(NumericContent::DayOfMonth), O_N2),
244
];
245
246
const I_YEAR_COMPL: [Item<'_>; 3] = [
247
    Item::new(Content::Numeric(NumericContent::Year), O_LITERAL),
248
    Item::new(Content::Literal("-"), O_LITERAL),
249
    Item::new(Content::Text(TextContent::ComplementaryDayName), O_N3),
250
];
251
252
const I_COMPL_ONLY: [Item<'_>; 1] = [Item::new(
253
    Content::Text(TextContent::ComplementaryDayName),
254
    O_LITERAL,
255
)];
256
257
const I_WEEKDAY_NAME_ONLY: [Item<'_>; 1] = [Item::new(
258
    Content::Text(TextContent::DayOfWeekName),
259
    O_LITERAL,
260
)];
261
262
const I_EPOCH_SECONDS_ONLY: [Item<'_>; 1] = [Item::new(
263
    Content::Numeric(NumericContent::SecondsSinceEpoch),
264
    O_LITERAL,
265
)];
266
267
const I_EPOCH_DAYS_ONLY: [Item<'_>; 1] = [Item::new(
268
    Content::Numeric(NumericContent::DaysSinceEpoch),
269
    O_LITERAL,
270
)];
271
272
/// Represents a date format
273
/// ## Crate Features
274
///
275
/// This is only available if `display` is enabled.
276
#[derive(Debug, PartialEq, Clone, Copy)]
277
pub struct PresetFormat<'a>(&'a [Item<'a>]);
278
279
/// HH:MM AM/PM time format
280
/// ## Crate Features
281
///
282
/// This is only available if `display` is enabled.
283
pub const HHMM_COLON_AMPM: PresetFormat<'static> = PresetFormat::<'static>(&I_HHMM_COLON_AMPM);
284
/// HH:MM:SS time format
285
/// ## Crate Features
286
///
287
/// This is only available if `display` is enabled.
288
pub const HHMMSS_COLON: PresetFormat<'static> = PresetFormat::<'static>(&I_HHMMSS_COLON);
289
/// YYYY-MM-DD numeric date format
290
/// ## Crate Features
291
///
292
/// This is only available if `display` is enabled.
293
pub const YYYYMMDD_DASH: PresetFormat<'static> = PresetFormat::<'static>(&I_YYYYMMDD_DASH);
294
/// YYYYY-MM-DD numeric date format
295
///
296
/// This is intended for the Holocene Calendar.
297
///
298
/// ## Crate Features
299
///
300
/// This is only available if `display` is enabled.
301
pub const YYYYYMMDD_DASH: PresetFormat<'static> = PresetFormat::<'static>(&I_YYYYYMMDD_DASH);
302
/// YYYY/MM/DD numeric date format
303
/// ## Crate Features
304
///
305
/// This is only available if `display` is enabled.
306
pub const YYYYMMDD_SLASH: PresetFormat<'static> = PresetFormat::<'static>(&I_YYYYMMDD_SLASH);
307
/// DD/MM/YYYY numeric date format
308
/// ## Crate Features
309
///
310
/// This is only available if `display` is enabled.
311
pub const DDMMYYYY_SLASH: PresetFormat<'static> = PresetFormat::<'static>(&I_DDMMYYYY_SLASH);
312
/// DD.MM.YYYY numeric date format
313
/// ## Crate Features
314
///
315
/// This is only available if `display` is enabled.
316
pub const DDMMYYYY_DOT: PresetFormat<'static> = PresetFormat::<'static>(&I_DDMMYYYY_DOT);
317
/// MM/DD/YYYY numeric date format
318
/// ## Crate Features
319
///
320
/// This is only available if `display` is enabled.
321
pub const MMDDYYYY_SLASH: PresetFormat<'static> = PresetFormat::<'static>(&I_MMDDYYYY_SLASH);
322
/// YYYY-OOO numeric date format, where OOO is day of year
323
///
324
/// ## Crate Features
325
///
326
/// This is only available if `display` is enabled.
327
pub const YYYYOOO_DASH: PresetFormat<'static> = PresetFormat::<'static>(&I_YYYYOOO_DASH);
328
/// YYYY-OOO numeric date format, where OOO is day of year
329
///
330
/// ## Crate Features
331
///
332
/// This is only available if `display` is enabled.
333
pub const YYYYYOOO_DASH: PresetFormat<'static> = PresetFormat::<'static>(&I_YYYYYOOO_DASH);
334
/// Calendar-specific long date format
335
/// ## Crate Features
336
///
337
/// This is only available if `display` is enabled.
338
pub const LONG_DATE: PresetFormat<'static> = PresetFormat::<'static>(&I_LONG_DATE);
339
/// Calendar-specific long date format with day of month name
340
/// ## Crate Features
341
///
342
/// This is only available if `display` is enabled.
343
pub const LONG_DAY_OF_MONTH: PresetFormat<'static> = PresetFormat::<'static>(&I_LONG_DAY_OF_MONTH);
344
/// Calendar-specific long complementary day format
345
///
346
/// This is intended for calendars with complementary days.
347
/// ## Crate Features
348
///
349
/// This is only available if `display` is enabled.
350
pub const LONG_COMPL: PresetFormat<'static> = PresetFormat::<'static>(&I_LONG_COMPL);
351
/// Calendar-specific long date format, with abbreviated era
352
/// ## Crate Features
353
///
354
/// This is only available if `display` is enabled.
355
pub const LONG_DATE_ERA_ABBR: PresetFormat<'static> =
356
    PresetFormat::<'static>(&I_LONG_DATE_ERA_ABBR);
357
/// Calendar-specific long date format with day of month name and abbreviated era
358
/// ## Crate Features
359
///
360
/// This is only available if `display` is enabled.
361
pub const LONG_DAY_OF_MONTH_ERA_ABBR: PresetFormat<'static> =
362
    PresetFormat::<'static>(&I_LONG_DAY_OF_MONTH_ERA_ABBR);
363
/// Calendar-specific long complementary day format, with abbreviated era
364
///
365
/// This is intended for calendars with complementary days.
366
/// ## Crate Features
367
///
368
/// This is only available if `display` is enabled.
369
pub const LONG_COMPL_ERA_ABBR: PresetFormat<'static> =
370
    PresetFormat::<'static>(&I_LONG_COMPL_ERA_ABBR);
371
/// YYYY-Www-DD alphanumeric date format
372
///
373
/// This is inteded for the ISO calendar.
374
/// ## Crate Features
375
///
376
/// This is only available if `display` is enabled.
377
pub const YEAR_WEEK_DAY: PresetFormat<'static> = PresetFormat::<'static>(&I_YEAR_WEEK_DAY);
378
/// Y-mDD alphanumeric date format, where Y has variable length, m is a single character
379
///
380
/// This is intended for the Tranquility calendar
381
/// ## Crate Features
382
///
383
/// This is only available if `display` is enabled.
384
pub const YEAR_MDD: PresetFormat<'static> = PresetFormat::<'static>(&I_YEAR_MDD);
385
/// Y-CCC alphanumeric date format, where Y has variable length, CCC is the complementary day.
386
///
387
/// This is intended for calendars with complementary days.
388
/// ## Crate Features
389
///
390
/// This is only available if `display` is enabled.
391
pub const YEAR_COMPL: PresetFormat<'static> = PresetFormat::<'static>(&I_YEAR_COMPL);
392
/// Format which is the full name of the complementary day
393
///
394
/// This is intended for calendars with complementary days.
395
/// ## Crate Features
396
///
397
/// This is only available if `display` is enabled.
398
pub const COMPL_ONLY: PresetFormat<'static> = PresetFormat::<'static>(&I_COMPL_ONLY);
399
/// Format which is the full name of the weekday
400
///
401
/// ## Crate Features
402
///
403
/// This is only available if `display` is enabled.
404
pub const WEEKDAY_NAME_ONLY: PresetFormat<'static> = PresetFormat::<'static>(&I_WEEKDAY_NAME_ONLY);
405
/// Format which is the seconds since an epoch only
406
///
407
/// The epoch is specific to the timekeeping system.
408
///
409
/// ## Crate Features
410
///
411
/// This is only available if `display` is enabled.
412
pub const EPOCH_SECONDS_ONLY: PresetFormat<'static> =
413
    PresetFormat::<'static>(&I_EPOCH_SECONDS_ONLY);
414
/// Format which is the days since an epoch only
415
///
416
/// The epoch is specific to the timekeeping system.
417
///
418
/// ## Crate Features
419
///
420
/// This is only available if `display` is enabled.
421
pub const EPOCH_DAYS_ONLY: PresetFormat<'static> = PresetFormat::<'static>(&I_EPOCH_DAYS_ONLY);
422
423
/// Format a date in a preset format
424
/// ## Crate Features
425
///
426
/// This is only available if `display` is enabled.
427
pub trait PresetDisplay: DisplayItem {
428
    /// Checks if language is supported
429
2
    fn supported_display_lang(lang: Language) -> bool {
430
2
        Self::supported_lang(lang)
431
2
    }
432
433
    /// Format a date in any `PresetFormat`
434
171k
    fn preset_str(&self, lang: Language, preset: PresetFormat) -> String {
435
171k
        let mut result = String::new();
436
1.14M
        for 
item970k
in preset.0 {
437
970k
            result.push_str(&self.fmt_item(lang, *item))
438
        }
439
171k
        result
440
171k
    }
441
442
    /// Format a date in a calendar-specific long format
443
23.0k
    fn long_date(&self) -> String {
444
23.0k
        self.preset_str(Language::EN, LONG_DATE)
445
23.0k
    }
446
447
    /// Format a date in a calendar-specific short format
448
6
    fn short_date(&self) -> String {
449
6
        self.preset_str(Language::EN, YYYYMMDD_DASH)
450
6
    }
451
}