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}