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