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