Coverage Report

Created: 2025-10-13 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/icu_capi-1.5.1/src/datetime.rs
Line
Count
Source
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
#[diplomat::bridge]
6
pub mod ffi {
7
    use alloc::boxed::Box;
8
    use alloc::sync::Arc;
9
    use core::convert::TryInto;
10
    use core::fmt::Write;
11
12
    use icu_calendar::{AnyCalendar, DateTime, Iso, Time};
13
    use tinystr::TinyAsciiStr;
14
15
    use crate::calendar::ffi::ICU4XCalendar;
16
    use crate::date::ffi::{ICU4XDate, ICU4XIsoDate, ICU4XIsoWeekday};
17
    use crate::errors::ffi::ICU4XError;
18
    use crate::time::ffi::ICU4XTime;
19
20
    #[cfg(feature = "icu_calendar")]
21
    use crate::week::ffi::ICU4XWeekCalculator;
22
23
    #[diplomat::opaque]
24
    /// An ICU4X DateTime object capable of containing a ISO-8601 date and time.
25
    #[diplomat::rust_link(icu::calendar::DateTime, Struct)]
26
    pub struct ICU4XIsoDateTime(pub DateTime<Iso>);
27
28
    impl ICU4XIsoDateTime {
29
        /// Creates a new [`ICU4XIsoDateTime`] from the specified date and time.
30
        #[diplomat::rust_link(icu::calendar::DateTime::try_new_iso_datetime, FnInStruct)]
31
        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors), constructor)]
32
0
        pub fn create(
33
0
            year: i32,
34
0
            month: u8,
35
0
            day: u8,
36
0
            hour: u8,
37
0
            minute: u8,
38
0
            second: u8,
39
0
            nanosecond: u32,
40
0
        ) -> Result<Box<ICU4XIsoDateTime>, ICU4XError> {
41
0
            let mut dt = DateTime::try_new_iso_datetime(year, month, day, hour, minute, second)?;
42
0
            dt.time.nanosecond = nanosecond.try_into()?;
43
0
            Ok(Box::new(ICU4XIsoDateTime(dt)))
44
0
        }
45
46
        /// Creates a new [`ICU4XIsoDateTime`] from an [`ICU4XIsoDate`] and [`ICU4XTime`] object
47
        #[diplomat::rust_link(icu::calendar::DateTime::new, FnInStruct)]
48
        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_date_and_time")]
49
0
        pub fn crate_from_date_and_time(
50
0
            date: &ICU4XIsoDate,
51
0
            time: &ICU4XTime,
52
0
        ) -> Box<ICU4XIsoDateTime> {
53
0
            let dt = DateTime::new(date.0, time.0);
54
0
            Box::new(ICU4XIsoDateTime(dt))
55
0
        }
56
57
        /// Creates a new [`ICU4XIsoDateTime`] of midnight on January 1, 1970
58
        #[diplomat::rust_link(icu::calendar::DateTime::local_unix_epoch, FnInStruct)]
59
        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "local_unix_epoch")]
60
0
        pub fn local_unix_epoch() -> Box<ICU4XIsoDateTime> {
61
0
            let dt = DateTime::local_unix_epoch();
62
0
            Box::new(ICU4XIsoDateTime(dt))
63
0
        }
64
65
        /// Construct from the minutes since the local unix epoch for this date (Jan 1 1970, 00:00)
66
        #[diplomat::rust_link(
67
            icu::calendar::DateTime::from_minutes_since_local_unix_epoch,
68
            FnInStruct
69
        )]
70
        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_minutes_since_local_unix_epoch")]
71
0
        pub fn create_from_minutes_since_local_unix_epoch(minutes: i32) -> Box<ICU4XIsoDateTime> {
72
0
            Box::new(ICU4XIsoDateTime(
73
0
                DateTime::from_minutes_since_local_unix_epoch(minutes),
74
0
            ))
75
0
        }
76
77
        /// Gets the date contained in this object
78
        #[diplomat::rust_link(icu::calendar::DateTime::date, StructField)]
79
        #[diplomat::attr(supports = accessors, getter)]
80
0
        pub fn date(&self) -> Box<ICU4XIsoDate> {
81
0
            Box::new(ICU4XIsoDate(self.0.date))
82
0
        }
83
84
        /// Gets the time contained in this object
85
        #[diplomat::rust_link(icu::calendar::DateTime::time, StructField)]
86
        #[diplomat::attr(supports = accessors, getter)]
87
0
        pub fn time(&self) -> Box<ICU4XTime> {
88
0
            Box::new(ICU4XTime(self.0.time))
89
0
        }
