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