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