90
91
        /// Converts this to an [`ICU4XDateTime`] capable of being mixed with dates of
92
        /// other calendars
93
        #[diplomat::rust_link(icu::calendar::DateTime::to_any, FnInStruct)]
94
        #[diplomat::rust_link(icu::calendar::DateTime::new_from_iso, FnInStruct, hidden)]
95
0
        pub fn to_any(&self) -> Box<ICU4XDateTime> {
96
0
            Box::new(ICU4XDateTime(self.0.to_any().wrap_calendar_in_arc()))
97
0
        }
98
99
        /// Gets the minutes since the local unix epoch for this date (Jan 1 1970, 00:00)
100
        #[diplomat::rust_link(icu::calendar::DateTime::minutes_since_local_unix_epoch, FnInStruct)]
101
        #[diplomat::attr(supports = accessors, getter)]
102
0
        pub fn minutes_since_local_unix_epoch(&self) -> i32 {
103
0
            self.0.minutes_since_local_unix_epoch()
104
0
        }
105
106
        /// Convert this datetime to one in a different calendar
107
        #[diplomat::rust_link(icu::calendar::DateTime::to_calendar, FnInStruct)]
108
0
        pub fn to_calendar(&self, calendar: &ICU4XCalendar) -> Box<ICU4XDateTime> {
109
0
            Box::new(ICU4XDateTime(self.0.to_calendar(calendar.0.clone())))
110
0
        }
111
112
        /// Returns the hour in this time
113
        #[diplomat::rust_link(icu::calendar::Time::hour, StructField)]
114
        #[diplomat::attr(supports = accessors, getter)]
115
0
        pub fn hour(&self) -> u8 {
116
0
            self.0.time.hour.into()
117
0
        }
118
        /// Returns the minute in this time
119
        #[diplomat::rust_link(icu::calendar::Time::minute, StructField)]
120
        #[diplomat::attr(supports = accessors, getter)]
121
0
        pub fn minute(&self) -> u8 {
122
0
            self.0.time.minute.into()
123
0
        }
124
        /// Returns the second in this time
125
        #[diplomat::rust_link(icu::calendar::Time::second, StructField)]
126
        #[diplomat::attr(supports = accessors, getter)]
127
0
        pub fn second(&self) -> u8 {
128
0
            self.0.time.second.into()
129
0
        }
130
        /// Returns the nanosecond in this time
131
        #[diplomat::rust_link(icu::calendar::Time::nanosecond, StructField)]
132
        #[diplomat::attr(supports = accessors, getter)]
133
0
        pub fn nanosecond(&self) -> u32 {
134
0
            self.0.time.nanosecond.into()
135
0
        }
136
137
        /// Returns the 1-indexed day in the year for this date
138
        #[diplomat::rust_link(icu::calendar::Date::day_of_year_info, FnInStruct)]
139
        #[diplomat::attr(supports = accessors, getter)]
140
0
        pub fn day_of_year(&self) -> u16 {
141
0
            self.0.date.day_of_year_info().day_of_year
142
0
        }
143
144
        /// Returns the 1-indexed day in the month for this date
145
        #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
146
        #[diplomat::attr(supports = accessors, getter)]
147
0
        pub fn day_of_month(&self) -> u32 {
148
0
            self.0.date.day_of_month().0
149
0
        }
150
151
        /// Returns the day in the week for this day
152
        #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
153
        #[diplomat::attr(supports = accessors, getter)]
154
0
        pub fn day_of_week(&self) -> ICU4XIsoWeekday {
155
0
            self.0.date.day_of_week().into()
156
0
        }
157
158
        /// Returns the week number in this month, 1-indexed, based on what
159
        /// is considered the first day of the week (often a locale preference).
160
        ///
161
        /// `first_weekday` can be obtained via `first_weekday()` on [`ICU4XWeekCalculator`]
162
        #[diplomat::rust_link(icu::calendar::Date::week_of_month, FnInStruct)]
163
        #[diplomat::rust_link(
164
            icu::calendar::week::WeekCalculator::week_of_month,
165
            FnInStruct,
166
            hidden
167
        )]
168
0
        pub fn week_of_month(&self, first_weekday: ICU4XIsoWeekday) -> u32 {
169
0
            self.0.date.week_of_month(first_weekday.into()).0
170
0
        }
171
172
        /// Returns the week number in this year, using week data
173
        #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
174
        #[diplomat::rust_link(
175
            icu::calendar::week::WeekCalculator::week_of_year,
176
            FnInStruct,
177
            hidden
178
        )]
