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