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 seconds = div_floor!(timestamp, Nanosecond::per_t::<i128>(Second));
240        if seconds < crate::timestamp::Seconds::MIN.get() as i128
241            || seconds > crate::timestamp::Seconds::MAX.get() as i128
242        {
243            return Err(error::ComponentRange::unconditional("timestamp"));
244        }
245
246        let Ok(datetime) = Self::from_unix_timestamp(seconds as i64) else {
247            // Safety: The range was just validated.
248            unsafe { core::hint::unreachable_unchecked() };
249        };
250
251        Ok(Self::new(
252            datetime.date(),
253            // Safety: `nanosecond` is in range due to `rem_euclid`.
254            unsafe {
255                Time::__from_hms_nanos_unchecked(
256                    datetime.hour(),
257                    datetime.minute(),
258                    datetime.second(),
259                    timestamp.rem_euclid(Nanosecond::per_t(Second)) as u32,
260                )
261            },
262        ))
263    }
264
265    /// Convert the `UtcDateTime` from UTC to the provided [`UtcOffset`], returning an
266    /// [`OffsetDateTime`].
267    ///
268    /// ```rust
269    /// # use time_macros::{utc_datetime, offset};
270    /// assert_eq!(
271    ///     utc_datetime!(2000-01-01 0:00)
272    ///         .to_offset(offset!(-1))
273    ///         .year(),
274    ///     1999,
275    /// );
276    ///
277    /// // Construct midnight on new year's, UTC.
278    /// let utc = utc_datetime!(2000-01-01 0:00);
279    /// let new_york = utc.to_offset(offset!(-5));
280    /// let los_angeles = utc.to_offset(offset!(-8));
281    /// assert_eq!(utc.hour(), 0);
282    /// assert_eq!(new_york.hour(), 19);
283    /// assert_eq!(los_angeles.hour(), 16);
284    /// ```
285    ///
286    /// # Panics
287    ///
288    /// This method panics if the local date-time in the new offset is outside the supported range.
289    #[inline]
290    #[track_caller]
291    pub const fn to_offset(self, offset: UtcOffset) -> OffsetDateTime {
292        self.checked_to_offset(offset)
293            .expect("local datetime out of valid range")
294    }
295
296    /// Convert the `UtcDateTime` from UTC to the provided [`UtcOffset`], returning an
297    /// [`OffsetDateTime`]. `None` is returned if the date-time in the resulting offset is
298    /// invalid.
299    ///
300    /// ```rust
301    /// # use time::UtcDateTime;
302    /// # use time_macros::{utc_datetime, offset};
303    /// assert_eq!(
304    ///     utc_datetime!(2000-01-01 0:00)
305    ///         .checked_to_offset(offset!(-1))
306    ///         .unwrap()
307    ///         .year(),
308    ///     1999,
309    /// );
310    /// assert_eq!(
311    ///     UtcDateTime::MAX.checked_to_offset(offset!(+1)),
312    ///     None,
313    /// );
314    /// ```
315    #[inline]
316    pub const fn checked_to_offset(self, offset: UtcOffset) -> Option<OffsetDateTime> {
317        // Fast path for when no conversion is necessary.
318        if offset.is_utc() {
319            return Some(self.inner.assume_utc());
320        }
321
322        let (year, ordinal, time) = self.to_offset_raw(offset);
323
324        if year > MAX_YEAR || year < MIN_YEAR {
325            return None;
326        }
327
328        Some(OffsetDateTime::new_in_offset(
329            // Safety: `ordinal` is not zero.
330            unsafe { Date::__from_ordinal_date_unchecked(year, ordinal) },
331            time,
332            offset,
333        ))
334    }
335
336    /// Equivalent to `.to_offset(offset)`, but returning the year, ordinal, and time. This avoids
337    /// constructing an invalid [`Date`] if the new value is out of range.
338    #[inline]
339    pub(crate) const fn to_offset_raw(self, offset: UtcOffset) -> (i32, u16, Time) {
340        let (second, carry) = carry!(@most_once
341            self.second().cast_signed() + offset.seconds_past_minute(),
342            0..Second::per_t(Minute)
343        );
344        let (minute, carry) = carry!(@most_once
345            self.minute().cast_signed() + offset.minutes_past_hour() + carry,
346            0..Minute::per_t(Hour)
347        );
348        let (hour, carry) = carry!(@most_twice
349            self.hour().cast_signed() + offset.whole_hours() + carry,
350            0..Hour::per_t(Day)
351        );
352        let (mut year, ordinal) = self.to_ordinal_date();
353        let mut ordinal = ordinal.cast_signed() + carry;
354        cascade!(ordinal => year);
355
356        debug_assert!(ordinal > 0);
357        debug_assert!(ordinal <= days_in_year(year).cast_signed());
358
359        (
360            year,
361            ordinal.cast_unsigned(),
362            // Safety: The cascades above ensure the values are in range.
363            unsafe {
364                Time::__from_hms_nanos_unchecked(
365                    hour.cast_unsigned(),
366                    minute.cast_unsigned(),
367                    second.cast_unsigned(),
368                    self.nanosecond(),
369                )
370            },
371        )
372    }
373
374    /// Get the [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time).
375    ///
376    /// ```rust
377    /// # use time_macros::utc_datetime;
378    /// assert_eq!(utc_datetime!(1970-01-01 0:00).unix_timestamp(), 0);
379    /// assert_eq!(utc_datetime!(1970-01-01 1:00).unix_timestamp(), 3_600);
380    /// ```
381    #[inline]
382    pub const fn unix_timestamp(self) -> i64 {
383        let days = (self.to_julian_day() as i64 - UNIX_EPOCH_JULIAN_DAY as i64)
384            * Second::per_t::<i64>(Day);
385        let hours = self.hour() as i64 * Second::per_t::<i64>(Hour);
386        let minutes = self.minute() as i64 * Second::per_t::<i64>(Minute);
387        let seconds = self.second() as i64;
388        days + hours + minutes + seconds
389    }
390
391    /// Get the Unix timestamp in nanoseconds.
392    ///
393    /// ```rust
394    /// use time_macros::utc_datetime;
395    /// assert_eq!(utc_datetime!(1970-01-01 0:00).unix_timestamp_nanos(), 0);
396    /// assert_eq!(
397    ///     utc_datetime!(1970-01-01 1:00).unix_timestamp_nanos(),
398    ///     3_600_000_000_000,
399    /// );
400    /// ```
401    #[inline]
402    pub const fn unix_timestamp_nanos(self) -> i128 {
403        self.unix_timestamp() as i128 * Nanosecond::per_t::<i128>(Second)
404            + self.nanosecond() as i128
405    }
406
407    /// Get the [`Date`] component of the `UtcDateTime`.
408    ///
409    /// ```rust
410    /// # use time_macros::{date, utc_datetime};
411    /// assert_eq!(utc_datetime!(2019-01-01 0:00).date(), date!(2019-01-01));
412    /// ```
413    #[inline]
414    pub const fn date(self) -> Date {
415        self.inner.date()
416    }
417
418    /// Get the [`Time`] component of the `UtcDateTime`.
419    ///
420    /// ```rust
421    /// # use time_macros::{utc_datetime, time};
422    /// assert_eq!(utc_datetime!(2019-01-01 0:00).time(), time!(0:00));
423    /// ```
424    #[inline]
425    pub const fn time(self) -> Time {
426        self.inner.time()
427    }
428
429    /// Get the year of the date.
430    ///
431    /// ```rust
432    /// # use time_macros::utc_datetime;
433    /// assert_eq!(utc_datetime!(2019-01-01 0:00).year(), 2019);
434    /// assert_eq!(utc_datetime!(2019-12-31 0:00).year(), 2019);
435    /// assert_eq!(utc_datetime!(2020-01-01 0:00).year(), 2020);
436    /// ```
437    #[inline]
438    pub const fn year(self) -> i32 {
439        self.date().year()
440    }
441
442    /// Get the month of the date.
443    ///
444    /// ```rust
445    /// # use time::Month;
446    /// # use time_macros::utc_datetime;
447    /// assert_eq!(utc_datetime!(2019-01-01 0:00).month(), Month::January);
448    /// assert_eq!(utc_datetime!(2019-12-31 0:00).month(), Month::December);
449    /// ```
450    #[inline]
451    pub const fn month(self) -> Month {
452        self.date().month()
453    }
454
455    /// Get the day of the date.
456    ///
457    /// The returned value will always be in the range `1..=31`.
458    ///
459    /// ```rust
460    /// # use time_macros::utc_datetime;
461    /// assert_eq!(utc_datetime!(2019-01-01 0:00).day(), 1);
462    /// assert_eq!(utc_datetime!(2019-12-31 0:00).day(), 31);
463    /// ```
464    #[inline]
465    pub const fn day(self) -> u8 {
466        self.date().day()
467    }
468
469    /// Get the day of the year.
470    ///
471    /// The returned value will always be in the range `1..=366` (`1..=365` for common years).
472    ///
473    /// ```rust
474    /// # use time_macros::utc_datetime;
475    /// assert_eq!(utc_datetime!(2019-01-01 0:00).ordinal(), 1);
476    /// assert_eq!(utc_datetime!(2019-12-31 0:00).ordinal(), 365);
477    /// ```
478    #[inline]
479    pub const fn ordinal(self) -> u16 {
480        self.date().ordinal()
481    }
482
483    /// Get the ISO week number.
484    ///
485    /// The returned value will always be in the range `1..=53`.
486    ///
487    /// ```rust
488    /// # use time_macros::utc_datetime;
489    /// assert_eq!(utc_datetime!(2019-01-01 0:00).iso_week(), 1);
490    /// assert_eq!(utc_datetime!(2019-10-04 0:00).iso_week(), 40);
491    /// assert_eq!(utc_datetime!(2020-01-01 0:00).iso_week(), 1);
492    /// assert_eq!(utc_datetime!(2020-12-31 0:00).iso_week(), 53);
493    /// assert_eq!(utc_datetime!(2021-01-01 0:00).iso_week(), 53);
494    /// ```
495    #[inline]
496    pub const fn iso_week(self) -> u8 {
497        self.date().iso_week()
498    }
499
500    /// Get the week number where week 1 begins on the first Sunday.
501    ///
502    /// The returned value will always be in the range `0..=53`.
503    ///
504    /// ```rust
505    /// # use time_macros::utc_datetime;
506    /// assert_eq!(utc_datetime!(2019-01-01 0:00).sunday_based_week(), 0);
507    /// assert_eq!(utc_datetime!(2020-01-01 0:00).sunday_based_week(), 0);
508    /// assert_eq!(utc_datetime!(2020-12-31 0:00).sunday_based_week(), 52);
509    /// assert_eq!(utc_datetime!(2021-01-01 0:00).sunday_based_week(), 0);
510    /// ```
511    #[inline]
512    pub const fn sunday_based_week(self) -> u8 {
513        self.date().sunday_based_week()
514    }
515
516    /// Get the week number where week 1 begins on the first Monday.
517    ///
518    /// The returned value will always be in the range `0..=53`.
519    ///
520    /// ```rust
521    /// # use time_macros::utc_datetime;
522    /// assert_eq!(utc_datetime!(2019-01-01 0:00).monday_based_week(), 0);
523    /// assert_eq!(utc_datetime!(2020-01-01 0:00).monday_based_week(), 0);
524    /// assert_eq!(utc_datetime!(2020-12-31 0:00).monday_based_week(), 52);
525    /// assert_eq!(utc_datetime!(2021-01-01 0:00).monday_based_week(), 0);
526    /// ```
527    #[inline]
528    pub const fn monday_based_week(self) -> u8 {
529        self.date().monday_based_week()
530    }
531
532    /// Get the year, month, and day.
533    ///
534    /// ```rust
535    /// # use time::Month;
536    /// # use time_macros::utc_datetime;
537    /// assert_eq!(
538    ///     utc_datetime!(2019-01-01 0:00).to_calendar_date(),
539    ///     (2019, Month::January, 1)
540    /// );
541    /// ```
542    #[inline]
543    pub const fn to_calendar_date(self) -> (i32, Month, u8) {
544        self.date().to_calendar_date()
545    }
546
547    /// Get the year and ordinal day number.
548    ///
549    /// ```rust
550    /// # use time_macros::utc_datetime;
551    /// assert_eq!(utc_datetime!(2019-01-01 0:00).to_ordinal_date(), (2019, 1));
552    /// ```
553    #[inline]
554    pub const fn to_ordinal_date(self) -> (i32, u16) {
555        self.date().to_ordinal_date()
556    }
557
558    /// Get the ISO 8601 year, week number, and weekday.
559    ///
560    /// ```rust
561    /// # use time::Weekday::*;
562    /// # use time_macros::utc_datetime;
563    /// assert_eq!(
564    ///     utc_datetime!(2019-01-01 0:00).to_iso_week_date(),
565    ///     (2019, 1, Tuesday)
566    /// );
567    /// assert_eq!(
568    ///     utc_datetime!(2019-10-04 0:00).to_iso_week_date(),
569    ///     (2019, 40, Friday)
570    /// );
571    /// assert_eq!(
572    ///     utc_datetime!(2020-01-01 0:00).to_iso_week_date(),
573    ///     (2020, 1, Wednesday)
574    /// );
575    /// assert_eq!(
576    ///     utc_datetime!(2020-12-31 0:00).to_iso_week_date(),
577    ///     (2020, 53, Thursday)
578    /// );
579    /// assert_eq!(
580    ///     utc_datetime!(2021-01-01 0:00).to_iso_week_date(),
581    ///     (2020, 53, Friday)
582    /// );
583    /// ```
584    #[inline]
585    pub const fn to_iso_week_date(self) -> (i32, u8, Weekday) {
586        self.date().to_iso_week_date()
587    }
588
589    /// Get the weekday.
590    ///
591    /// ```rust
592    /// # use time::Weekday::*;
593    /// # use time_macros::utc_datetime;
594    /// assert_eq!(utc_datetime!(2019-01-01 0:00).weekday(), Tuesday);
595    /// assert_eq!(utc_datetime!(2019-02-01 0:00).weekday(), Friday);
596    /// assert_eq!(utc_datetime!(2019-03-01 0:00).weekday(), Friday);
597    /// assert_eq!(utc_datetime!(2019-04-01 0:00).weekday(), Monday);
598    /// assert_eq!(utc_datetime!(2019-05-01 0:00).weekday(), Wednesday);
599    /// assert_eq!(utc_datetime!(2019-06-01 0:00).weekday(), Saturday);
600    /// assert_eq!(utc_datetime!(2019-07-01 0:00).weekday(), Monday);
601    /// assert_eq!(utc_datetime!(2019-08-01 0:00).weekday(), Thursday);
602    /// assert_eq!(utc_datetime!(2019-09-01 0:00).weekday(), Sunday);
603    /// assert_eq!(utc_datetime!(2019-10-01 0:00).weekday(), Tuesday);
604    /// assert_eq!(utc_datetime!(2019-11-01 0:00).weekday(), Friday);
605    /// assert_eq!(utc_datetime!(2019-12-01 0:00).weekday(), Sunday);
606    /// ```
607    #[inline]
608    pub const fn weekday(self) -> Weekday {
609        self.date().weekday()
610    }
611
612    /// Get the Julian day for the date. The time is not taken into account for this calculation.
613    ///
614    /// ```rust
615    /// # use time_macros::utc_datetime;
616    /// assert_eq!(utc_datetime!(-4713-11-24 0:00).to_julian_day(), 0);
617    /// assert_eq!(utc_datetime!(2000-01-01 0:00).to_julian_day(), 2_451_545);
618    /// assert_eq!(utc_datetime!(2019-01-01 0:00).to_julian_day(), 2_458_485);
619    /// assert_eq!(utc_datetime!(2019-12-31 0:00).to_julian_day(), 2_458_849);
620    /// ```
621    #[inline]
622    pub const fn to_julian_day(self) -> i32 {
623        self.date().to_julian_day()
624    }
625
626    /// Get the clock hour, minute, and second.
627    ///
628    /// ```rust
629    /// # use time_macros::utc_datetime;
630    /// assert_eq!(utc_datetime!(2020-01-01 0:00:00).as_hms(), (0, 0, 0));
631    /// assert_eq!(utc_datetime!(2020-01-01 23:59:59).as_hms(), (23, 59, 59));
632    /// ```
633    #[inline]
634    pub const fn as_hms(self) -> (u8, u8, u8) {
635        self.time().as_hms()
636    }
637
638    /// Get the clock hour, minute, second, and millisecond.
639    ///
640    /// ```rust
641    /// # use time_macros::utc_datetime;
642    /// assert_eq!(utc_datetime!(2020-01-01 0:00:00).as_hms_milli(), (0, 0, 0, 0));
643    /// assert_eq!(
644    ///     utc_datetime!(2020-01-01 23:59:59.999).as_hms_milli(),
645    ///     (23, 59, 59, 999)
646    /// );
647    /// ```
648    #[inline]
649    pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) {
650        self.time().as_hms_milli()
651    }
652
653    /// Get the clock hour, minute, second, and microsecond.
654    ///
655    /// ```rust
656    /// # use time_macros::utc_datetime;
657    /// assert_eq!(utc_datetime!(2020-01-01 0:00:00).as_hms_micro(), (0, 0, 0, 0));
658    /// assert_eq!(
659    ///     utc_datetime!(2020-01-01 23:59:59.999_999).as_hms_micro(),
660    ///     (23, 59, 59, 999_999)
661    /// );
662    /// ```
663    #[inline]
664    pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) {
665        self.time().as_hms_micro()
666    }
667
668    /// Get the clock hour, minute, second, and nanosecond.
669    ///
670    /// ```rust
671    /// # use time_macros::utc_datetime;
672    /// assert_eq!(utc_datetime!(2020-01-01 0:00:00).as_hms_nano(), (0, 0, 0, 0));
673    /// assert_eq!(
674    ///     utc_datetime!(2020-01-01 23:59:59.999_999_999).as_hms_nano(),
675    ///     (23, 59, 59, 999_999_999)
676    /// );
677    /// ```
678    #[inline]
679    pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) {
680        self.time().as_hms_nano()
681    }
682
683    /// Get the clock hour.
684    ///
685    /// The returned value will always be in the range `0..24`.
686    ///
687    /// ```rust
688    /// # use time_macros::utc_datetime;
689    /// assert_eq!(utc_datetime!(2019-01-01 0:00).hour(), 0);
690    /// assert_eq!(utc_datetime!(2019-01-01 23:59:59).hour(), 23);
691    /// ```
692    #[inline]
693    pub const fn hour(self) -> u8 {
694        self.time().hour()
695    }
696
697    /// Get the minute within the hour.
698    ///
699    /// The returned value will always be in the range `0..60`.
700    ///
701    /// ```rust
702    /// # use time_macros::utc_datetime;
703    /// assert_eq!(utc_datetime!(2019-01-01 0:00).minute(), 0);
704    /// assert_eq!(utc_datetime!(2019-01-01 23:59:59).minute(), 59);
705    /// ```
706    #[inline]
707    pub const fn minute(self) -> u8 {
708        self.time().minute()
709    }
710
711    /// Get the second within the minute.
712    ///
713    /// The returned value will always be in the range `0..60`.
714    ///
715    /// ```rust
716    /// # use time_macros::utc_datetime;
717    /// assert_eq!(utc_datetime!(2019-01-01 0:00).second(), 0);
718    /// assert_eq!(utc_datetime!(2019-01-01 23:59:59).second(), 59);
719    /// ```
720    #[inline]
721    pub const fn second(self) -> u8 {
722        self.time().second()
723    }
724
725    /// Get the milliseconds within the second.
726    ///
727    /// The returned value will always be in the range `0..1_000`.
728    ///
729    /// ```rust
730    /// # use time_macros::utc_datetime;
731    /// assert_eq!(utc_datetime!(2019-01-01 0:00).millisecond(), 0);
732    /// assert_eq!(utc_datetime!(2019-01-01 23:59:59.999).millisecond(), 999);
733    /// ```
734    #[inline]
735    pub const fn millisecond(self) -> u16 {
736        self.time().millisecond()
737    }
738
739    /// Get the microseconds within the second.
740    ///
741    /// The returned value will always be in the range `0..1_000_000`.
742    ///
743    /// ```rust
744    /// # use time_macros::utc_datetime;
745    /// assert_eq!(utc_datetime!(2019-01-01 0:00).microsecond(), 0);
746    /// assert_eq!(
747    ///     utc_datetime!(2019-01-01 23:59:59.999_999).microsecond(),
748    ///     999_999
749    /// );
750    /// ```
751    #[inline]
752    pub const fn microsecond(self) -> u32 {
753        self.time().microsecond()
754    }
755
756    /// Get the nanoseconds within the second.
757    ///
758    /// The returned value will always be in the range `0..1_000_000_000`.
759    ///
760    /// ```rust
761    /// # use time_macros::utc_datetime;
762    /// assert_eq!(utc_datetime!(2019-01-01 0:00).nanosecond(), 0);
763    /// assert_eq!(
764    ///     utc_datetime!(2019-01-01 23:59:59.999_999_999).nanosecond(),
765    ///     999_999_999,
766    /// );
767    /// ```
768    #[inline]
769    pub const fn nanosecond(self) -> u32 {
770        self.time().nanosecond()
771    }
772
773    /// Computes `self + duration`, returning `None` if an overflow occurred.
774    ///
775    /// ```rust
776    /// # use time::{UtcDateTime, ext::NumericalDuration};
777    /// # use time_macros::utc_datetime;
778    /// assert_eq!(UtcDateTime::MIN.checked_add((-2).days()), None);
779    /// assert_eq!(UtcDateTime::MAX.checked_add(1.days()), None);
780    /// assert_eq!(
781    ///     utc_datetime!(2019-11-25 15:30).checked_add(27.hours()),
782    ///     Some(utc_datetime!(2019-11-26 18:30))
783    /// );
784    /// ```
785    #[inline]
786    pub const fn checked_add(self, duration: SignedDuration) -> Option<Self> {
787        Some(Self::from_plain(const_try_opt!(
788            self.inner.checked_add(duration)
789        )))
790    }
791
792    /// Computes `self - duration`, returning `None` if an overflow occurred.
793    ///
794    /// ```rust
795    /// # use time::{UtcDateTime, ext::NumericalDuration};
796    /// # use time_macros::utc_datetime;
797    /// assert_eq!(UtcDateTime::MIN.checked_sub(2.days()), None);
798    /// assert_eq!(UtcDateTime::MAX.checked_sub((-1).days()), None);
799    /// assert_eq!(
800    ///     utc_datetime!(2019-11-25 15:30).checked_sub(27.hours()),
801    ///     Some(utc_datetime!(2019-11-24 12:30))
802    /// );
803    /// ```
804    #[inline]
805    pub const fn checked_sub(self, duration: SignedDuration) -> Option<Self> {
806        Some(Self::from_plain(const_try_opt!(
807            self.inner.checked_sub(duration)
808        )))
809    }
810
811    /// Computes `self + duration`, saturating value on overflow.
812    ///
813    /// ```rust
814    /// # use time::{UtcDateTime, ext::NumericalDuration};
815    /// # use time_macros::utc_datetime;
816    /// assert_eq!(
817    ///     UtcDateTime::MIN.saturating_add((-2).days()),
818    ///     UtcDateTime::MIN
819    /// );
820    /// assert_eq!(
821    ///     UtcDateTime::MAX.saturating_add(2.days()),
822    ///     UtcDateTime::MAX
823    /// );
824    /// assert_eq!(
825    ///     utc_datetime!(2019-11-25 15:30).saturating_add(27.hours()),
826    ///     utc_datetime!(2019-11-26 18:30)
827    /// );
828    /// ```
829    #[inline]
830    pub const fn saturating_add(self, duration: SignedDuration) -> Self {
831        Self::from_plain(self.inner.saturating_add(duration))
832    }
833
834    /// Computes `self - duration`, saturating value on overflow.
835    ///
836    /// ```rust
837    /// # use time::{UtcDateTime, ext::NumericalDuration};
838    /// # use time_macros::utc_datetime;
839    /// assert_eq!(
840    ///     UtcDateTime::MIN.saturating_sub(2.days()),
841    ///     UtcDateTime::MIN
842    /// );
843    /// assert_eq!(
844    ///     UtcDateTime::MAX.saturating_sub((-2).days()),
845    ///     UtcDateTime::MAX
846    /// );
847    /// assert_eq!(
848    ///     utc_datetime!(2019-11-25 15:30).saturating_sub(27.hours()),
849    ///     utc_datetime!(2019-11-24 12:30)
850    /// );
851    /// ```
852    #[inline]
853    pub const fn saturating_sub(self, duration: SignedDuration) -> Self {
854        Self::from_plain(self.inner.saturating_sub(duration))
855    }
856}
857
858/// Methods that replace part of the `UtcDateTime`.
859impl UtcDateTime {
860    /// Replace the time, preserving the date.
861    ///
862    /// ```rust
863    /// # use time_macros::{utc_datetime, time};
864    /// assert_eq!(
865    ///     utc_datetime!(2020-01-01 17:00).replace_time(time!(5:00)),
866    ///     utc_datetime!(2020-01-01 5:00)
867    /// );
868    /// ```
869    #[must_use = "This method does not mutate the original `UtcDateTime`."]
870    #[inline]
871    pub const fn replace_time(self, time: Time) -> Self {
872        Self::from_plain(self.inner.replace_time(time))
873    }
874
875    /// Replace the date, preserving the time.
876    ///
877    /// ```rust
878    /// # use time_macros::{utc_datetime, date};
879    /// assert_eq!(
880    ///     utc_datetime!(2020-01-01 12:00).replace_date(date!(2020-01-30)),
881    ///     utc_datetime!(2020-01-30 12:00)
882    /// );
883    /// ```
884    #[must_use = "This method does not mutate the original `UtcDateTime`."]
885    #[inline]
886    pub const fn replace_date(self, date: Date) -> Self {
887        Self::from_plain(self.inner.replace_date(date))
888    }
889
890    /// Replace the year. The month and day will be unchanged.
891    ///
892    /// ```rust
893    /// # use time_macros::utc_datetime;
894    /// assert_eq!(
895    ///     utc_datetime!(2022-02-18 12:00).replace_year(2019),
896    ///     Ok(utc_datetime!(2019-02-18 12:00))
897    /// );
898    /// 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
899    /// 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
900    /// ```
901    #[must_use = "This method does not mutate the original `UtcDateTime`."]
902    #[inline]
903    pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
904        Ok(Self::from_plain(const_try!(self.inner.replace_year(year))))
905    }
906
907    /// Replace the month of the year.
908    ///
909    /// ```rust
910    /// # use time_macros::utc_datetime;
911    /// # use time::Month;
912    /// assert_eq!(
913    ///     utc_datetime!(2022-02-18 12:00).replace_month(Month::January),
914    ///     Ok(utc_datetime!(2022-01-18 12:00))
915    /// );
916    /// assert!(utc_datetime!(2022-01-30 12:00).replace_month(Month::February).is_err()); // 30 isn't a valid day in February
917    /// ```
918    #[must_use = "This method does not mutate the original `UtcDateTime`."]
919    #[inline]
920    pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
921        Ok(Self::from_plain(const_try!(
922            self.inner.replace_month(month)
923        )))
924    }
925
926    /// Replace the day of the month.
927    ///
928    /// ```rust
929    /// # use time_macros::utc_datetime;
930    /// assert_eq!(
931    ///     utc_datetime!(2022-02-18 12:00).replace_day(1),
932    ///     Ok(utc_datetime!(2022-02-01 12:00))
933    /// );
934    /// assert!(utc_datetime!(2022-02-18 12:00).replace_day(0).is_err()); // 00 isn't a valid day
935    /// assert!(utc_datetime!(2022-02-18 12:00).replace_day(30).is_err()); // 30 isn't a valid day in February
936    /// ```
937    #[must_use = "This method does not mutate the original `UtcDateTime`."]
938    #[inline]
939    pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
940        Ok(Self::from_plain(const_try!(self.inner.replace_day(day))))
941    }
942
943    /// Replace the day of the year.
944    ///
945    /// ```rust
946    /// # use time_macros::utc_datetime;
947    /// assert_eq!(utc_datetime!(2022-049 12:00).replace_ordinal(1), Ok(utc_datetime!(2022-001 12:00)));
948    /// assert!(utc_datetime!(2022-049 12:00).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
949    /// assert!(utc_datetime!(2022-049 12:00).replace_ordinal(366).is_err()); // 2022 isn't a leap year
950    /// ```
951    #[must_use = "This method does not mutate the original `UtcDateTime`."]
952    #[inline]
953    pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
954        Ok(Self::from_plain(const_try!(
955            self.inner.replace_ordinal(ordinal)
956        )))
957    }
958
959    /// Truncate to the start of the day, setting the time to midnight.
960    ///
961    /// ```rust
962    /// # use time_macros::utc_datetime;
963    /// assert_eq!(
964    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_day(),
965    ///     utc_datetime!(2022-02-18 0:00)
966    /// );
967    /// ```
968    #[must_use = "This method does not mutate the original `UtcDateTime`."]
969    #[inline]
970    pub const fn truncate_to_day(self) -> Self {
971        Self::from_plain(self.inner.truncate_to_day())
972    }
973
974    /// Replace the clock hour.
975    ///
976    /// ```rust
977    /// # use time_macros::utc_datetime;
978    /// assert_eq!(
979    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_hour(7),
980    ///     Ok(utc_datetime!(2022-02-18 07:02:03.004_005_006))
981    /// );
982    /// assert!(utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_hour(24).is_err()); // 24 isn't a valid hour
983    /// ```
984    #[must_use = "This method does not mutate the original `UtcDateTime`."]
985    #[inline]
986    pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
987        Ok(Self::from_plain(const_try!(self.inner.replace_hour(hour))))
988    }
989
990    /// Truncate to the hour, setting the minute, second, and subsecond components to zero.
991    ///
992    /// ```rust
993    /// # use time_macros::utc_datetime;
994    /// assert_eq!(
995    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_hour(),
996    ///     utc_datetime!(2022-02-18 15:00)
997    /// );
998    /// ```
999    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1000    #[inline]
1001    pub const fn truncate_to_hour(self) -> Self {
1002        Self::from_plain(self.inner.truncate_to_hour())
1003    }
1004
1005    /// Replace the minutes within the hour.
1006    ///
1007    /// ```rust
1008    /// # use time_macros::utc_datetime;
1009    /// assert_eq!(
1010    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_minute(7),
1011    ///     Ok(utc_datetime!(2022-02-18 01:07:03.004_005_006))
1012    /// );
1013    /// assert!(utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_minute(60).is_err()); // 60 isn't a valid minute
1014    /// ```
1015    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1016    #[inline]
1017    pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
1018        Ok(Self::from_plain(const_try!(
1019            self.inner.replace_minute(minute)
1020        )))
1021    }
1022
1023    /// Truncate to the minute, setting the second and subsecond components to zero.
1024    ///
1025    /// ```rust
1026    /// # use time_macros::utc_datetime;
1027    /// assert_eq!(
1028    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_minute(),
1029    ///     utc_datetime!(2022-02-18 15:30)
1030    /// );
1031    /// ```
1032    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1033    #[inline]
1034    pub const fn truncate_to_minute(self) -> Self {
1035        Self::from_plain(self.inner.truncate_to_minute())
1036    }
1037
1038    /// Replace the seconds within the minute.
1039    ///
1040    /// ```rust
1041    /// # use time_macros::utc_datetime;
1042    /// assert_eq!(
1043    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_second(7),
1044    ///     Ok(utc_datetime!(2022-02-18 01:02:07.004_005_006))
1045    /// );
1046    /// assert!(utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_second(60).is_err()); // 60 isn't a valid second
1047    /// ```
1048    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1049    #[inline]
1050    pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
1051        Ok(Self::from_plain(const_try!(
1052            self.inner.replace_second(second)
1053        )))
1054    }
1055
1056    /// Truncate to the second, setting the subsecond components to zero.
1057    ///
1058    /// ```rust
1059    /// # use time_macros::utc_datetime;
1060    /// assert_eq!(
1061    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_second(),
1062    ///     utc_datetime!(2022-02-18 15:30:45)
1063    /// );
1064    /// ```
1065    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1066    #[inline]
1067    pub const fn truncate_to_second(self) -> Self {
1068        Self::from_plain(self.inner.truncate_to_second())
1069    }
1070
1071    /// Replace the milliseconds within the second.
1072    ///
1073    /// ```rust
1074    /// # use time_macros::utc_datetime;
1075    /// assert_eq!(
1076    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_millisecond(7),
1077    ///     Ok(utc_datetime!(2022-02-18 01:02:03.007))
1078    /// );
1079    /// 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
1080    /// ```
1081    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1082    #[inline]
1083    pub const fn replace_millisecond(
1084        self,
1085        millisecond: u16,
1086    ) -> Result<Self, error::ComponentRange> {
1087        Ok(Self::from_plain(const_try!(
1088            self.inner.replace_millisecond(millisecond)
1089        )))
1090    }
1091
1092    /// Truncate to the millisecond, setting the microsecond and nanosecond components to zero.
1093    ///
1094    /// ```rust
1095    /// # use time_macros::utc_datetime;
1096    /// assert_eq!(
1097    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_millisecond(),
1098    ///     utc_datetime!(2022-02-18 15:30:45.123)
1099    /// );
1100    /// ```
1101    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1102    #[inline]
1103    pub const fn truncate_to_millisecond(self) -> Self {
1104        Self::from_plain(self.inner.truncate_to_millisecond())
1105    }
1106
1107    /// Replace the microseconds within the second.
1108    ///
1109    /// ```rust
1110    /// # use time_macros::utc_datetime;
1111    /// assert_eq!(
1112    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_microsecond(7_008),
1113    ///     Ok(utc_datetime!(2022-02-18 01:02:03.007_008))
1114    /// );
1115    /// 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
1116    /// ```
1117    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1118    #[inline]
1119    pub const fn replace_microsecond(
1120        self,
1121        microsecond: u32,
1122    ) -> Result<Self, error::ComponentRange> {
1123        Ok(Self::from_plain(const_try!(
1124            self.inner.replace_microsecond(microsecond)
1125        )))
1126    }
1127
1128    /// Truncate to the microsecond, setting the nanosecond component to zero.
1129    ///
1130    /// ```rust
1131    /// # use time_macros::utc_datetime;
1132    /// assert_eq!(
1133    ///     utc_datetime!(2022-02-18 15:30:45.123_456_789).truncate_to_microsecond(),
1134    ///     utc_datetime!(2022-02-18 15:30:45.123_456)
1135    /// );
1136    /// ```
1137    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1138    #[inline]
1139    pub const fn truncate_to_microsecond(self) -> Self {
1140        Self::from_plain(self.inner.truncate_to_microsecond())
1141    }
1142
1143    /// Replace the nanoseconds within the second.
1144    ///
1145    /// ```rust
1146    /// # use time_macros::utc_datetime;
1147    /// assert_eq!(
1148    ///     utc_datetime!(2022-02-18 01:02:03.004_005_006).replace_nanosecond(7_008_009),
1149    ///     Ok(utc_datetime!(2022-02-18 01:02:03.007_008_009))
1150    /// );
1151    /// 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
1152    /// ```
1153    #[must_use = "This method does not mutate the original `UtcDateTime`."]
1154    #[inline]
1155    pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
1156        Ok(Self::from_plain(const_try!(
1157            self.inner.replace_nanosecond(nanosecond)
1158        )))
1159    }
1160}
1161
1162#[cfg(feature = "formatting")]
1163impl UtcDateTime {
1164    /// Format the `UtcDateTime` using the provided [format
1165    /// description](crate::format_description).
1166    #[inline]
1167    pub fn format_into(
1168        self,
1169        output: &mut (impl io::Write + ?Sized),
1170        format: &(impl Formattable + ?Sized),
1171    ) -> Result<usize, error::Format> {
1172        format.format_into(output, &self, &mut Default::default(), PrivateMethod)
1173    }
1174
1175    /// Format the `UtcDateTime` using the provided [format
1176    /// description](crate::format_description).
1177    ///
1178    /// ```rust
1179    /// # use time::format_description;
1180    /// # use time_macros::utc_datetime;
1181    /// let format = format_description::parse_borrowed::<3>(
1182    ///     "[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour \
1183    ///          sign:mandatory]:[offset_minute]:[offset_second]",
1184    /// )?;
1185    /// assert_eq!(
1186    ///     utc_datetime!(2020-01-02 03:04:05).format(&format)?,
1187    ///     "2020-01-02 03:04:05 +00:00:00"
1188    /// );
1189    /// # Ok::<_, time::Error>(())
1190    /// ```
1191    #[inline]
1192    pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
1193        format.format(&self, &mut Default::default(), PrivateMethod)
1194    }
1195}
1196
1197#[cfg(feature = "parsing")]
1198impl UtcDateTime {
1199    /// Parse an `UtcDateTime` from the input using the provided [format
1200    /// description](crate::format_description). A [`UtcOffset`] is permitted, but not required to
1201    /// be present. If present, the value will be converted to UTC.
1202    ///
1203    /// ```rust
1204    /// # use time::UtcDateTime;
1205    /// # use time_macros::{utc_datetime, format_description};
1206    /// let format = format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
1207    /// assert_eq!(
1208    ///     UtcDateTime::parse("2020-01-02 03:04:05", &format)?,
1209    ///     utc_datetime!(2020-01-02 03:04:05)
1210    /// );
1211    /// # Ok::<_, time::Error>(())
1212    /// ```
1213    #[inline]
1214    pub fn parse(
1215        input: &str,
1216        description: &(impl Parsable + ?Sized),
1217    ) -> Result<Self, error::Parse> {
1218        description.parse_utc_date_time(input.as_bytes(), None, PrivateMethod)
1219    }
1220
1221    /// Parse a `UtcDateTime` from the input using the provided [format
1222    /// description](crate::format_description) and default values.
1223    ///
1224    /// ```rust
1225    /// # use time::UtcDateTime;
1226    /// # use time::parsing::Parsed;
1227    /// # use time_macros::{utc_datetime, format_description};
1228    /// let format = format_description!("[year]-[month]-[day]");
1229    /// let defaults = Parsed::new().with_hour_24(12).expect("12 is a valid hour");
1230    /// assert_eq!(
1231    ///     UtcDateTime::parse_with_defaults(b"2020-01-02", &format, defaults)?,
1232    ///     utc_datetime!(2020-01-02 12:00)
1233    /// );
1234    /// # Ok::<_, time::Error>(())
1235    /// ```
1236    #[inline]
1237    pub fn parse_with_defaults(
1238        input: &[u8],
1239        description: &(impl Parsable + ?Sized),
1240        defaults: Parsed,
1241    ) -> Result<Self, error::Parse> {
1242        description.parse_utc_date_time(input, Some(defaults), PrivateMethod)
1243    }
1244
1245    /// A helper method to check if the `UtcDateTime` is a valid representation of a leap second.
1246    /// Leap seconds, when parsed, are represented as the preceding nanosecond. However, leap
1247    /// seconds can only occur as the last second of a month UTC.
1248    #[cfg(feature = "parsing")]
1249    #[inline]
1250    pub(crate) const fn is_valid_leap_second_stand_in(self) -> bool {
1251        let dt = self.inner;
1252
1253        dt.hour() == 23
1254            && dt.minute() == 59
1255            && dt.second() == 59
1256            && dt.nanosecond() == 999_999_999
1257            && dt.day() == dt.month().length(dt.year())
1258    }
1259}
1260
1261// This no longer needs special handling, as the format is fixed and doesn't require anything
1262// advanced. Trait impls can't be deprecated and the info is still useful for other types
1263// implementing `SmartDisplay`, so leave it as-is for now.
1264impl SmartDisplay for UtcDateTime {
1265    type Metadata = ();
1266
1267    #[inline]
1268    fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
1269        let width = self.as_plain().metadata(f).unpadded_width() + 4;
1270        Metadata::new(width, self, ())
1271    }
1272
1273    #[inline]
1274    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1275        fmt::Display::fmt(self, f)
1276    }
1277}
1278
1279impl UtcDateTime {
1280    /// The maximum number of bytes that the `fmt_into_buffer` method will write, which is also used
1281    /// for the `Display` implementation.
1282    pub(crate) const DISPLAY_BUFFER_SIZE: usize = PlainDateTime::DISPLAY_BUFFER_SIZE + 4;
1283
1284    /// Format the `PlainDateTime` into the provided buffer, returning the number of bytes 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<SignedDuration> 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: SignedDuration) -> 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<SignedDuration> 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: SignedDuration) {
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<SignedDuration> 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: SignedDuration) -> 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_plain(self.inner.sub(duration))
1394    }
1395}
1396
1397impl SubAssign<SignedDuration> 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: SignedDuration) {
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 = SignedDuration;
1421
1422    #[inline]
1423    fn sub(self, rhs: Self) -> Self::Output {
1424        self.inner.sub(rhs.inner)
1425    }
1426}