179
        #[cfg(feature = "icu_calendar")]
180
0
        pub fn week_of_year(
181
0
            &self,
182
0
            calculator: &ICU4XWeekCalculator,
183
0
        ) -> Result<crate::week::ffi::ICU4XWeekOf, ICU4XError> {
184
0
            Ok(self.0.date.week_of_year(&calculator.0)?.into())
185
0
        }
186
187
        /// Returns 1-indexed number of the month of this date in its year
188
        #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
189
        #[diplomat::attr(supports = accessors, getter)]
190
0
        pub fn month(&self) -> u32 {
191
0
            self.0.date.month().ordinal
192
0
        }
193
194
        /// Returns the year number for this date
195
        #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
196
        #[diplomat::attr(supports = accessors, getter)]
197
0
        pub fn year(&self) -> i32 {
198
0
            self.0.date.year().number
199
0
        }
200
201
        /// Returns whether this date is in a leap year
202
        #[diplomat::rust_link(icu::calendar::Date::is_in_leap_year, FnInStruct)]
203
        #[diplomat::attr(supports = accessors, getter)]
204
0
        pub fn is_in_leap_year(&self) -> bool {
205
0
            self.0.date.is_in_leap_year()
206
0
        }
207
208
        /// Returns the number of months in the year represented by this date
209
        #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
210
        #[diplomat::attr(supports = accessors, getter)]
211
0
        pub fn months_in_year(&self) -> u8 {
212
0
            self.0.date.months_in_year()
213
0
        }
214
215
        /// Returns the number of days in the month represented by this date
216
        #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
217
        #[diplomat::attr(supports = accessors, getter)]
218
0
        pub fn days_in_month(&self) -> u8 {
219
0
            self.0.date.days_in_month()
220
0
        }
221
222
        /// Returns the number of days in the year represented by this date
223
        #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
224
        #[diplomat::attr(supports = accessors, getter)]
225
0
        pub fn days_in_year(&self) -> u16 {
226
0
            self.0.date.days_in_year()
227
0
        }
228
    }
229
230
    #[diplomat::opaque]
231
    /// An ICU4X DateTime object capable of containing a date and time for any calendar.
232
    #[diplomat::rust_link(icu::calendar::DateTime, Struct)]
233
    pub struct ICU4XDateTime(pub DateTime<Arc<AnyCalendar>>);
