Coverage Report

Created: 2025-08-26 06:41

/rust/registry/src/index.crates.io-6f17d22bba15001f/icu_calendar-1.5.2/src/datetime.rs
Line
Count
Source (jump to first uncovered line)
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 crate::any_calendar::{AnyCalendar, IntoAnyCalendar};
6
use crate::types::{self, Time};
7
use crate::{AsCalendar, Calendar, CalendarError, Date, Iso};
8
use alloc::rc::Rc;
9
use alloc::sync::Arc;
10
11
/// A date+time for a given calendar.
12
///
13
/// This can work with wrappers around [`Calendar`](crate::Calendar) types,
14
/// e.g. `Rc<C>`, via the [`AsCalendar`] trait, much like
15
/// [`Date`].
16
///
17
/// This can be constructed manually from a [`Date`] and [`Time`], or can be constructed
18
/// from its fields via [`Self::try_new_from_codes()`], or can be constructed with one of the
19
/// `new_<calendar>_datetime()` per-calendar methods (and then freely converted between calendars).
20
///
21
/// ```rust
22
/// use icu::calendar::DateTime;
23
///
24
/// // Example: Construction of ISO datetime from integers.
25
/// let datetime_iso = DateTime::try_new_iso_datetime(1970, 1, 2, 13, 1, 0)
26
///     .expect("Failed to initialize ISO DateTime instance.");
27
///
28
/// assert_eq!(datetime_iso.date.year().number, 1970);
29
/// assert_eq!(datetime_iso.date.month().ordinal, 1);
30
/// assert_eq!(datetime_iso.date.day_of_month().0, 2);
31
/// assert_eq!(datetime_iso.time.hour.number(), 13);
32
/// assert_eq!(datetime_iso.time.minute.number(), 1);
33
/// assert_eq!(datetime_iso.time.second.number(), 0);
34
/// ```
35
#[derive(Debug)]
36
#[allow(clippy::exhaustive_structs)] // this type is stable
37
pub struct DateTime<A: AsCalendar> {
38
    /// The date
39
    pub date: Date<A>,
40
    /// The time
41
    pub time: Time,
42
}
43
44
impl<A: AsCalendar> DateTime<A> {
45
    /// Construct a [`DateTime`] for a given [`Date`] and [`Time`]
46
0
    pub fn new(date: Date<A>, time: Time) -> Self {
47
0
        DateTime { date, time }
48
0
    }
Unexecuted instantiation: <icu_calendar::datetime::DateTime<alloc::sync::Arc<icu_calendar::any_calendar::AnyCalendar>>>::new
Unexecuted instantiation: <icu_calendar::datetime::DateTime<icu_calendar::iso::Iso>>::new
Unexecuted instantiation: <icu_calendar::datetime::DateTime<_>>::new
49
50
    /// Construct a datetime from from era/month codes and fields,
51
    /// and some calendar representation
52
    #[inline]
53
0
    pub fn try_new_from_codes(
54
0
        era: types::Era,
55
0
        year: i32,
56
0
        month_code: types::MonthCode,
57
0
        day: u8,
58
0
        time: Time,
59
0
        calendar: A,
60
0
    ) -> Result<Self, CalendarError> {
61
0
        let date = Date::try_new_from_codes(era, year, month_code, day, calendar)?;
62
0
        Ok(DateTime { date, time })
63
0
    }
Unexecuted instantiation: <icu_calendar::datetime::DateTime<alloc::sync::Arc<icu_calendar::any_calendar::AnyCalendar>>>::try_new_from_codes
Unexecuted instantiation: <icu_calendar::datetime::DateTime<_>>::try_new_from_codes
64
65
    /// Construct a DateTime from an ISO datetime and some calendar representation
66
    #[inline]
67
0
    pub fn new_from_iso(iso: DateTime<Iso>, calendar: A) -> Self {
68
0
        let date = Date::new_from_iso(iso.date, calendar);
69
0
        DateTime {
70
0
            date,
71
0
            time: iso.time,
72
0
        }
73
0
    }
Unexecuted instantiation: <icu_calendar::datetime::DateTime<icu_calendar::gregorian::Gregorian>>::new_from_iso
Unexecuted instantiation: <icu_calendar::datetime::DateTime<_>>::new_from_iso
74
75
    /// Convert the DateTime to an ISO DateTime
76
    #[inline]
77
0
    pub fn to_iso(&self) -> DateTime<Iso> {
78
0
        DateTime {
79
0
            date: self.date.to_iso(),
80
0
            time: self.time,
81
0
        }
82
0
    }
Unexecuted instantiation: <icu_calendar::datetime::DateTime<alloc::sync::Arc<icu_calendar::any_calendar::AnyCalendar>>>::to_iso
Unexecuted instantiation: <icu_calendar::datetime::DateTime<_>>::to_iso
83
84
    /// Convert the DateTime to a DateTime in a different calendar
85
    #[inline]
86
0
    pub fn to_calendar<A2: AsCalendar>(&self, calendar: A2) -> DateTime<A2> {
87
0
        DateTime {
88
0
            date: self.date.to_calendar(calendar),
89
0
            time: self.time,
90
0
        }
91
0
    }
Unexecuted instantiation: <icu_calendar::datetime::DateTime<alloc::sync::Arc<icu_calendar::any_calendar::AnyCalendar>>>::to_calendar::<alloc::sync::Arc<icu_calendar::any_calendar::AnyCalendar>>
Unexecuted instantiation: <icu_calendar::datetime::DateTime<icu_calendar::iso::Iso>>::to_calendar::<alloc::sync::Arc<icu_calendar::any_calendar::AnyCalendar>>
Unexecuted instantiation: <icu_calendar::datetime::DateTime<_>>::to_calendar::<_>
92
}
93
94
impl<C: IntoAnyCalendar, A: AsCalendar<Calendar = C>> DateTime<A> {
95
    /// Type-erase the date, converting it to a date for [`AnyCalendar`]
96
0
    pub fn to_any(&self) -> DateTime<AnyCalendar> {
97
0
        DateTime {
98
0
            date: self.date.to_any(),
99
0
            time: self.time,
100
0
        }
101
0
    }
Unexecuted instantiation: <icu_calendar::datetime::DateTime<icu_calendar::iso::Iso>>::to_any
Unexecuted instantiation: <icu_calendar::datetime::DateTime<_>>::to_any
102
}
103
104
impl<C: Calendar> DateTime<C> {
105
    /// Wrap the calendar type in `Rc<T>`
106
    ///
107
    /// Useful when paired with [`Self::to_any()`] to obtain a `DateTime<Rc<AnyCalendar>>`
108
0
    pub fn wrap_calendar_in_rc(self) -> DateTime<Rc<C>> {
109
0
        DateTime {
110
0
            date: self.date.wrap_calendar_in_rc(),
111
0
            time: self.time,
112
0
        }
113
0
    }
114
115
    /// Wrap the calendar type in `Arc<T>`
116
    ///
117
    /// Useful when paired with [`Self::to_any()`] to obtain a `DateTime<Rc<AnyCalendar>>`
118
0
    pub fn wrap_calendar_in_arc(self) -> DateTime<Arc<C>> {
119
0
        DateTime {
120
0
            date: self.date.wrap_calendar_in_arc(),
121
0
            time: self.time,
122
0
        }
123
0
    }
Unexecuted instantiation: <icu_calendar::datetime::DateTime<icu_calendar::any_calendar::AnyCalendar>>::wrap_calendar_in_arc
Unexecuted instantiation: <icu_calendar::datetime::DateTime<_>>::wrap_calendar_in_arc
124
}
125
126
impl<C, A, B> PartialEq<DateTime<B>> for DateTime<A>
127
where
128
    C: Calendar,
