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