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