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