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