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