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