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