234
235
    impl ICU4XDateTime {
236
        /// Creates a new [`ICU4XDateTime`] representing the ISO date and time
237
        /// given but in a given calendar
238
        #[diplomat::rust_link(icu::DateTime::new_from_iso, FnInStruct)]
239
        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_iso_in_calendar")]
240
        #[allow(clippy::too_many_arguments)]
241
0
        pub fn create_from_iso_in_calendar(
242
0
            year: i32,
243
0
            month: u8,
244
0
            day: u8,
245
0
            hour: u8,
246
0
            minute: u8,
247
0
            second: u8,
248
0
            nanosecond: u32,
249
0
            calendar: &ICU4XCalendar,
250
0
        ) -> Result<Box<ICU4XDateTime>, ICU4XError> {
251
0
            let cal = calendar.0.clone();
252
0
            let mut dt = DateTime::try_new_iso_datetime(year, month, day, hour, minute, second)?;
253
0
            dt.time.nanosecond = nanosecond.try_into()?;
254
0
            Ok(Box::new(ICU4XDateTime(dt.to_calendar(cal))))
255
0
        }
256
        /// Creates a new [`ICU4XDateTime`] from the given codes, which are interpreted in the given calendar system
257
        #[diplomat::rust_link(icu::calendar::DateTime::try_new_from_codes, FnInStruct)]
258
        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_codes_in_calendar")]
259
        #[allow(clippy::too_many_arguments)]
260
0
        pub fn create_from_codes_in_calendar(
261
0
            era_code: &DiplomatStr,
262
0
            year: i32,
263
0
            month_code: &DiplomatStr,
264
0
            day: u8,
265
0
            hour: u8,
266
0
            minute: u8,
267
0
            second: u8,
268
0
            nanosecond: u32,
269
0
            calendar: &ICU4XCalendar,
270
0
        ) -> Result<Box<ICU4XDateTime>, ICU4XError> {
271
0
            let era = TinyAsciiStr::from_bytes(era_code)
272
0
                .map_err(|_| ICU4XError::CalendarUnknownEraError)?
273
0
                .into();
274
0
            let month = TinyAsciiStr::from_bytes(month_code)
275
0
                .map_err(|_| ICU4XError::CalendarUnknownMonthCodeError)?
276
0
                .into();
277
0
            let cal = calendar.0.clone();
278
0
            let hour = hour.try_into()?;
279
0
            let minute = minute.try_into()?;
280
0
            let second = second.try_into()?;
281
0
            let nanosecond = nanosecond.try_into()?;
282
0
            let time = Time {
283
0
                hour,
284
0
                minute,
285
0
                second,
286
0
                nanosecond,
287
0
            };
288
0
            Ok(Box::new(ICU4XDateTime(DateTime::try_new_from_codes(
289
0
                era, year, month, day, time, cal,
290
0
            )?)))
291
0
        }
292
        /// Creates a new [`ICU4XDateTime`] from an [`ICU4XDate`] and [`ICU4XTime`] object
293
        #[diplomat::rust_link(icu::calendar::DateTime::new, FnInStruct)]
294
        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_date_and_time")]
295
0
        pub fn create_from_date_and_time(date: &ICU4XDate, time: &ICU4XTime) -> Box<ICU4XDateTime> {
296
0
            let dt = DateTime::new(date.0.clone(), time.0);
297
0
            Box::new(ICU4XDateTime(dt))
298
0
        }
299
300
        /// Gets a copy of the date contained in this object
301
        #[diplomat::rust_link(icu::calendar::DateTime::date, StructField)]
302
        #[diplomat::attr(supports = accessors, getter)]
303
0
        pub fn date(&self) -> Box<ICU4XDate> {
304
0
            Box::new(ICU4XDate(self.0.date.clone()))
305
0
        }
306
307
        /// Gets the time contained in this object
308
        #[diplomat::rust_link(icu::calendar::DateTime::time, StructField)]
309
        #[diplomat::attr(supports = accessors, getter)]
310
0
        pub fn time(&self) -> Box<ICU4XTime> {
311
0
            Box::new(ICU4XTime(self.0.time))
312
0
        }
313
314
        /// Converts this date to ISO
315
        #[diplomat::rust_link(icu::calendar::DateTime::to_iso, FnInStruct)]
316
0
        pub fn to_iso(&self) -> Box<ICU4XIsoDateTime> {
317
0
            Box::new(ICU4XIsoDateTime(self.0.to_iso()))
318
0
        }
319
320
        /// Convert this datetime to one in a different calendar
321
        #[diplomat::rust_link(icu::calendar::DateTime::to_calendar, FnInStruct)]
322
0
        pub fn to_calendar(&self, calendar: &ICU4XCalendar) -> Box<ICU4XDateTime> {
323
0
            Box::new(ICU4XDateTime(self.0.to_calendar(calendar.0.clone())))
324
0
        }
325
326
        /// Returns the hour in this time
327
        #[diplomat::rust_link(icu::calendar::Time::hour, StructField)]
328
        #[diplomat::attr(supports = accessors, getter)]
329
0
        pub fn hour(&self) -> u8 {
330
0
            self.0.time.hour.into()
331
0
        }
332
        /// Returns the minute in this time
333
        #[diplomat::rust_link(icu::calendar::Time::minute, StructField)]
334
        #[diplomat::attr(supports = accessors, getter)]
335
0
        pub fn minute(&self) -> u8 {
336
0
            self.0.time.minute.into()
337
0
        }
338
        /// Returns the second in this time
339
        #[diplomat::rust_link(icu::calendar::Time::second, StructField)]
340
        #[diplomat::attr(supports = accessors, getter)]
341
0
        pub fn second(&self) -> u8 {
342
0
            self.0.time.second.into()
343
0
        }
344
        /// Returns the nanosecond in this time
345
        #[diplomat::rust_link(icu::calendar::Time::nanosecond, StructField)]
346
        #[diplomat::attr(supports = accessors, getter)]
347
0
        pub fn nanosecond(&self) -> u32 {
348
0
            self.0.time.nanosecond.into()
349
0
        }
350
351
        /// Returns the 1-indexed day in the year for this date
352
        #[diplomat::rust_link(icu::calendar::Date::day_of_year_info, FnInStruct)]
353
        #[diplomat::attr(supports = accessors, getter)]
354
0
        pub fn day_of_year(&self) -> u16 {
355
0
            self.0.date.day_of_year_info().day_of_year
356
0
        }
357
358
        /// Returns the 1-indexed day in the month for this date
359
        #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
360
        #[diplomat::attr(supports = accessors, getter)]
361
0
        pub fn day_of_month(&self) -> u32 {
362
0
            self.0.date.day_of_month().0
363
0
        }
364
365
        /// Returns the day in the week for this day
366
        #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
367
        #[diplomat::attr(supports = accessors, getter)]
368
0
        pub fn day_of_week(&self) -> ICU4XIsoWeekday {
369
0
            self.0.date.day_of_week().into()
370
0
        }
371
372
        /// Returns the week number in this month, 1-indexed, based on what
373
        /// is considered the first day of the week (often a locale preference).
374
        ///
375
        /// `first_weekday` can be obtained via `first_weekday()` on [`ICU4XWeekCalculator`]
376
        #[diplomat::rust_link(icu::calendar::Date::week_of_month, FnInStruct)]
377
        #[diplomat::rust_link(
378
            icu::calendar::week::WeekCalculator::week_of_month,
379
            FnInStruct,
380
            hidden
381
        )]
