time/
utc_date_time.rs

1//! The [`UtcDateTime`] struct and associated `impl`s.
2
3#[cfg(feature = "formatting")]
4use alloc::string::String;
5use core::fmt;
6use core::ops::{Add, AddAssign, Sub, SubAssign};
7use core::time::Duration as StdDuration;
8#[cfg(feature = "formatting")]
9use std::io;
10
11use deranged::RangedI64;
12use powerfmt::ext::FormatterExt as _;
13use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
14
15use crate::convert::*;
16use crate::date::{MAX_YEAR, MIN_YEAR};
17#[cfg(feature = "formatting")]
18use crate::formatting::Formattable;
19use crate::internal_macros::{
20    cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt,
21};
22#[cfg(feature = "parsing")]
23use crate::parsing::Parsable;
24use crate::{
25    error, util, Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset, Weekday,
26};
27
28/// The Julian day of the Unix epoch.
29const UNIX_EPOCH_JULIAN_DAY: i32 = UtcDateTime::UNIX_EPOCH.to_julian_day();
30
31/// A [`PrimitiveDateTime`] that is known to be UTC.
32///
33/// `UtcDateTime` is guaranteed to be ABI-compatible with [`PrimitiveDateTime`], meaning that
34/// transmuting from one to the other will not result in undefined behavior.
35#[repr(transparent)]
36#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub struct UtcDateTime {
38    inner: PrimitiveDateTime,
39}
40
41impl UtcDateTime {
42    /// Midnight, 1 January, 1970.
43    ///
44    /// ```rust
45    /// # use time::UtcDateTime;
46    /// # use time_macros::utc_datetime;
47    /// assert_eq!(UtcDateTime::UNIX_EPOCH, utc_datetime!(1970-01-01 0:00));
48    /// ```
49    pub const UNIX_EPOCH: Self = Self::new(
50        // Safety: `ordinal` is not zero.
51        unsafe { Date::__from_ordinal_date_unchecked(1970, 1) },
52        Time::MIDNIGHT,
53    );
54
55    /// The smallest value that can be represented by `UtcDateTime`.
56    ///
57    /// Depending on `large-dates` feature flag, value of this constant may vary.
58    ///
59    /// 1. With `large-dates` disabled it is equal to `-9999-01-01 00:00:00.0`
60    /// 2. With `large-dates` enabled it is equal to `-999999-01-01 00:00:00.0`
61    ///
62    /// ```rust
63    /// # use time::UtcDateTime;
64    /// # use time_macros::utc_datetime;
65    #[cfg_attr(
66        feature = "large-dates",
67        doc = "// Assuming `large-dates` feature is enabled."
68    )]
69    #[cfg_attr(
70        feature = "large-dates",
71        doc = "assert_eq!(UtcDateTime::MIN, utc_datetime!(-999999-01-01 0:00));"
72    )]
73    #[cfg_attr(
74        not(feature = "large-dates"),
75        doc = "// Assuming `large-dates` feature is disabled."
76    )]
77    #[cfg_attr(
78        not(feature = "large-dates"),
79        doc = "assert_eq!(UtcDateTime::MIN, utc_datetime!(-9999-01-01 0:00));"
80    )]
81    /// ```
82    pub const MIN: Self = Self::new(Date::MIN, Time::MIDNIGHT);
83
84    /// The largest value that can be represented by `UtcDateTime`.
85    ///
86    /// Depending on `large-dates` feature flag, value of this constant may vary.
87    ///
88    /// 1. With `large-dates` disabled it is equal to `9999-12-31 23:59:59.999_999_999`
89    /// 2. With `large-dates` enabled it is equal to `999999-12-31 23:59:59.999_999_999`
90    ///
91    /// ```rust
92    /// # use time::UtcDateTime;
93    /// # use time_macros::utc_datetime;
94    #[cfg_attr(
95        feature = "large-dates",
96        doc = "// Assuming `large-dates` feature is enabled."
97    )]
98    #[cfg_attr(
99        feature = "large-dates",
100        doc = "assert_eq!(UtcDateTime::MAX, utc_datetime!(+999999-12-31 23:59:59.999_999_999));"
101    )]
102    #[cfg_attr(
103        not(feature = "large-dates"),
104        doc = "// Assuming `large-dates` feature is disabled."
105    )]
106    #[cfg_attr(
107        not(feature = "large-dates"),
108        doc = "assert_eq!(UtcDateTime::MAX, utc_datetime!(+9999-12-31 23:59:59.999_999_999));"
109    )]
110    /// ```
111    pub const MAX: Self = Self::new(Date::MAX, Time::MAX);
112
113    /// Create a new `UtcDateTime` with the current date and time.
114    ///
115    /// ```rust
116    /// # use time::UtcDateTime;
117    /// assert!(UtcDateTime::now().year() >= 2019);
118    /// ```
119    #[cfg(feature = "std")]
120    pub fn now() -> Self {
121        #[cfg(all(
122            target_family = "wasm",
123            not(any(target_os = "emscripten", target_os = "wasi")),
124            feature = "wasm-bindgen"
125        ))]
126        {
127            js_sys::Date::new_0().into()
128        }
129
130        #[cfg(not(all(
131            target_family = "wasm",
132            not(any(target_os = "emscripten", target_os = "wasi")),
133            feature = "wasm-bindgen"
134        )))]
135        std::time::SystemTime::now().into()
136    }
137
138    /// Create a new `UtcDateTime` from the provided [`Date`] and [`Time`].
139    ///
140    /// ```rust
141    /// # use time::UtcDateTime;
142    /// # use time_macros::{date, utc_datetime, time};
143    /// assert_eq!(
144    ///     UtcDateTime::new(date!(2019-01-01), time!(0:00)),
145    ///     utc_datetime!(2019-01-01 0:00),
146    /// );
147    /// ```
148    pub const fn new(date: Date, time: Time) -> Self {
149        Self {
150            inner: PrimitiveDateTime::new(date, time),
151        }
152    }
153
154    /// Create a new `UtcDateTime` from the [`PrimitiveDateTime`], assuming that the latter is UTC.
155    pub(crate) const fn from_primitive(date_time: PrimitiveDateTime) -> Self {
156        Self { inner: date_time }
157    }
158
159    /// Obtain the [`PrimitiveDateTime`] that this `UtcDateTime` represents. The no-longer-attached
160    /// [`UtcOffset`] is assumed to be UTC.
161    pub(crate) const fn as_primitive(self) -> PrimitiveDateTime {
162        self.inner
163    }
164
165    /// Create a `UtcDateTime` from the provided Unix timestamp.
166    ///
167    /// ```rust
168    /// # use time::UtcDateTime;
169    /// # use time_macros::utc_datetime;
170    /// assert_eq!(
171    ///     UtcDateTime::from_unix_timestamp(0),
172    ///     Ok(UtcDateTime::UNIX_EPOCH),
173    /// );
174    /// assert_eq!(
175    ///     UtcDateTime::from_unix_timestamp(1_546_300_800),
176    ///     Ok(utc_datetime!(2019-01-01 0:00)),
177    /// );
178    /// ```
179    ///
180    /// If you have a timestamp-nanosecond pair, you can use something along the lines of the
181    /// following:
182    ///
183    /// ```rust
184    /// # use time::{Duration, UtcDateTime, ext::NumericalDuration};
185    /// let (timestamp, nanos) = (1, 500_000_000);
186    /// assert_eq!(
187    ///     UtcDateTime::from_unix_timestamp(timestamp)? + Duration::nanoseconds(nanos),
188    ///     UtcDateTime::UNIX_EPOCH + 1.5.seconds()
189    /// );
190    /// # Ok::<_, time::Error>(())
191    /// ```
192    pub const fn from_unix_timestamp(timestamp: i64) -> Result<Self, error::ComponentRange> {
193        type Timestamp =
194            RangedI64<{ UtcDateTime::MIN.unix_timestamp() }, { UtcDateTime::MAX.unix_timestamp() }>;
195        ensure_ranged!(Timestamp: timestamp);
196
197        // Use the unchecked method here, as the input validity has already been verified.
198        // Safety: The Julian day number is in range.
199        let date = unsafe {
200            Date::from_julian_day_unchecked(
201                UNIX_EPOCH_JULIAN_DAY + div_floor!(timestamp, Second::per_t::<i64>(Day)) as i32,
202            )
203        };
204
205        let seconds_within_day = timestamp.rem_euclid(Second::per_t::<i64>(Day));
206        // Safety: All values are in range.
207        let time = unsafe {
208            Time::__from_hms_nanos_unchecked(
209                (seconds_within_day / Second::per_t::<i64>(Hour)) as u8,
210                ((seconds_within_day % Second::per_t::<i64>(Hour)) / Minute::per_t::<i64>(Hour))
211                    as u8,
212                (seconds_within_day % Second::per_t::<i64>(Minute)) as u8,
213                0,
214            )
215        };
216
217        Ok(Self::new(date, time))
218    }
219
220    /// Construct an `UtcDateTime` from the provided Unix timestamp (in nanoseconds).
221    ///
222    /// ```rust
223    /// # use time::UtcDateTime;
224    /// # use time_macros::utc_datetime;
225    /// assert_eq!(
226    ///     UtcDateTime::from_unix_timestamp_nanos(0),
227    ///     Ok(UtcDateTime::UNIX_EPOCH),
228    /// );
229    /// assert_eq!(
230    ///     UtcDateTime::from_unix_timestamp_nanos(1_546_300_800_000_000_000),
231    ///     Ok(utc_datetime!(2019-01-01 0:00)),
232    /// );
233    /// ```
234    pub const fn from_unix_timestamp_nanos(timestamp: i128) -> Result<Self, error::ComponentRange> {
235        let datetime = const_try!(Self::from_unix_timestamp(div_floor!(
236            timestamp,
237            Nanosecond::per_t::<i128>(Second)
238        ) as i64));
239
240        Ok(Self::new(
241            datetime.date(),
242            // Safety: `nanosecond` is in range due to `rem_euclid`.
243            unsafe {
244                Time::__from_hms_nanos_unchecked(
245                    datetime.hour(),
246                    datetime.minute(),
247                    datetime.second(),
248                    timestamp.rem_euclid(Nanosecond::per_t(Second)) as u32,
249                )
250            },
251        ))
252    }
253
254    /// Convert the `UtcDateTime` from UTC to the provided [`UtcOffset`], returning an
255    /// [`OffsetDateTime`].
256    ///
257    /// ```rust
258    /// # use time_macros::{utc_datetime, offset};
259    /// assert_eq!(
260    ///     utc_datetime!(2000-01-01 0:00)
261    ///         .to_offset(offset!(-1))
262    ///         .year(),
263    ///     1999,
264    /// );
265    ///
266    /// // Construct midnight on new year's, UTC.
267    /// let utc = utc_datetime!(2000-01-01 0:00);
268    /// let new_york = utc.to_offset(offset!(-5));
269    /// let los_angeles = utc.to_offset(offset!(-8));
270    /// assert_eq!(utc.hour(), 0);
271    /// assert_eq!(new_york.hour(), 19);
272    /// assert_eq!(los_angeles.hour(), 16);
273    /// ```
274    ///
275    /// # Panics
276    ///
277    /// This method panics if the local date-time in the new offset is outside the supported range.
278    pub const fn to_offset(self, offset: UtcOffset) -> OffsetDateTime {
279        expect_opt!(
280            self.checked_to_offset(offset),
281            "local datetime out of valid range"
282        )
283    }
284
285    /// Convert the `UtcDateTime` from UTC to the provided [`UtcOffset`], returning an
286    /// [`OffsetDateTime`]. `None` is returned if the date-time in the resulting offset is
287    /// invalid.
288    ///
289    /// ```rust
290    /// # use time::UtcDateTime;
291    /// # use time_macros::{utc_datetime, offset};
292    /// assert_eq!(
293    ///     utc_datetime!(2000-01-01 0:00)
294    ///         .checked_to_offset(offset!(-1))
295    ///         .unwrap()
296    ///         .year(),
297    ///     1999,
298    /// );
299    /// assert_eq!(
300    ///     UtcDateTime::MAX.checked_to_offset(offset!(+1)),
301    ///     None,
302    /// );
303    /// ```
304    pub const fn checked_to_offset(self, offset: UtcOffset) -> Option<OffsetDateTime> {
305        // Fast path for when no conversion is necessary.
306        if offset.is_utc() {
307            return Some(self.inner.assume_utc());
308        }
309
310        let (year, ordinal, time) = self.to_offset_raw(offset);
311
312        if year > MAX_YEAR || year < MIN_YEAR {
313            return None;
314        }
315
316        Some(OffsetDateTime::new_in_offset(
317            // Safety: `ordinal` is not zero.
318            unsafe { Date::__from_ordinal_date_unchecked(year, ordinal) },
319            time,
320            offset,
321        ))
322    }
323
324    /// Equivalent to `.to_offset(UtcOffset::UTC)`, but returning the year, ordinal, and time. This
325    /// avoids constructing an invalid [`Date`] if the new value is out of range.
326    pub(crate) const fn to_offset_raw(self, offset: UtcOffset) -> (i32, u16, Time) {
327        let mut second = self.second() as i16 + offset.seconds_past_minute() as i16;
328        let mut minute = self.minute() as i16 + offset.minutes_past_hour() as i16;
329        let mut hour = self.hour() as i8 + offset.whole_hours();
330        let (mut year, ordinal) = self.to_ordinal_date();
331        let mut ordinal = ordinal as i16;
332
333        cascade!(second in 0..Second::per_t(Minute) => minute);
334        cascade!(minute in 0..Minute::per_t(Hour) => hour);
335        cascade!(hour in 0..Hour::per_t(Day) => ordinal);
336        cascade!(ordinal => year);
337
338        debug_assert!(ordinal > 0);
339        debug_assert!(ordinal <= util::days_in_year(year) as i16);
340
341        (
342            year,
343            ordinal as u16,
344            // Safety: The cascades above ensure the values are in range.
345            unsafe {
346                Time::__from_hms_nanos_unchecked(
347                    hour as u8,
348                    minute as u8,
349                    second as u8,
350                    self.nanosecond(),
351                )
352            },
353        )
354    }
355
356    /// Get the [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time).
357    ///
358    /// ```rust
359    /// # use time_macros::utc_datetime;
360    /// assert_eq!(utc_datetime!(1970-01-01 0:00).unix_timestamp(), 0);
361    /// assert_eq!(utc_datetime!(1970-01-01 1:00).unix_timestamp(), 3_600);
362    /// ```
363    pub const fn unix_timestamp(self) -> i64 {
364        let days = (self.to_julian_day() as i64 - UNIX_EPOCH_JULIAN_DAY as i64)
365            * Second::per_t::<i64>(Day);
366        let hours = self.hour() as i64 * Second::per_t::<i64>(Hour);
367        let minutes = self.minute() as i64 * Second::per_t::<i64>(Minute);
368        let seconds = self.second() as i64;
369        days + hours + minutes + seconds
370    }
371
372    /// Get the Unix timestamp in nanoseconds.
373    ///
374    /// ```rust
375    /// use time_macros::utc_datetime;
376    /// assert_eq!(utc_datetime!(1970-01-01 0:00).unix_timestamp_nanos(), 0);
377    /// assert_eq!(
378    ///     utc_datetime!(1970-01-01 1:00).unix_timestamp_nanos(),
379    ///     3_600_000_000_000,
380    /// );
381    /// ```
382    pub const fn unix_timestamp_nanos(self) -> i128 {
383        self.unix_timestamp() as i128 * Nanosecond::per_t::<i128>(Second)
384            + self.nanosecond() as i128
385    }
386
387    /// Get the [`Date`] component of the `UtcDateTime`.
388    ///
389    /// ```rust
390    /// # use time_macros::{date, utc_datetime};
391    /// assert_eq!(utc_datetime!(2019-01-01 0:00).date(), date!(2019-01-01));
392    /// ```
393    pub const fn date(self) -> Date {
394        self.inner.date()
395    }
396
397    /// Get the [`Time`] component of the `UtcDateTime`.
398    ///
399    /// ```rust
400    /// # use time_macros::{utc_datetime, time};
401    /// assert_eq!(utc_datetime!(2019-01-01 0:00).time(), time!(0:00));
402    /// ```
403    pub const fn time(self) -> Time {
404        self.inner.time()
405    }
406
407    /// Get the year of the date.
408    ///
409    /// ```rust
410    /// # use time_macros::utc_datetime;
411    /// assert_eq!(utc_datetime!(2019-01-01 0:00).year(), 2019);
412    /// assert_eq!(utc_datetime!(2019-12-31 0:00).year(), 2019);
413    /// assert_eq!(utc_datetime!(2020-01-01 0:00).year(), 2020);
414    /// ```
415    pub const fn year(self) -> i32 {
416        self.date().year()
417    }
418
419    /// Get the month of the date.
420    ///
421    /// ```rust
422    /// # use time::Month;
423    /// # use time_macros::utc_datetime;
424    /// assert_eq!(utc_datetime!(2019-01-01 0:00).month(), Month::January);
425    /// assert_eq!(utc_datetime!(2019-12-31 0:00).month(), Month::December);
426    /// ```
427    pub const fn month(self) -> Month {
428        self.date().month()
429    }
430
431    /// Get the day of the date.
432    ///
433    /// The returned value will always be in the range `1..=31`.
434    ///
435    /// ```rust
436    /// # use time_macros::utc_datetime;
437    /// assert_eq!(utc_datetime!(2019-01-01 0:00).day(), 1);
438    /// assert_eq!(utc_datetime!(2019-12-31 0:00).day(), 31);
439    /// ```
440    pub const fn day(self) -> u8 {
441        self.date().day()
442    }
443
444    /// Get the day of the year.
445    ///
446    /// The returned value will always be in the range `1..=366` (`1..=365` for common years).
447    ///
448    /// ```rust
449    /// # use time_macros::utc_datetime;
450    /// assert_eq!(utc_datetime!(2019-01-01 0:00).ordinal(), 1);
451    /// assert_eq!(utc_datetime!(2019-12-31 0:00).ordinal(), 365);
452    /// ```
453    pub const fn ordinal(self) -> u16 {
454        self.date().ordinal()
455    }
456
457    /// Get the ISO week number.
458    ///
459    /// The returned value will always be in the range `1..=53`.
460    ///
461    /// ```rust
462    /// # use time_macros::utc_datetime;
463    /// assert_eq!(utc_datetime!(2019-01-01 0:00).iso_week(), 1);
464    /// assert_eq!(utc_datetime!(2019-10-04 0:00).iso_week(), 40);
465    /// assert_eq!(utc_datetime!(2020-01-01 0:00).iso_week(), 1);
466    /// assert_eq!(utc_datetime!(2020-12-31 0:00).iso_week(), 53);
467    /// assert_eq!(utc_datetime!(2021-01-01 0:00).iso_week(), 53);
468    /// ```
469    pub const fn iso_week(self) -> u8 {
470        self.date().iso_week()
471    }
472
473    /// Get the week number where week 1 begins on the first Sunday.
474    ///
475    /// The returned value will always be in the range `0..=53`.
476    ///
477    /// ```rust
478    /// # use time_macros::utc_datetime;
479    /// assert_eq!(utc_datetime!(2019-01-01 0:00).sunday_based_week(), 0);
480    /// assert_eq!(utc_datetime!(2020-01-01 0:00).sunday_based_week(), 0);
481    /// assert_eq!(utc_datetime!(2020-12-31 0:00).sunday_based_week(), 52);
482    /// assert_eq!(utc_datetime!(2021-01-01 0:00).sunday_based_week(), 0);
483    /// ```
484    pub const fn sunday_based_week(self) -> u8 {
485        self.date().sunday_based_week()
486    }
487
488    /// Get the week number where week 1 begins on the first Monday.
489    ///
490    /// The returned value will always be in the range `0..=53`.
491    ///
492    /// ```rust
493    /// # use time_macros::utc_datetime;
494    /// assert_eq!(utc_datetime!(2019-01-01 0:00).monday_based_week(), 0);
495    /// assert_eq!(utc_datetime!(2020-01-01 0:00).monday_based_week(), 0);
496    /// assert_eq!(utc_datetime!(2020-12-31 0:00).monday_based_week(), 52);
497    /// assert_eq!(utc_datetime!(2021-01-01 0:00).monday_based_week(), 0);
498    /// ```
499    pub const fn monday_based_week(self) -> u8 {
500        self.date().monday_based_week()
501    }
502
503    /// Get the year, month, and day.
504    ///
505    /// ```rust
506    /// # use time::Month;
507    /// # use time_macros::utc_datetime;
508    /// assert_eq!(
509    ///     utc_datetime!(2019-01-01 0:00).to_calendar_date(),
510    ///     (2019, Month::January, 1)
511    /// );
512    /// ```
513    pub const fn to_calendar_date(self) -> (i32, Month, u8) {
514        self.date().to_calendar_date()
515    }
516
517    /// Get the year and ordinal day number.
518    ///
519    /// ```rust
520    /// # use time_macros::utc_datetime;
521    /// assert_eq!(utc_datetime!(2019-01-01 0:00).to_ordinal_date(), (2019, 1));
522    /// ```
523    pub const fn to_ordinal_date(self) -> (i32, u16) {
524        self.date().to_ordinal_date()
525    }
526
527    /// Get the ISO 8601 year, week number, and weekday.
528    ///
529    /// ```rust
530    /// # use time::Weekday::*;
531    /// # use time_macros::utc_datetime;
532    /// assert_eq!(
533    ///     utc_datetime!(2019-01-01 0:00).to_iso_week_date(),
534    ///     (2019, 1, Tuesday)
535    /// );
536    /// assert_eq!(
537    ///     utc_datetime!(2019-10-04 0:00).to_iso_week_date(),
538    ///     (2019, 40, Friday)
539    /// );
540    /// assert_eq!(
541    ///     utc_datetime!(2020-01-01 0:00).to_iso_week_date(),
542    ///     (2020, 1, Wednesday)
543    /// );
544    /// assert_eq!(
545    ///     utc_datetime!(2020-12-31 0:00).to_iso_week_date(),
546    ///     (2020, 53, Thursday)
547    /// );
548    /// assert_eq!(
549    ///     utc_datetime!(2021-01-01 0:00).to_iso_week_date(),
550    ///     (2020, 53, Friday)
551    /// );
552    /// ```
553    pub const fn to_iso_week_date(self) -> (i32, u8, Weekday) {
554        self.date().to_iso_week_date()
555    }
556
557    /// Get the weekday.
558    ///
559    /// ```rust
560    /// # use time::Weekday::*;
561    /// # use time_macros::utc_datetime;
562    /// assert_eq!(utc_datetime!(2019-01-01 0:00).weekday(), Tuesday);
563    /// assert_eq!(utc_datetime!(2019-02-01 0:00).weekday(), Friday);
564    /// assert_eq!(utc_datetime!(2019-03-01 0:00).weekday(), Friday);
565    /// assert_eq!(utc_datetime!(2019-04-01 0:00).weekday(), Monday);
566    /// assert_eq!(utc_datetime!(2019-05-01 0:00).weekday(), Wednesday);
567    /// assert_eq!(utc_datetime!(2019-06-01 0:00).weekday(), Saturday);
568    /// assert_eq!(utc_datetime!(2019-07-01 0:00).weekday(), Monday);
569    /// assert_eq!(utc_datetime!(2019-08-01 0:00).weekday(), Thursday);
570    /// assert_eq!(utc_datetime!(2019-09-01 0:00).weekday(), Sunday);
571    /// assert_eq!(utc_datetime!(2019-10-01 0:00).weekday(), Tuesday);
572    /// assert_eq!(utc_datetime!(2019-11-01 0:00).weekday(), Friday);
573    /// assert_eq!(utc_datetime!(2019-12-01 0:00).weekday(), Sunday);
574    /// ```
575    pub const fn weekday(self) -> Weekday {
576        self.date().weekday()
577    }
578
579    /// Get the Julian day for the date. The time is not taken into account for this calculation.
580    ///
581    /// The algorithm to perform this conversion is derived from one provided by Peter Baum; it is
582    /// freely available [here](https://www.researchgate.net/publication/316558298_Date_Algorithms).
583    ///
584    /// ```rust
585    /// # use time_macros::utc_datetime;
586    /// assert_eq!(utc_datetime!(-4713-11-24 0:00).to_julian_day(), 0);
587    /// assert_eq!(utc_datetime!(2000-01-01 0:00).to_julian_day(), 2_451_545);
588    /// assert_eq!(utc_datetime!(2019-01-01 0:00).to_julian_day(), 2_458_485);
589    /// assert_eq!(utc_datetime!(2019-12-31 0:00).to_julian_day(), 2_458_849);
590    /// ```
591    pub const fn to_julian_day(self) -> i32 {
592        self.date().to_julian_day()
593    }
594
595    /// Get the clock hour, minute, and second.
596    ///
597    /// ```rust
598    /// # use time_macros::utc_datetime;
599    /// assert_eq!(utc_datetime!(2020-01-01 0:00:00).as_hms(), (0, 0, 0));
600    /// assert_eq!(utc_datetime!(2020-01-01 23:59:59).as_hms(), (23, 59, 59));
601    /// ```
602    pub const fn as_hms(self) -> (u8, u8, u8) {
603        self.time().as_hms()
604    }
605
606    /// Get the clock hour, minute, second, and millisecond.
607    ///
608    /// ```rust
609    /// # use time_macros::utc_datetime;
610    /// assert_eq!(utc_datetime!(2020-01-01 0:00:00).as_hms_milli(), (0, 0, 0, 0));
611    /// assert_eq!(
612    ///     utc_datetime!(2020-01-01 23:59:59.999).as_hms_milli(),
613    ///     (23, 59, 59, 999)
614    /// );
615    /// ```
616    pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) {
617        self.time().as_hms_milli()
618    }
619
620    /// Get the clock hour, minute, second, and microsecond.
621    ///
622    /// ```rust
623    /// # use time_macros::utc_datetime;
624    /// assert_eq!(utc_datetime!(2020-01-01 0:00:00).as_hms_micro(), (0, 0, 0, 0));
625    /// assert_eq!(
626    ///     utc_datetime!(2020-01-01 23:59:59.999_999).as_hms_micro(),
627    ///     (23, 59, 59, 999_999)
628    /// );
629    /// ```
630    pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) {
631        self.time().as_hms_micro()
632    }
633
634    /// Get the clock hour, minute, second, and nanosecond.
635    ///
636    /// ```rust
637    /// # use time_macros::utc_datetime;
638    /// assert_eq!(utc_datetime!(2020-01-01 0:00:00).as_hms_nano(), (0, 0, 0, 0));
639    /// assert_eq!(
640    ///     utc_datetime!(2020-01-01 23:59:59.999_999_999).as_hms_nano(),
641    ///     (23, 59, 59, 999_999_999)
642    /// );
643    /// ```
644    pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) {
645        self.time().as_hms_nano()
646    }
647
648    /// Get the clock hour.
649    ///
650    /// The returned value will always be in the range `0..24`.
651    ///
652    /// ```rust
653    /// # use time_macros::utc_datetime;
654    /// assert_eq!(utc_datetime!(2019-01-01 0:00).hour(), 0);
655    /// assert_eq!(utc_datetime!(2019-01-01 23:59:59).hour(), 23);
656    /// ```
657    pub const fn hour(self) -> u8 {
658        self.time().hour()
659    }
660
661    /// Get the minute within the hour.
662    ///
663    /// The returned value will always be in the range `0..60`.
664    ///
665    /// ```rust
666    /// # use time_macros::utc_datetime;
667    /// assert_eq!(utc_datetime!(2019-01-01 0:00).minute(), 0);
668    /// assert_eq!(utc_datetime!(2019-01-01 23:59:59).minute(), 59);
669    /// ```
670    pub const fn minute(self) -> u8 {
671        self.time().minute()
672    }
673
674    /// Get the second within the minute.
675    ///
676    /// The returned value will always be in the range `0..60`.
677    ///
678    /// ```rust
679    /// # use time_macros::utc_datetime;
680    /// assert_eq!(utc_datetime!(2019-01-01 0:00).second(), 0);
681    /// assert_eq!(utc_datetime!(2019-01-01 23:59:59).second(), 59);
682    /// ```
683    pub const fn second(self) -> u8 {
684        self.time().second()
685    }
686
687    /// Get the milliseconds within the second.
688    ///
689    /// The returned value will always be in the range `0..1_000`.
690    ///
691    /// ```rust
692    /// # use time_macros::utc_datetime;
693    /// assert_eq!(utc_datetime!(2019-01-01 0:00).millisecond(), 0);
694    /// assert_eq!(utc_datetime!(2019-01-01 23:59:59.999).millisecond(), 999);
695    /// ```
696    pub const fn millisecond(self) -> u16 {
697        self.time().millisecond()
698    }
699
700    /// Get the microseconds within the second.
701    ///
702    /// The returned value will always be in the range `0..1_000_000`.
703    ///
704    /// ```rust
705    /// # use time_macros::utc_datetime;
706    /// assert_eq!(utc_datetime!(2019-01-01 0:00).microsecond(), 0);
707    /// assert_eq!(
708    ///     utc_datetime!(2019-01-01 23:59:59.999_999).microsecond(),
709    ///     999_999
710    /// );
711    /// ```
712    pub const fn microsecond(self) -> u32 {
713        self.time().microsecond()
714    }
715
716    /// Get the nanoseconds within the second.
717    ///
718    /// The returned value will always be in the range `0..1_000_000_000`.
719    ///
720    /// ```rust
721    /// # use time_macros::utc_datetime;
722    /// assert_eq!(utc_datetime!(2019-01-01 0:00).nanosecond(), 0);
723    /// assert_eq!(
724    ///     utc_datetime!(2019-01-01 23:59:59.999_999_999).nanosecond(),
725    ///     999_999_999,
726    /// );
727    /// ```
728    pub const fn nanosecond(self) -> u32 {
729        self.time().nanosecond()
730    }
731
732    /// Computes `self + duration`, returning `None` if an overflow occurred.
733    ///
734    /// ```rust
735    /// # use time::{UtcDateTime, ext::NumericalDuration};
736    /// # use time_macros::utc_datetime;
737    /// assert_eq!(UtcDateTime::MIN.checked_add((-2).days()), None);
738    /// assert_eq!(UtcDateTime::MAX.checked_add(1.days()), None);
739    /// assert_eq!(
740    ///     utc_datetime!(2019 - 11 - 25 15:30).checked_add(27.hours()),
741    ///     Some(utc_datetime!(2019 - 11 - 26 18:30))
742    /// );
743    /// ```
744    pub const fn checked_add(self, duration: Duration) -> Option<Self> {
745        Some(Self::from_primitive(const_try_opt!(self
746            .inner
747            .checked_add(duration))))
748    }
749
750    /// Computes `self - duration`, returning `None` if an overflow occurred.
751    ///
752    /// ```rust
753    /// # use time::{UtcDateTime, ext::NumericalDuration};
754    /// # use time_macros::utc_datetime;
755    /// assert_eq!(UtcDateTime::MIN.checked_sub(2.days()), None);
756    /// assert_eq!(UtcDateTime::MAX.checked_sub((-1).days()), None);
757    /// assert_eq!(
758    ///     utc_datetime!(2019 - 11 - 25 15:30).checked_sub(27.hours()),
759    ///     Some(utc_datetime!(2019 - 11 - 24 12:30))
760    /// );
761    /// ```
762    pub const fn checked_sub(self, duration: Duration) -> Option<Self> {
763        Some(Self::from_primitive(const_try_opt!(self
764            .inner
765            .checked_sub(duration))))
766    }
767
768    /// Computes `self + duration`, saturating value on overflow.
769    ///
770    /// ```rust
771    /// # use time::{UtcDateTime, ext::NumericalDuration};
772    /// # use time_macros::utc_datetime;
773    /// assert_eq!(
774    ///     UtcDateTime::MIN.saturating_add((-2).days()),
775    ///     UtcDateTime::MIN
776    /// );
777    /// assert_eq!(
778    ///     UtcDateTime::MAX.saturating_add(2.days()),
779    ///     UtcDateTime::MAX
780    /// );
781    /// assert_eq!(
782    ///     utc_datetime!(2019 - 11 - 25 15:30).saturating_add(27.hours()),
783    ///     utc_datetime!(2019 - 11 - 26 18:30)
784    /// );
785    /// ```
786    pub const fn saturating_add(self, duration: Duration) -> Self {
787        Self::from_primitive(self.inner.saturating_add(duration))
788    }
789
790    /// Computes `self - duration`, saturating value on overflow.
791    ///
792    /// ```rust
793    /// # use time::{UtcDateTime, ext::NumericalDuration};
794    /// # use time_macros::utc_datetime;
795    /// assert_eq!(
796    ///     UtcDateTime::MIN.saturating_sub(2.days()),
797    ///     UtcDateTime::MIN
798    /// );
799    /// assert_eq!(
800    ///     UtcDateTime::MAX.saturating_sub((-2).days()),
801    ///     UtcDateTime::MAX
802    /// );
803    /// assert_eq!(
804    ///     utc_datetime!(2019 - 11 - 25 15:30).saturating_sub(27.hours()),
805    ///     utc_datetime!(2019 - 11 - 24 12:30)
806    /// );
807    /// ```
808    pub const fn saturating_sub(self, duration: Duration) -> Self {
809        Self::from_primitive(self.inner.saturating_sub(duration))
810    }
811}
812
813/// Methods that replace part of the `UtcDateTime`.
814impl UtcDateTime {
815    /// Replace the time, preserving the date.
816    ///
817    /// ```rust
818    /// # use time_macros::{utc_datetime, time};
819    /// assert_eq!(
820    ///     utc_datetime!(2020-01-01 17:00).replace_time(time!(5:00)),
821    ///     utc_datetime!(2020-01-01 5:00)
822    /// );
823    /// ```
824    #[must_use = "This method does not mutate the original `UtcDateTime`."]
825    pub const fn replace_time(self, time: Time) -> Self {
826        Self::from_primitive(self.inner.replace_time(time))
827    }
828
829    /// Replace the date, preserving the time.
830    ///
831    /// ```rust
832    /// # use time_macros::{utc_datetime, date};
833    /// assert_eq!(
834    ///     utc_datetime!(2020-01-01 12:00).replace_date(date!(2020-01-30)),
835    ///     utc_datetime!(2020-01-30 12:00)
836    /// );
837    /// ```
838    #[must_use = "This method does not mutate the original `UtcDateTime`."]
839    pub const fn replace_date(self, date: Date) -> Self {
840        Self::from_primitive(self.inner.replace_date(date))
841    }
842
843    /// Replace the year. The month and day will be unchanged.
844    ///
845    /// ```rust
846    /// # use time_macros::utc_datetime;
847    /// assert_eq!(
848    ///     utc_datetime!(2022 - 02 - 18 12:00).replace_year(2019),
849    ///     Ok(utc_datetime!(2019 - 02 - 18 12:00))
850    /// );
851    /// assert!(utc_datetime!(2022 - 02 - 18 12:00).replace_year(-1_000_000_000).is_err()); // -1_000_000_000 isn't a valid year
852    /// assert!(utc_datetime!(2022 - 02 - 18 12:00).replace_year(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid year
853    /// ```
854    #[must_use = "This method does not mutate the original `UtcDateTime`."]
855    pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
856        Ok(Self::from_primitive(const_try!(self
857            .inner
858            .replace_year(year))))
859    }
860
861    /// Replace the month of the year.
862    ///
863    /// ```rust
864    /// # use time_macros::utc_datetime;
865    /// # use time::Month;
866    /// assert_eq!(
867    ///     utc_datetime!(2022 - 02 - 18 12:00).replace_month(Month::January),
868    ///     Ok(utc_datetime!(2022 - 01 - 18 12:00))
869    /// );
870    /// assert!(utc_datetime!(2022 - 01 - 30 12:00).replace_month(Month::February).is_err()); // 30 isn't a valid day in February
871    /// ```
872    #[must_use = "This method does not mutate the original `UtcDateTime`."]
873    pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
874        Ok(Self::from_primitive(const_try!(self
875            .inner
876            .replace_month(month))))
877    }
878
879    /// Replace the day of the month.
880    ///
881    /// ```rust
882    /// # use time_macros::utc_datetime;
883    /// assert_eq!(
884    ///     utc_datetime!(2022 - 02 - 18 12:00).replace_day(1),
885    ///     Ok(utc_datetime!(2022 - 02 - 01 12:00))
886    /// );
887    /// assert!(utc_datetime!(2022 - 02 - 18 12:00).replace_day(0).is_err()); // 00 isn't a valid day
888    /// assert!(utc_datetime!(2022 - 02 - 18 12:00).replace_day(30).is_err()); // 30 isn't a valid day in February
889    /// ```
890    #[must_use = "This method does not mutate the original `UtcDateTime`."]
891    pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
892        Ok(Self::from_primitive(const_try!(self
893            .inner
894            .replace_day(day))))
895    }
896
897    /// Replace the day of the year.
898    ///
899    /// ```rust
900    /// # use time_macros::utc_datetime;
901    /// assert_eq!(utc_datetime!(2022-049 12:00).replace_ordinal(1), Ok(utc_datetime!(2022-001 12:00)));
902    /// assert!(utc_datetime!(2022-049 12:00).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
903    /// assert!(utc_datetime!(2022-049 12:00).replace_ordinal(366).is_err()); // 2022 isn't a leap year
904    /// ```
905    #[must_use = "This method does not mutate the original `UtcDateTime`."]
906    pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
907        Ok(Self::from_primitive(const_try!(self
908            .inner
909            .replace_ordinal(ordinal))))
910    }
911
912    /// Replace the clock hour.
913    ///
914    /// ```rust
915    /// # use time_macros::utc_datetime;
916    /// assert_eq!(
917    ///     utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_hour(7),
918    ///     Ok(utc_datetime!(2022 - 02 - 18 07:02:03.004_005_006))
919    /// );
920    /// assert!(utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_hour(24).is_err()); // 24 isn't a valid hour
921    /// ```
922    #[must_use = "This method does not mutate the original `UtcDateTime`."]
923    pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
924        Ok(Self::from_primitive(const_try!(self
925            .inner
926            .replace_hour(hour))))
927    }
928
929    /// Replace the minutes within the hour.
930    ///
931    /// ```rust
932    /// # use time_macros::utc_datetime;
933    /// assert_eq!(
934    ///     utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_minute(7),
935    ///     Ok(utc_datetime!(2022 - 02 - 18 01:07:03.004_005_006))
936    /// );
937    /// assert!(utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_minute(60).is_err()); // 60 isn't a valid minute
938    /// ```
939    #[must_use = "This method does not mutate the original `UtcDateTime`."]
940    pub const fn replace_minute(
941        self,
942        sunday_based_week: u8,
943    ) -> Result<Self, error::ComponentRange> {
944        Ok(Self::from_primitive(const_try!(self
945            .inner
946            .replace_minute(sunday_based_week))))
947    }
948
949    /// Replace the seconds within the minute.
950    ///
951    /// ```rust
952    /// # use time_macros::utc_datetime;
953    /// assert_eq!(
954    ///     utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_second(7),
955    ///     Ok(utc_datetime!(2022 - 02 - 18 01:02:07.004_005_006))
956    /// );
957    /// assert!(utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_second(60).is_err()); // 60 isn't a valid second
958    /// ```
959    #[must_use = "This method does not mutate the original `UtcDateTime`."]
960    pub const fn replace_second(
961        self,
962        monday_based_week: u8,
963    ) -> Result<Self, error::ComponentRange> {
964        Ok(Self::from_primitive(const_try!(self
965            .inner
966            .replace_second(monday_based_week))))
967    }
968
969    /// Replace the milliseconds within the second.
970    ///
971    /// ```rust
972    /// # use time_macros::utc_datetime;
973    /// assert_eq!(
974    ///     utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_millisecond(7),
975    ///     Ok(utc_datetime!(2022 - 02 - 18 01:02:03.007))
976    /// );
977    /// assert!(utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_millisecond(1_000).is_err()); // 1_000 isn't a valid millisecond
978    /// ```
979    #[must_use = "This method does not mutate the original `UtcDateTime`."]
980    pub const fn replace_millisecond(
981        self,
982        millisecond: u16,
983    ) -> Result<Self, error::ComponentRange> {
984        Ok(Self::from_primitive(const_try!(self
985            .inner
986            .replace_millisecond(millisecond))))
987    }
988
989    /// Replace the microseconds within the second.
990    ///
991    /// ```rust
992    /// # use time_macros::utc_datetime;
993    /// assert_eq!(
994    ///     utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_microsecond(7_008),
995    ///     Ok(utc_datetime!(2022 - 02 - 18 01:02:03.007_008))
996    /// );
997    /// assert!(utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_microsecond(1_000_000).is_err()); // 1_000_000 isn't a valid microsecond
998    /// ```
999    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1000    pub const fn replace_microsecond(
1001        self,
1002        microsecond: u32,
1003    ) -> Result<Self, error::ComponentRange> {
1004        Ok(Self::from_primitive(const_try!(self
1005            .inner
1006            .replace_microsecond(microsecond))))
1007    }
1008
1009    /// Replace the nanoseconds within the second.
1010    ///
1011    /// ```rust
1012    /// # use time_macros::utc_datetime;
1013    /// assert_eq!(
1014    ///     utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_nanosecond(7_008_009),
1015    ///     Ok(utc_datetime!(2022 - 02 - 18 01:02:03.007_008_009))
1016    /// );
1017    /// assert!(utc_datetime!(2022 - 02 - 18 01:02:03.004_005_006).replace_nanosecond(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid nanosecond
1018    /// ```
1019    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1020    pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
1021        Ok(Self::from_primitive(const_try!(self
1022            .inner
1023            .replace_nanosecond(nanosecond))))
1024    }
1025}
1026
1027#[cfg(feature = "formatting")]
1028impl UtcDateTime {
1029    /// Format the `UtcDateTime` using the provided [format
1030    /// description](crate::format_description).
1031    pub fn format_into(
1032        self,
1033        output: &mut (impl io::Write + ?Sized),
1034        format: &(impl Formattable + ?Sized),
1035    ) -> Result<usize, error::Format> {
1036        format.format_into(
1037            output,
1038            Some(self.date()),
1039            Some(self.time()),
1040            Some(UtcOffset::UTC),
1041        )
1042    }
1043
1044    /// Format the `UtcDateTime` using the provided [format
1045    /// description](crate::format_description).
1046    ///
1047    /// ```rust
1048    /// # use time::format_description;
1049    /// # use time_macros::utc_datetime;
1050    /// let format = format_description::parse(
1051    ///     "[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour \
1052    ///          sign:mandatory]:[offset_minute]:[offset_second]",
1053    /// )?;
1054    /// assert_eq!(
1055    ///     utc_datetime!(2020-01-02 03:04:05).format(&format)?,
1056    ///     "2020-01-02 03:04:05 +00:00:00"
1057    /// );
1058    /// # Ok::<_, time::Error>(())
1059    /// ```
1060    pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
1061        format.format(Some(self.date()), Some(self.time()), Some(UtcOffset::UTC))
1062    }
1063}
1064
1065#[cfg(feature = "parsing")]
1066impl UtcDateTime {
1067    /// Parse an `UtcDateTime` from the input using the provided [format
1068    /// description](crate::format_description). A [`UtcOffset`] is permitted, but not required to
1069    /// be present. If present, the value will be converted to UTC.
1070    ///
1071    /// ```rust
1072    /// # use time::UtcDateTime;
1073    /// # use time_macros::{utc_datetime, format_description};
1074    /// let format = format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
1075    /// assert_eq!(
1076    ///     UtcDateTime::parse("2020-01-02 03:04:05", &format)?,
1077    ///     utc_datetime!(2020-01-02 03:04:05)
1078    /// );
1079    /// # Ok::<_, time::Error>(())
1080    /// ```
1081    pub fn parse(
1082        input: &str,
1083        description: &(impl Parsable + ?Sized),
1084    ) -> Result<Self, error::Parse> {
1085        description.parse_utc_date_time(input.as_bytes())
1086    }
1087
1088    /// A helper method to check if the `UtcDateTime` is a valid representation of a leap second.
1089    /// Leap seconds, when parsed, are represented as the preceding nanosecond. However, leap
1090    /// seconds can only occur as the last second of a month UTC.
1091    #[cfg(feature = "parsing")]
1092    pub(crate) const fn is_valid_leap_second_stand_in(self) -> bool {
1093        let dt = self.inner;
1094
1095        dt.hour() == 23
1096            && dt.minute() == 59
1097            && dt.second() == 59
1098            && dt.nanosecond() == 999_999_999
1099            && dt.day() == dt.month().length(dt.year())
1100    }
1101}
1102
1103impl SmartDisplay for UtcDateTime {
1104    type Metadata = ();
1105
1106    fn metadata(&self, _: FormatterOptions) -> Metadata<Self> {
1107        let width = smart_display::padded_width_of!(self.date(), " ", self.time(), " +00");
1108        Metadata::new(width, self, ())
1109    }
1110
1111    fn fmt_with_metadata(
1112        &self,
1113        f: &mut fmt::Formatter<'_>,
1114        metadata: Metadata<Self>,
1115    ) -> fmt::Result {
1116        f.pad_with_width(
1117            metadata.unpadded_width(),
1118            format_args!("{} {} +00", self.date(), self.time()),
1119        )
1120    }
1121}
1122
1123impl fmt::Display for UtcDateTime {
1124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1125        SmartDisplay::fmt(self, f)
1126    }
1127}
1128
1129impl fmt::Debug for UtcDateTime {
1130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1131        fmt::Display::fmt(self, f)
1132    }
1133}
1134
1135impl Add<Duration> for UtcDateTime {
1136    type Output = Self;
1137
1138    /// # Panics
1139    ///
1140    /// This may panic if an overflow occurs.
1141    fn add(self, duration: Duration) -> Self::Output {
1142        self.inner.add(duration).as_utc()
1143    }
1144}
1145
1146impl Add<StdDuration> for UtcDateTime {
1147    type Output = Self;
1148
1149    /// # Panics
1150    ///
1151    /// This may panic if an overflow occurs.
1152    fn add(self, duration: StdDuration) -> Self::Output {
1153        self.inner.add(duration).as_utc()
1154    }
1155}
1156
1157impl AddAssign<Duration> for UtcDateTime {
1158    /// # Panics
1159    ///
1160    /// This may panic if an overflow occurs.
1161    fn add_assign(&mut self, rhs: Duration) {
1162        self.inner.add_assign(rhs);
1163    }
1164}
1165
1166impl AddAssign<StdDuration> for UtcDateTime {
1167    /// # Panics
1168    ///
1169    /// This may panic if an overflow occurs.
1170    fn add_assign(&mut self, rhs: StdDuration) {
1171        self.inner.add_assign(rhs);
1172    }
1173}
1174
1175impl Sub<Duration> for UtcDateTime {
1176    type Output = Self;
1177
1178    /// # Panics
1179    ///
1180    /// This may panic if an overflow occurs.
1181    fn sub(self, rhs: Duration) -> Self::Output {
1182        self.checked_sub(rhs)
1183            .expect("resulting value is out of range")
1184    }
1185}
1186
1187impl Sub<StdDuration> for UtcDateTime {
1188    type Output = Self;
1189
1190    /// # Panics
1191    ///
1192    /// This may panic if an overflow occurs.
1193    fn sub(self, duration: StdDuration) -> Self::Output {
1194        Self::from_primitive(self.inner.sub(duration))
1195    }
1196}
1197
1198impl SubAssign<Duration> for UtcDateTime {
1199    /// # Panics
1200    ///
1201    /// This may panic if an overflow occurs.
1202    fn sub_assign(&mut self, rhs: Duration) {
1203        self.inner.sub_assign(rhs);
1204    }
1205}
1206
1207impl SubAssign<StdDuration> for UtcDateTime {
1208    /// # Panics
1209    ///
1210    /// This may panic if an overflow occurs.
1211    fn sub_assign(&mut self, rhs: StdDuration) {
1212        self.inner.sub_assign(rhs);
1213    }
1214}
1215
1216impl Sub for UtcDateTime {
1217    type Output = Duration;
1218
1219    /// # Panics
1220    ///
1221    /// This may panic if an overflow occurs.
1222    fn sub(self, rhs: Self) -> Self::Output {
1223        self.inner.sub(rhs.inner)
1224    }
1225}