Skip to main content

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