382
0
        pub fn week_of_month(&self, first_weekday: ICU4XIsoWeekday) -> u32 {
383
0
            self.0.date.week_of_month(first_weekday.into()).0
384
0
        }
385
386
        /// Returns the week number in this year, using week data
387
        #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
388
        #[diplomat::rust_link(
389
            icu::calendar::week::WeekCalculator::week_of_year,
390
            FnInStruct,
391
            hidden
392
        )]
393
        #[cfg(feature = "icu_calendar")]
394
0
        pub fn week_of_year(
395
0
            &self,
396
0
            calculator: &ICU4XWeekCalculator,
397
0
        ) -> Result<crate::week::ffi::ICU4XWeekOf, ICU4XError> {
398
0
            Ok(self.0.date.week_of_year(&calculator.0)?.into())
399
0
        }
400
401
        /// Returns 1-indexed number of the month of this date in its year
402
        ///
403
        /// Note that for lunar calendars this may not lead to the same month
404
        /// having the same ordinal month across years; use month_code if you care
405
        /// about month identity.
406
        #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
407
        #[diplomat::attr(supports = accessors, getter)]
408
0
        pub fn ordinal_month(&self) -> u32 {
409
0
            self.0.date.month().ordinal
410
0
        }
411
412
        /// Returns the month code for this date. Typically something
413
        /// like "M01", "M02", but can be more complicated for lunar calendars.
414
        #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
415
        #[diplomat::attr(supports = accessors, getter)]
416
0
        pub fn month_code(
417
0
            &self,
418
0
            write: &mut diplomat_runtime::DiplomatWriteable,
419
0
        ) -> Result<(), ICU4XError> {
420
0
            let code = self.0.date.month().code;
421
0
            write.write_str(&code.0)?;
422
0
            Ok(())
423
0
        }
424
425
        /// Returns the year number in the current era for this date
426
        #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
427
        #[diplomat::attr(supports = accessors, getter)]
428
0
        pub fn year_in_era(&self) -> i32 {
429
0
            self.0.date.year().number
430
0
        }
431
432
        /// Returns the era for this date,
433
        #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
434
        #[diplomat::attr(supports = accessors, getter)]
435
0
        pub fn era(
436
0
            &self,
437
0
            write: &mut diplomat_runtime::DiplomatWriteable,
438
0
        ) -> Result<(), ICU4XError> {
439
0
            let era = self.0.date.year().era;
440
0
            write.write_str(&era.0)?;
441
0
            Ok(())
442
0
        }
443
444
        /// Returns the number of months in the year represented by this date
445
        #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
446
        #[diplomat::attr(supports = accessors, getter)]
447
0
        pub fn months_in_year(&self) -> u8 {
448
0
            self.0.date.months_in_year()
449
0
        }
450
451
        /// Returns the number of days in the month represented by this date
452
        #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
453
        #[diplomat::attr(supports = accessors, getter)]
454
0
        pub fn days_in_month(&self) -> u8 {
455
0
            self.0.date.days_in_month()
456
0
        }
457
458
        /// Returns the number of days in the year represented by this date
459
        #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
460
        #[diplomat::attr(supports = accessors, getter)]
461
0
        pub fn days_in_year(&self) -> u16 {
462
0
            self.0.date.days_in_year()
463
0
        }
464
465
        /// Returns the [`ICU4XCalendar`] object backing this date
466
        #[diplomat::rust_link(icu::calendar::Date::calendar, FnInStruct)]
467
        #[diplomat::rust_link(icu::calendar::Date::calendar_wrapper, FnInStruct, hidden)]
468
        #[diplomat::attr(supports = accessors, getter)]
469
0
        pub fn calendar(&self) -> Box<ICU4XCalendar> {
470
0
            Box::new(ICU4XCalendar(self.0.date.calendar_wrapper().clone()))
471
0
        }
472
    }
473
}