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