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, Month, OffsetDateTime, PlainDateTime, SignedDuration, 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 [`PlainDateTime`] that is known to be UTC.
34///
35/// `UtcDateTime` is guaranteed to be ABI-compatible with [`PlainDateTime`], 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: PlainDateTime,
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: PlainDateTime::new(date, time),
151        }
152    }
153
154    /// Create a new `UtcDateTime` from the [`PlainDateTime`], assuming that the latter is UTC.
155    #[inline]
156    pub(crate) const fn from_plain(date_time: PlainDateTime) -> Self {
157        Self { inner: date_time }
158    }
159
160    /// Obtain the [`PlainDateTime`] that this `UtcDateTime` represents. The no-longer-attached
161    /// [`UtcOffset`] is assumed to be UTC.
162    #[inline]
163    pub(crate) const fn as_plain(self) -> PlainDateTime {
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::{SignedDuration, UtcDateTime, ext::NumericalDuration};
187    /// let (timestamp, nanos) = (1, 500_000_000);
188    /// assert_eq!(
189    ///     UtcDateTime::from_unix_timestamp(timestamp)? + SignedDuration::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: SignedDuration) -> Option<Self> {
780        Some(Self::from_plain(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: SignedDuration) -> Option<Self> {
799        Some(Self::from_plain(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: SignedDuration) -> Self {
824        Self::from_plain(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: SignedDuration) -> Self {
847        Self::from_plain(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_plain(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_plain(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_plain(const_try!(self.inner.replace_year(year))))
898    }
899
900    /// Replace the month of the year.
901    ///
902    /// ```rust
903    /// # use time_macros::utc_datetime;
904    /// # use time::Month;
905    /// assert_eq!(
906    ///     utc_datetime!(2022-02-18 12:00).replace_month(Month::January),
907    ///     Ok(utc_datetime!(2022-01-18 12:00))
908    /// );
909    /// assert!(utc_datetime!(2022-01-30 12:00).replace_month(Month::February).is_err()); // 30 isn't a valid day in February
910    /// ```
911    #[must_use = "This method does not mutate the original `UtcDateTime`."]
912    #[inline]
913    pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
914        Ok(Self::from_plain(const_try!(
915            self.inner.replace_month(month)
916        )))
917    }
918
919    /// Replace the day of the month.
920    ///
921    /// ```rust
922    /// # use time_macros::utc_datetime;
923    /// assert_eq!(
924    ///     utc_datetime!(2022-02-18 12:00).replace_day(1),
925    ///     Ok(utc_datetime!(2022-02-01 12:00))
926    /// );
927    /// assert!(utc_datetime!(2022-02-18 12:00).replace_day(0).is_err()); // 00 isn't a valid day
928    /// assert!(utc_datetime!(2022-02-18 12:00).replace_day(30).is_err()); // 30 isn't a valid day in February
929    /// ```
930    #[must_use = "This method does not mutate the original `UtcDateTime`."]
931    #[inline]
932    pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
933        Ok(Self::from_plain(const_try!(self.inner.replace_day(day))))
934    }
935
936    /// Replace the day of the year.
937    ///
938    /// ```rust
939    /// # use time_macros::utc_datetime;
940    /// assert_eq!(utc_datetime!(2022-049 12:00).replace_ordinal(1), Ok(utc_datetime!(2022-001 12:00)));
941    /// assert!(utc_datetime!(2022-049 12:00).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
942    /// assert!(utc_datetime!(2022-049 12:00).replace_ordinal(366).is_err()); // 2022 isn't a leap year
943    /// ```
944    #[must_use = "This method does not mutate the original `UtcDateTime`."]
945    #[inline]
946    pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
947        Ok(Self::from_plain(const_try!(
948            self.inner.replace_ordinal(ordinal)
949        )))
950    }
951
952    /// Truncate to the start of the day, setting the time to midnight.
953    ///
954    /// ```rust
955    /// # use time_macros::utc_datetime;
956    /// assert_eq!(
957    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_day(),
958    ///     utc_datetime!(2022-02-18 0:00)
959    /// );
960    /// ```
961    #[must_use = "This method does not mutate the original `UtcDateTime`."]
962    #[inline]
963    pub const fn truncate_to_day(self) -> Self {
964        Self::from_plain(self.inner.truncate_to_day())
965    }
966
967    /// Replace the clock hour.
968    ///
969    /// ```rust
970    /// # use time_macros::utc_datetime;
971    /// assert_eq!(
972    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_hour(7),
973    ///     Ok(utc_datetime!(2022-02-18 07:02:03.004_005_006))
974    /// );
975    /// assert!(utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_hour(24).is_err()); // 24 isn't a valid hour
976    /// ```
977    #[must_use = "This method does not mutate the original `UtcDateTime`."]
978    #[inline]
979    pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
980        Ok(Self::from_plain(const_try!(self.inner.replace_hour(hour))))
981    }
982
983    /// Truncate to the hour, setting the minute, second, and subsecond components to zero.
984    ///
985    /// ```rust
986    /// # use time_macros::utc_datetime;
987    /// assert_eq!(
988    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_hour(),
989    ///     utc_datetime!(2022-02-18 15:00)
990    /// );
991    /// ```
992    #[must_use = "This method does not mutate the original `UtcDateTime`."]
993    #[inline]
994    pub const fn truncate_to_hour(self) -> Self {
995        Self::from_plain(self.inner.truncate_to_hour())
996    }
997
998    /// Replace the minutes within the hour.
999    ///
1000    /// ```rust
1001    /// # use time_macros::utc_datetime;
1002    /// assert_eq!(
1003    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_minute(7),
1004    ///     Ok(utc_datetime!(2022-02-18 01:07:03.004_005_006))
1005    /// );
1006    /// assert!(utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_minute(60).is_err()); // 60 isn't a valid minute
1007    /// ```
1008    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1009    #[inline]
1010    pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
1011        Ok(Self::from_plain(const_try!(
1012            self.inner.replace_minute(minute)
1013        )))
1014    }
1015
1016    /// Truncate to the minute, setting the second and subsecond components to zero.
1017    ///
1018    /// ```rust
1019    /// # use time_macros::utc_datetime;
1020    /// assert_eq!(
1021    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_minute(),
1022    ///     utc_datetime!(2022-02-18 15:30)
1023    /// );
1024    /// ```
1025    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1026    #[inline]
1027    pub const fn truncate_to_minute(self) -> Self {
1028        Self::from_plain(self.inner.truncate_to_minute())
1029    }
1030
1031    /// Replace the seconds within the minute.
1032    ///
1033    /// ```rust
1034    /// # use time_macros::utc_datetime;
1035    /// assert_eq!(
1036    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_second(7),
1037    ///     Ok(utc_datetime!(2022-02-18 01:02:07.004_005_006))
1038    /// );
1039    /// assert!(utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_second(60).is_err()); // 60 isn't a valid second
1040    /// ```
1041    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1042    #[inline]
1043    pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
1044        Ok(Self::from_plain(const_try!(
1045            self.inner.replace_second(second)
1046        )))
1047    }
1048
1049    /// Truncate to the second, setting the subsecond components to zero.
1050    ///
1051    /// ```rust
1052    /// # use time_macros::utc_datetime;
1053    /// assert_eq!(
1054    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_second(),
1055    ///     utc_datetime!(2022-02-18 15:30:45)
1056    /// );
1057    /// ```
1058    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1059    #[inline]
1060    pub const fn truncate_to_second(self) -> Self {
1061        Self::from_plain(self.inner.truncate_to_second())
1062    }
1063
1064    /// Replace the milliseconds within the second.
1065    ///
1066    /// ```rust
1067    /// # use time_macros::utc_datetime;
1068    /// assert_eq!(
1069    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_millisecond(7),
1070    ///     Ok(utc_datetime!(2022-02-18 01:02:03.007))
1071    /// );
1072    /// 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
1073    /// ```
1074    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1075    #[inline]
1076    pub const fn replace_millisecond(
1077        self,
1078        millisecond: u16,
1079    ) -> Result<Self, error::ComponentRange> {
1080        Ok(Self::from_plain(const_try!(
1081            self.inner.replace_millisecond(millisecond)
1082        )))
1083    }
1084
1085    /// Truncate to the millisecond, setting the microsecond and nanosecond components to zero.
1086    ///
1087    /// ```rust
1088    /// # use time_macros::utc_datetime;
1089    /// assert_eq!(
1090    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_millisecond(),
1091    ///     utc_datetime!(2022-02-18 15:30:45.123)
1092    /// );
1093    /// ```
1094    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1095    #[inline]
1096    pub const fn truncate_to_millisecond(self) -> Self {
1097        Self::from_plain(self.inner.truncate_to_millisecond())
1098    }
1099
1100    /// Replace the microseconds within the second.
1101    ///
1102    /// ```rust
1103    /// # use time_macros::utc_datetime;
1104    /// assert_eq!(
1105    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_microsecond(7_008),
1106    ///     Ok(utc_datetime!(2022-02-18 01:02:03.007_008))
1107    /// );
1108    /// 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
1109    /// ```
1110    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1111    #[inline]
1112    pub const fn replace_microsecond(
1113        self,
1114        microsecond: u32,
1115    ) -> Result<Self, error::ComponentRange> {
1116        Ok(Self::from_plain(const_try!(
1117            self.inner.replace_microsecond(microsecond)
1118        )))
1119    }
1120
1121    /// Truncate to the microsecond, setting the nanosecond component to zero.
1122    ///
1123    /// ```rust
1124    /// # use time_macros::utc_datetime;
1125    /// assert_eq!(
1126    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_microsecond(),
1127    ///     utc_datetime!(2022-02-18 15:30:45.123_456)
1128    /// );
1129    /// ```
1130    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1131    #[inline]
1132    pub const fn truncate_to_microsecond(self) -> Self {
1133        Self::from_plain(self.inner.truncate_to_microsecond())
1134    }
1135
1136    /// Replace the nanoseconds within the second.
1137    ///
1138    /// ```rust
1139    /// # use time_macros::utc_datetime;
1140    /// assert_eq!(
1141    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_nanosecond(7_008_009),
1142    ///     Ok(utc_datetime!(2022-02-18 01:02:03.007_008_009))
1143    /// );
1144    /// 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
1145    /// ```
1146    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1147    #[inline]
1148    pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
1149        Ok(Self::from_plain(const_try!(
1150            self.inner.replace_nanosecond(nanosecond)
1151        )))
1152    }
1153}
1154
1155#[cfg(feature = "formatting")]
1156impl UtcDateTime {
1157    /// Format the `UtcDateTime` using the provided [format
1158    /// description](crate::format_description).
1159    #[inline]
1160    pub fn format_into(
1161        self,
1162        output: &mut (impl io::Write + ?Sized),
1163        format: &(impl Formattable + ?Sized),
1164    ) -> Result<usize, error::Format> {
1165        format.format_into(output, &self, &mut Default::default(), PrivateMethod)
1166    }
1167
1168    /// Format the `UtcDateTime` using the provided [format
1169    /// description](crate::format_description).
1170    ///
1171    /// ```rust
1172    /// # use time::format_description;
1173    /// # use time_macros::utc_datetime;
1174    /// let format = format_description::parse_borrowed::<3>(
1175    ///     "[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour \
1176    ///          sign:mandatory]:[offset_minute]:[offset_second]",
1177    /// )?;
1178    /// assert_eq!(
1179    ///     utc_datetime!(2020-01-02 03:04:05).format(&format)?,
1180    ///     "2020-01-02 03:04:05 +00:00:00"
1181    /// );
1182    /// # Ok::<_, time::Error>(())
1183    /// ```
1184    #[inline]
1185    pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
1186        format.format(&self, &mut Default::default(), PrivateMethod)
1187    }
1188}
1189
1190#[cfg(feature = "parsing")]
1191impl UtcDateTime {
1192    /// Parse an `UtcDateTime` from the input using the provided [format
1193    /// description](crate::format_description). A [`UtcOffset`] is permitted, but not required to
1194    /// be present. If present, the value will be converted to UTC.
1195    ///
1196    /// ```rust
1197    /// # use time::UtcDateTime;
1198    /// # use time_macros::{utc_datetime, format_description};
1199    /// let format = format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
1200    /// assert_eq!(
1201    ///     UtcDateTime::parse("2020-01-02 03:04:05", &format)?,
1202    ///     utc_datetime!(2020-01-02 03:04:05)
1203    /// );
1204    /// # Ok::<_, time::Error>(())
1205    /// ```
1206    #[inline]
1207    pub fn parse(
1208        input: &str,
1209        description: &(impl Parsable + ?Sized),
1210    ) -> Result<Self, error::Parse> {
1211        description.parse_utc_date_time(input.as_bytes(), None, PrivateMethod)
1212    }
1213
1214    /// Parse a `UtcDateTime` from the input using the provided [format
1215    /// description](crate::format_description) and default values.
1216    ///
1217    /// ```rust
1218    /// # use time::UtcDateTime;
1219    /// # use time::parsing::Parsed;
1220    /// # use time_macros::{utc_datetime, format_description};
1221    /// let format = format_description!("[year]-[month]-[day]");
1222    /// let defaults = Parsed::new().with_hour_24(12).expect("12 is a valid hour");
1223    /// assert_eq!(
1224    ///     UtcDateTime::parse_with_defaults(b"2020-01-02", &format, defaults)?,
1225    ///     utc_datetime!(2020-01-02 12:00)
1226    /// );
1227    /// # Ok::<_, time::Error>(())
1228    /// ```
1229    #[inline]
1230    pub fn parse_with_defaults(
1231        input: &[u8],
1232        description: &(impl Parsable + ?Sized),
1233        defaults: Parsed,
1234    ) -> Result<Self, error::Parse> {
1235        description.parse_utc_date_time(input, Some(defaults), PrivateMethod)
1236    }
1237
1238    /// A helper method to check if the `UtcDateTime` is a valid representation of a leap second.
1239    /// Leap seconds, when parsed, are represented as the preceding nanosecond. However, leap
1240    /// seconds can only occur as the last second of a month UTC.
1241    #[cfg(feature = "parsing")]
1242    #[inline]
1243    pub(crate) const fn is_valid_leap_second_stand_in(self) -> bool {
1244        let dt = self.inner;
1245
1246        dt.hour() == 23
1247            && dt.minute() == 59
1248            && dt.second() == 59
1249            && dt.nanosecond() == 999_999_999
1250            && dt.day() == dt.month().length(dt.year())
1251    }
1252}
1253
1254// This no longer needs special handling, as the format is fixed and doesn't require anything
1255// advanced. Trait impls can't be deprecated and the info is still useful for other types
1256// implementing `SmartDisplay`, so leave it as-is for now.
1257impl SmartDisplay for UtcDateTime {
1258    type Metadata = ();
1259
1260    #[inline]
1261    fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
1262        let width = self.as_plain().metadata(f).unpadded_width() + 4;
1263        Metadata::new(width, self, ())
1264    }
1265
1266    #[inline]
1267    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1268        fmt::Display::fmt(self, f)
1269    }
1270}
1271
1272impl UtcDateTime {
1273    /// The maximum number of bytes that the `fmt_into_buffer` method will write, which is also used
1274    /// for the `Display` implementation.
1275    pub(crate) const DISPLAY_BUFFER_SIZE: usize = PlainDateTime::DISPLAY_BUFFER_SIZE + 4;
1276
1277    /// Format the `PlainDateTime` into the provided buffer, returning the number of bytes written.
1278    #[inline]
1279    pub(crate) fn fmt_into_buffer(
1280        self,
1281        buf: &mut [MaybeUninit<u8>; Self::DISPLAY_BUFFER_SIZE],
1282    ) -> usize {
1283        // Safety: The buffer is large enough that the first chunk is in bounds.
1284        let pdt_len = self
1285            .inner
1286            .fmt_into_buffer(unsafe { buf.first_chunk_mut().unwrap_unchecked() });
1287        // Safety: The buffer is large enough to hold the additional 4 bytes.
1288        unsafe {
1289            b" +00"
1290                .as_ptr()
1291                .copy_to_nonoverlapping(buf.as_mut_ptr().add(pdt_len).cast(), 4)
1292        };
1293        pdt_len + 4
1294    }
1295}
1296
1297impl fmt::Display for UtcDateTime {
1298    #[inline]
1299    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1300        let mut buf = [MaybeUninit::uninit(); Self::DISPLAY_BUFFER_SIZE];
1301        let len = self.fmt_into_buffer(&mut buf);
1302        // Safety: All bytes up to `len` have been initialized with ASCII characters.
1303        let s = unsafe { str_from_raw_parts(buf.as_ptr().cast(), len) };
1304        f.pad(s)
1305    }
1306}
1307
1308impl fmt::Debug for UtcDateTime {
1309    #[inline]
1310    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1311        fmt::Display::fmt(self, f)
1312    }
1313}
1314
1315impl Add<SignedDuration> for UtcDateTime {
1316    type Output = Self;
1317
1318    /// # Panics
1319    ///
1320    /// This may panic if an overflow occurs.
1321    #[inline]
1322    #[track_caller]
1323    fn add(self, duration: SignedDuration) -> Self::Output {
1324        self.inner.add(duration).as_utc()
1325    }
1326}
1327
1328impl Add<StdDuration> 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 add(self, duration: StdDuration) -> Self::Output {
1337        self.inner.add(duration).as_utc()
1338    }
1339}
1340
1341impl AddAssign<SignedDuration> for UtcDateTime {
1342    /// # Panics
1343    ///
1344    /// This may panic if an overflow occurs.
1345    #[inline]
1346    #[track_caller]
1347    fn add_assign(&mut self, rhs: SignedDuration) {
1348        self.inner.add_assign(rhs);
1349    }
1350}
1351
1352impl AddAssign<StdDuration> for UtcDateTime {
1353    /// # Panics
1354    ///
1355    /// This may panic if an overflow occurs.
1356    #[inline]
1357    #[track_caller]
1358    fn add_assign(&mut self, rhs: StdDuration) {
1359        self.inner.add_assign(rhs);
1360    }
1361}
1362
1363impl Sub<SignedDuration> for UtcDateTime {
1364    type Output = Self;
1365
1366    /// # Panics
1367    ///
1368    /// This may panic if an overflow occurs.
1369    #[inline]
1370    #[track_caller]
1371    fn sub(self, rhs: SignedDuration) -> Self::Output {
1372        self.checked_sub(rhs)
1373            .expect("resulting value is out of range")
1374    }
1375}
1376
1377impl Sub<StdDuration> for UtcDateTime {
1378    type Output = Self;
1379
1380    /// # Panics
1381    ///
1382    /// This may panic if an overflow occurs.
1383    #[inline]
1384    #[track_caller]
1385    fn sub(self, duration: StdDuration) -> Self::Output {
1386        Self::from_plain(self.inner.sub(duration))
1387    }
1388}
1389
1390impl SubAssign<SignedDuration> for UtcDateTime {
1391    /// # Panics
1392    ///
1393    /// This may panic if an overflow occurs.
1394    #[inline]
1395    #[track_caller]
1396    fn sub_assign(&mut self, rhs: SignedDuration) {
1397        self.inner.sub_assign(rhs);
1398    }
1399}
1400
1401impl SubAssign<StdDuration> for UtcDateTime {
1402    /// # Panics
1403    ///
1404    /// This may panic if an overflow occurs.
1405    #[inline]
1406    #[track_caller]
1407    fn sub_assign(&mut self, rhs: StdDuration) {
1408        self.inner.sub_assign(rhs);
1409    }
1410}
1411
1412impl Sub for UtcDateTime {
1413    type Output = SignedDuration;
1414
1415    #[inline]
1416    fn sub(self, rhs: Self) -> Self::Output {
1417        self.inner.sub(rhs.inner)
1418    }
1419}