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