Skip to main content

time/
primitive_date_time.rs

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