129
    A: AsCalendar<Calendar = C>,
130
    B: AsCalendar<Calendar = C>,
131
{
132
0
    fn eq(&self, other: &DateTime<B>) -> bool {
133
0
        self.date == other.date && self.time == other.time
134
0
    }
135
}
136
137
// We can do this since DateInner is required to be Eq by the Calendar trait
138
impl<A: AsCalendar> Eq for DateTime<A> {}
139
140
impl<C, A, B> PartialOrd<DateTime<B>> for DateTime<A>
141
where
142
    C: Calendar,
143
    C::DateInner: PartialOrd,
144
    A: AsCalendar<Calendar = C>,
145
    B: AsCalendar<Calendar = C>,
146
{
147
0
    fn partial_cmp(&self, other: &DateTime<B>) -> Option<core::cmp::Ordering> {
148
0
        match self.date.partial_cmp(&other.date) {
149
0
            Some(core::cmp::Ordering::Equal) => self.time.partial_cmp(&other.time),
150
0
            other => other,
151
        }
152
0
    }
153
}
154
155
impl<C, A> Ord for DateTime<A>
156
where
157
    C: Calendar,
158
    C::DateInner: Ord,
159
    A: AsCalendar<Calendar = C>,
160
{
161
0
    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
162
0
        (&self.date, &self.time).cmp(&(&other.date, &other.time))
163
0
    }
164
}
165
166
impl<A: AsCalendar + Clone> Clone for DateTime<A> {
167
0
    fn clone(&self) -> Self {
168
0
        Self {
169
0
            date: self.date.clone(),
170
0
            time: self.time,
171
0
        }
172
0
    }
173
}
174
175
impl<A> Copy for DateTime<A>
176
where
177
    A: AsCalendar + Copy,
178
    <<A as AsCalendar>::Calendar as Calendar>::DateInner: Copy,
179
{
180
}
181
182
#[cfg(test)]
183
mod tests {
184
    use super::*;
185
186
    #[test]
187
    fn test_ord() {
188
        let dates_in_order = [
189
            DateTime::try_new_iso_datetime(0, 1, 1, 0, 0, 0).unwrap(),
190
            DateTime::try_new_iso_datetime(0, 1, 1, 0, 0, 1).unwrap(),
191
            DateTime::try_new_iso_datetime(0, 1, 1, 0, 1, 0).unwrap(),
192
            DateTime::try_new_iso_datetime(0, 1, 1, 1, 0, 0).unwrap(),
193
            DateTime::try_new_iso_datetime(0, 1, 2, 0, 0, 0).unwrap(),
194
            DateTime::try_new_iso_datetime(0, 2, 1, 0, 0, 0).unwrap(),
195
            DateTime::try_new_iso_datetime(1, 1, 1, 0, 0, 0).unwrap(),
196
        ];
197
        for (i, i_date) in dates_in_order.iter().enumerate() {
198
            for (j, j_date) in dates_in_order.iter().enumerate() {
199
                let result1 = i_date.cmp(j_date);
200
                let result2 = j_date.cmp(i_date);
201
                assert_eq!(result1.reverse(), result2);
202
                assert_eq!(i.cmp(&j), i_date.cmp(j_date));
203
            }
204
        }
205
    }
206
}