Skip to main content

time/
time.rs

1//! The [`Time`] struct and its associated `impl`s.
2
3#[cfg(feature = "formatting")]
4use alloc::string::String;
5use core::cmp::Ordering;
6use core::hash::{Hash, Hasher};
7use core::mem::MaybeUninit;
8use core::ops::{Add, AddAssign, Sub, SubAssign};
9use core::time::Duration as StdDuration;
10use core::{fmt, hint};
11#[cfg(feature = "formatting")]
12use std::io;
13
14use deranged::{ru8, ru32};
15use num_conv::prelude::*;
16use powerfmt::smart_display::{FormatterOptions, Metadata, SmartDisplay};
17
18#[cfg(any(feature = "formatting", feature = "parsing"))]
19use crate::PrivateMethod;
20#[cfg(feature = "formatting")]
21use crate::formatting::Formattable;
22use crate::internal_macros::{cascade, ensure_ranged};
23use crate::num_fmt::{
24    one_to_two_digits_no_padding, str_from_raw_parts, truncated_subsecond_from_nanos,
25    two_digits_zero_padded,
26};
27#[cfg(feature = "parsing")]
28use crate::parsing::{Parsable, Parsed};
29use crate::unit::*;
30use crate::util::DateAdjustment;
31use crate::{Duration, error};
32
33/// By explicitly inserting this enum where padding is expected, the compiler is able to better
34/// perform niche value optimization.
35#[repr(u8)]
36#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub(crate) enum Padding {
38    #[allow(clippy::missing_docs_in_private_items)]
39    Optimize,
40}
41
42/// The type of the `hour` field of `Time`.
43pub(crate) type Hours = ru8<0, { Hour::per_t::<u8>(Day) - 1 }>;
44/// The type of the `minute` field of `Time`.
45pub(crate) type Minutes = ru8<0, { Minute::per_t::<u8>(Hour) - 1 }>;
46/// The type of the `second` field of `Time`.
47pub(crate) type Seconds = ru8<0, { Second::per_t::<u8>(Minute) - 1 }>;
48/// The type of the `nanosecond` field of `Time`.
49pub(crate) type Nanoseconds = ru32<0, { Nanosecond::per_t::<u32>(Second) - 1 }>;
50
51/// The clock time within a given date. Nanosecond precision.
52///
53/// All minutes are assumed to have exactly 60 seconds; no attempt is made to handle leap seconds
54/// (either positive or negative).
55///
56/// When comparing two `Time`s, they are assumed to be in the same calendar date.
57#[derive(Clone, Copy, Eq)]
58#[cfg_attr(not(docsrs), repr(C))]
59pub struct Time {
60    // The order of this struct's fields matter! Do not reorder them.
61
62    // Little endian version
63    #[cfg(target_endian = "little")]
64    nanosecond: Nanoseconds,
65    #[cfg(target_endian = "little")]
66    second: Seconds,
67    #[cfg(target_endian = "little")]
68    minute: Minutes,
69    #[cfg(target_endian = "little")]
70    hour: Hours,
71    #[cfg(target_endian = "little")]
72    padding: Padding,
73
74    // Big endian version
75    #[cfg(target_endian = "big")]
76    padding: Padding,
77    #[cfg(target_endian = "big")]
78    hour: Hours,
79    #[cfg(target_endian = "big")]
80    minute: Minutes,
81    #[cfg(target_endian = "big")]
82    second: Seconds,
83    #[cfg(target_endian = "big")]
84    nanosecond: Nanoseconds,
85}
86
87impl Hash for Time {
88    #[inline]
89    fn hash<H>(&self, state: &mut H)
90    where
91        H: Hasher,
92    {
93        self.as_u64().hash(state)
94    }
95}
96
97impl PartialEq for Time {
98    #[inline]
99    fn eq(&self, other: &Self) -> bool {
100        self.as_u64().eq(&other.as_u64())
101    }
102}
103
104impl PartialOrd for Time {
105    #[inline]
106    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
107        Some(self.cmp(other))
108    }
109}
110
111impl Ord for Time {
112    #[inline]
113    fn cmp(&self, other: &Self) -> Ordering {
114        self.as_u64().cmp(&other.as_u64())
115    }
116}
117
118impl Time {
119    /// Provide a representation of `Time` as a `u64`. This value can be used for equality, hashing,
120    /// and ordering.
121    #[inline]
122    pub(crate) const fn as_u64(self) -> u64 {
123        // Safety: `self` is presumed valid because it exists, and any value of `u64` is valid. Size
124        // and alignment are enforced by the compiler. There is no implicit padding in either `Time`
125        // or `u64`.
126        unsafe { core::mem::transmute(self) }
127    }
128
129    /// A `Time` that is exactly midnight. This is the smallest possible value for a `Time`.
130    ///
131    /// ```rust
132    /// # use time::Time;
133    /// # use time_macros::time;
134    /// assert_eq!(Time::MIDNIGHT, time!(0:00));
135    /// ```
136    #[doc(alias = "MIN")]
137    pub const MIDNIGHT: Self =
138        Self::from_hms_nanos_ranged(Hours::MIN, Minutes::MIN, Seconds::MIN, Nanoseconds::MIN);
139
140    /// A `Time` that is one nanosecond before midnight. This is the largest possible value for a
141    /// `Time`.
142    ///
143    /// ```rust
144    /// # use time::Time;
145    /// # use time_macros::time;
146    /// assert_eq!(Time::MAX, time!(23:59:59.999_999_999));
147    /// ```
148    pub const MAX: Self =
149        Self::from_hms_nanos_ranged(Hours::MAX, Minutes::MAX, Seconds::MAX, Nanoseconds::MAX);
150
151    /// Create a `Time` from its components.
152    ///
153    /// # Safety
154    ///
155    /// - `hours` must be in the range `0..=23`.
156    /// - `minutes` must be in the range `0..=59`.
157    /// - `seconds` must be in the range `0..=59`.
158    /// - `nanoseconds` must be in the range `0..=999_999_999`.
159    #[doc(hidden)]
160    #[inline]
161    #[track_caller]
162    pub const unsafe fn __from_hms_nanos_unchecked(
163        hour: u8,
164        minute: u8,
165        second: u8,
166        nanosecond: u32,
167    ) -> Self {
168        // Safety: The caller must uphold the safety invariants.
169        unsafe {
170            Self::from_hms_nanos_ranged(
171                Hours::new_unchecked(hour),
172                Minutes::new_unchecked(minute),
173                Seconds::new_unchecked(second),
174                Nanoseconds::new_unchecked(nanosecond),
175            )
176        }
177    }
178
179    /// Attempt to create a `Time` from the hour, minute, and second.
180    ///
181    /// ```rust
182    /// # use time::Time;
183    /// assert!(Time::from_hms(1, 2, 3).is_ok());
184    /// ```
185    ///
186    /// ```rust
187    /// # use time::Time;
188    /// assert!(Time::from_hms(24, 0, 0).is_err()); // 24 isn't a valid hour.
189    /// assert!(Time::from_hms(0, 60, 0).is_err()); // 60 isn't a valid minute.
190    /// assert!(Time::from_hms(0, 0, 60).is_err()); // 60 isn't a valid second.
191    /// ```
192    #[inline]
193    pub const fn from_hms(hour: u8, minute: u8, second: u8) -> Result<Self, error::ComponentRange> {
194        Ok(Self::from_hms_nanos_ranged(
195            ensure_ranged!(Hours: hour),
196            ensure_ranged!(Minutes: minute),
197            ensure_ranged!(Seconds: second),
198            Nanoseconds::MIN,
199        ))
200    }
201
202    /// Create a `Time` from the hour, minute, second, and nanosecond.
203    #[inline]
204    pub(crate) const fn from_hms_nanos_ranged(
205        hour: Hours,
206        minute: Minutes,
207        second: Seconds,
208        nanosecond: Nanoseconds,
209    ) -> Self {
210        Self {
211            hour,
212            minute,
213            second,
214            nanosecond,
215            padding: Padding::Optimize,
216        }
217    }
218
219    /// Attempt to create a `Time` from the hour, minute, second, and millisecond.
220    ///
221    /// ```rust
222    /// # use time::Time;
223    /// assert!(Time::from_hms_milli(1, 2, 3, 4).is_ok());
224    /// ```
225    ///
226    /// ```rust
227    /// # use time::Time;
228    /// assert!(Time::from_hms_milli(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
229    /// assert!(Time::from_hms_milli(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
230    /// assert!(Time::from_hms_milli(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
231    /// assert!(Time::from_hms_milli(0, 0, 0, 1_000).is_err()); // 1_000 isn't a valid millisecond.
232    /// ```
233    #[inline]
234    pub const fn from_hms_milli(
235        hour: u8,
236        minute: u8,
237        second: u8,
238        millisecond: u16,
239    ) -> Result<Self, error::ComponentRange> {
240        Ok(Self::from_hms_nanos_ranged(
241            ensure_ranged!(Hours: hour),
242            ensure_ranged!(Minutes: minute),
243            ensure_ranged!(Seconds: second),
244            ensure_ranged!(Nanoseconds: millisecond as u32 * Nanosecond::per_t::<u32>(Millisecond)),
245        ))
246    }
247
248    /// Attempt to create a `Time` from the hour, minute, second, and microsecond.
249    ///
250    /// ```rust
251    /// # use time::Time;
252    /// assert!(Time::from_hms_micro(1, 2, 3, 4).is_ok());
253    /// ```
254    ///
255    /// ```rust
256    /// # use time::Time;
257    /// assert!(Time::from_hms_micro(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
258    /// assert!(Time::from_hms_micro(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
259    /// assert!(Time::from_hms_micro(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
260    /// assert!(Time::from_hms_micro(0, 0, 0, 1_000_000).is_err()); // 1_000_000 isn't a valid microsecond.
261    /// ```
262    #[inline]
263    pub const fn from_hms_micro(
264        hour: u8,
265        minute: u8,
266        second: u8,
267        microsecond: u32,
268    ) -> Result<Self, error::ComponentRange> {
269        Ok(Self::from_hms_nanos_ranged(
270            ensure_ranged!(Hours: hour),
271            ensure_ranged!(Minutes: minute),
272            ensure_ranged!(Seconds: second),
273            ensure_ranged!(Nanoseconds: microsecond * Nanosecond::per_t::<u32>(Microsecond)),
274        ))
275    }
276
277    /// Attempt to create a `Time` from the hour, minute, second, and nanosecond.
278    ///
279    /// ```rust
280    /// # use time::Time;
281    /// assert!(Time::from_hms_nano(1, 2, 3, 4).is_ok());
282    /// ```
283    ///
284    /// ```rust
285    /// # use time::Time;
286    /// assert!(Time::from_hms_nano(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
287    /// assert!(Time::from_hms_nano(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
288    /// assert!(Time::from_hms_nano(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
289    /// assert!(Time::from_hms_nano(0, 0, 0, 1_000_000_000).is_err()); // 1_000_000_000 isn't a valid nanosecond.
290    /// ```
291    #[inline]
292    pub const fn from_hms_nano(
293        hour: u8,
294        minute: u8,
295        second: u8,
296        nanosecond: u32,
297    ) -> Result<Self, error::ComponentRange> {
298        Ok(Self::from_hms_nanos_ranged(
299            ensure_ranged!(Hours: hour),
300            ensure_ranged!(Minutes: minute),
301            ensure_ranged!(Seconds: second),
302            ensure_ranged!(Nanoseconds: nanosecond),
303        ))
304    }
305
306    /// Get the clock hour, minute, and second.
307    ///
308    /// ```rust
309    /// # use time_macros::time;
310    /// assert_eq!(time!(0:00:00).as_hms(), (0, 0, 0));
311    /// assert_eq!(time!(23:59:59).as_hms(), (23, 59, 59));
312    /// ```
313    #[inline]
314    pub const fn as_hms(self) -> (u8, u8, u8) {
315        (self.hour.get(), self.minute.get(), self.second.get())
316    }
317
318    /// Get the clock hour, minute, second, and millisecond.
319    ///
320    /// ```rust
321    /// # use time_macros::time;
322    /// assert_eq!(time!(0:00:00).as_hms_milli(), (0, 0, 0, 0));
323    /// assert_eq!(time!(23:59:59.999).as_hms_milli(), (23, 59, 59, 999));
324    /// ```
325    #[inline]
326    pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) {
327        (
328            self.hour.get(),
329            self.minute.get(),
330            self.second.get(),
331            (self.nanosecond.get() / Nanosecond::per_t::<u32>(Millisecond)) as u16,
332        )
333    }
334
335    /// Get the clock hour, minute, second, and microsecond.
336    ///
337    /// ```rust
338    /// # use time_macros::time;
339    /// assert_eq!(time!(0:00:00).as_hms_micro(), (0, 0, 0, 0));
340    /// assert_eq!(
341    ///     time!(23:59:59.999_999).as_hms_micro(),
342    ///     (23, 59, 59, 999_999)
343    /// );
344    /// ```
345    #[inline]
346    pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) {
347        (
348            self.hour.get(),
349            self.minute.get(),
350            self.second.get(),
351            self.nanosecond.get() / Nanosecond::per_t::<u32>(Microsecond),
352        )
353    }
354
355    /// Get the clock hour, minute, second, and nanosecond.
356    ///
357    /// ```rust
358    /// # use time_macros::time;
359    /// assert_eq!(time!(0:00:00).as_hms_nano(), (0, 0, 0, 0));
360    /// assert_eq!(
361    ///     time!(23:59:59.999_999_999).as_hms_nano(),
362    ///     (23, 59, 59, 999_999_999)
363    /// );
364    /// ```
365    #[inline]
366    pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) {
367        (
368            self.hour.get(),
369            self.minute.get(),
370            self.second.get(),
371            self.nanosecond.get(),
372        )
373    }
374
375    /// Get the clock hour, minute, second, and nanosecond.
376    #[inline]
377    #[cfg(any(feature = "formatting", feature = "quickcheck"))]
378    pub(crate) const fn as_hms_nano_ranged(self) -> (Hours, Minutes, Seconds, Nanoseconds) {
379        (self.hour, self.minute, self.second, self.nanosecond)
380    }
381
382    /// Get the clock hour.
383    ///
384    /// The returned value will always be in the range `0..24`.
385    ///
386    /// ```rust
387    /// # use time_macros::time;
388    /// assert_eq!(time!(0:00:00).hour(), 0);
389    /// assert_eq!(time!(23:59:59).hour(), 23);
390    /// ```
391    #[inline]
392    pub const fn hour(self) -> u8 {
393        self.hour.get()
394    }
395
396    /// Get the minute within the hour.
397    ///
398    /// The returned value will always be in the range `0..60`.
399    ///
400    /// ```rust
401    /// # use time_macros::time;
402    /// assert_eq!(time!(0:00:00).minute(), 0);
403    /// assert_eq!(time!(23:59:59).minute(), 59);
404    /// ```
405    #[inline]
406    pub const fn minute(self) -> u8 {
407        self.minute.get()
408    }
409
410    /// Get the second within the minute.
411    ///
412    /// The returned value will always be in the range `0..60`.
413    ///
414    /// ```rust
415    /// # use time_macros::time;
416    /// assert_eq!(time!(0:00:00).second(), 0);
417    /// assert_eq!(time!(23:59:59).second(), 59);
418    /// ```
419    #[inline]
420    pub const fn second(self) -> u8 {
421        self.second.get()
422    }
423
424    /// Get the milliseconds within the second.
425    ///
426    /// The returned value will always be in the range `0..1_000`.
427    ///
428    /// ```rust
429    /// # use time_macros::time;
430    /// assert_eq!(time!(0:00).millisecond(), 0);
431    /// assert_eq!(time!(23:59:59.999).millisecond(), 999);
432    /// ```
433    #[inline]
434    pub const fn millisecond(self) -> u16 {
435        (self.nanosecond.get() / Nanosecond::per_t::<u32>(Millisecond)) as u16
436    }
437
438    /// Get the microseconds within the second.
439    ///
440    /// The returned value will always be in the range `0..1_000_000`.
441    ///
442    /// ```rust
443    /// # use time_macros::time;
444    /// assert_eq!(time!(0:00).microsecond(), 0);
445    /// assert_eq!(time!(23:59:59.999_999).microsecond(), 999_999);
446    /// ```
447    #[inline]
448    pub const fn microsecond(self) -> u32 {
449        self.nanosecond.get() / Nanosecond::per_t::<u32>(Microsecond)
450    }
451
452    /// Get the nanoseconds within the second.
453    ///
454    /// The returned value will always be in the range `0..1_000_000_000`.
455    ///
456    /// ```rust
457    /// # use time_macros::time;
458    /// assert_eq!(time!(0:00).nanosecond(), 0);
459    /// assert_eq!(time!(23:59:59.999_999_999).nanosecond(), 999_999_999);
460    /// ```
461    #[inline]
462    pub const fn nanosecond(self) -> u32 {
463        self.nanosecond.get()
464    }
465
466    /// Determine the [`Duration`] that, if added to `self`, would result in the parameter.
467    ///
468    /// ```rust
469    /// # use time::Time;
470    /// # use time::ext::NumericalDuration;
471    /// # use time_macros::time;
472    /// assert_eq!(time!(18:00).duration_until(Time::MIDNIGHT), 6.hours());
473    /// assert_eq!(time!(23:00).duration_until(time!(1:00)), 2.hours());
474    /// ```
475    #[inline]
476    pub const fn duration_until(self, other: Self) -> Duration {
477        let mut nanoseconds =
478            other.nanosecond.get().cast_signed() - self.nanosecond.get().cast_signed();
479        let seconds = other.second.get().cast_signed() - self.second.get().cast_signed();
480        let minutes = other.minute.get().cast_signed() - self.minute.get().cast_signed();
481        let hours = other.hour.get().cast_signed() - self.hour.get().cast_signed();
482
483        // Safety: For all four variables, the bounds are obviously true given the previous bounds
484        // and nature of subtraction.
485        unsafe {
486            hint::assert_unchecked(
487                nanoseconds
488                    >= Nanoseconds::MIN.get().cast_signed() - Nanoseconds::MAX.get().cast_signed(),
489            );
490            hint::assert_unchecked(
491                nanoseconds
492                    <= Nanoseconds::MAX.get().cast_signed() - Nanoseconds::MIN.get().cast_signed(),
493            );
494            hint::assert_unchecked(
495                seconds >= Seconds::MIN.get().cast_signed() - Seconds::MAX.get().cast_signed(),
496            );
497            hint::assert_unchecked(
498                seconds <= Seconds::MAX.get().cast_signed() - Seconds::MIN.get().cast_signed(),
499            );
500            hint::assert_unchecked(
501                minutes >= Minutes::MIN.get().cast_signed() - Minutes::MAX.get().cast_signed(),
502            );
503            hint::assert_unchecked(
504                minutes <= Minutes::MAX.get().cast_signed() - Minutes::MIN.get().cast_signed(),
505            );
506            hint::assert_unchecked(
507                hours >= Hours::MIN.get().cast_signed() - Hours::MAX.get().cast_signed(),
508            );
509            hint::assert_unchecked(
510                hours <= Hours::MAX.get().cast_signed() - Hours::MIN.get().cast_signed(),
511            );
512        }
513
514        let mut total_seconds = hours as i32 * Second::per_t::<i32>(Hour)
515            + minutes as i32 * Second::per_t::<i32>(Minute)
516            + seconds as i32;
517
518        cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => total_seconds);
519
520        if total_seconds < 0 {
521            total_seconds += Second::per_t::<i32>(Day);
522        }
523
524        // Safety: The range of `nanoseconds` is guaranteed by the cascades above.
525        unsafe { Duration::new_unchecked(total_seconds as i64, nanoseconds) }
526    }
527
528    /// Determine the [`Duration`] that, if added to the parameter, would result in `self`.
529    ///
530    /// ```rust
531    /// # use time::Time;
532    /// # use time::ext::NumericalDuration;
533    /// # use time_macros::time;
534    /// assert_eq!(Time::MIDNIGHT.duration_since(time!(18:00)), 6.hours());
535    /// assert_eq!(time!(1:00).duration_since(time!(23:00)), 2.hours());
536    /// ```
537    #[inline]
538    pub const fn duration_since(self, other: Self) -> Duration {
539        other.duration_until(self)
540    }
541
542    /// Add the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow, returning whether
543    /// the date is different.
544    #[inline]
545    pub(crate) const fn adjusting_add(self, duration: Duration) -> (DateAdjustment, Self) {
546        let mut nanoseconds = self.nanosecond.get().cast_signed() + duration.subsec_nanoseconds();
547        let mut seconds = self.second.get().cast_signed()
548            + (duration.whole_seconds() % Second::per_t::<i64>(Minute)) as i8;
549        let mut minutes = self.minute.get().cast_signed()
550            + (duration.whole_minutes() % Minute::per_t::<i64>(Hour)) as i8;
551        let mut hours = self.hour.get().cast_signed()
552            + (duration.whole_hours() % Hour::per_t::<i64>(Day)) as i8;
553        let mut date_adjustment = DateAdjustment::None;
554
555        cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => seconds);
556        cascade!(seconds in 0..Second::per_t(Minute) => minutes);
557        cascade!(minutes in 0..Minute::per_t(Hour) => hours);
558        if hours >= Hour::per_t(Day) {
559            hours -= Hour::per_t::<i8>(Day);
560            date_adjustment = DateAdjustment::Next;
561        } else if hours < 0 {
562            hours += Hour::per_t::<i8>(Day);
563            date_adjustment = DateAdjustment::Previous;
564        }
565
566        (
567            date_adjustment,
568            // Safety: The cascades above ensure the values are in range.
569            unsafe {
570                Self::__from_hms_nanos_unchecked(
571                    hours.cast_unsigned(),
572                    minutes.cast_unsigned(),
573                    seconds.cast_unsigned(),
574                    nanoseconds.cast_unsigned(),
575                )
576            },
577        )
578    }
579
580    /// Subtract the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow, returning
581    /// whether the date is different.
582    #[inline]
583    pub(crate) const fn adjusting_sub(self, duration: Duration) -> (DateAdjustment, Self) {
584        let mut nanoseconds = self.nanosecond.get().cast_signed() - duration.subsec_nanoseconds();
585        let mut seconds = self.second.get().cast_signed()
586            - (duration.whole_seconds() % Second::per_t::<i64>(Minute)) as i8;
587        let mut minutes = self.minute.get().cast_signed()
588            - (duration.whole_minutes() % Minute::per_t::<i64>(Hour)) as i8;
589        let mut hours = self.hour.get().cast_signed()
590            - (duration.whole_hours() % Hour::per_t::<i64>(Day)) as i8;
591        let mut date_adjustment = DateAdjustment::None;
592
593        cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => seconds);
594        cascade!(seconds in 0..Second::per_t(Minute) => minutes);
595        cascade!(minutes in 0..Minute::per_t(Hour) => hours);
596        if hours >= Hour::per_t(Day) {
597            hours -= Hour::per_t::<i8>(Day);
598            date_adjustment = DateAdjustment::Next;
599        } else if hours < 0 {
600            hours += Hour::per_t::<i8>(Day);
601            date_adjustment = DateAdjustment::Previous;
602        }
603
604        (
605            date_adjustment,
606            // Safety: The cascades above ensure the values are in range.
607            unsafe {
608                Self::__from_hms_nanos_unchecked(
609                    hours.cast_unsigned(),
610                    minutes.cast_unsigned(),
611                    seconds.cast_unsigned(),
612                    nanoseconds.cast_unsigned(),
613                )
614            },
615        )
616    }
617
618    /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow,
619    /// returning whether the date is the previous date as the first element of the tuple.
620    #[inline]
621    pub(crate) const fn adjusting_add_std(self, duration: StdDuration) -> (bool, Self) {
622        let mut nanosecond = self.nanosecond.get() + duration.subsec_nanos();
623        let mut second =
624            self.second.get() + (duration.as_secs() % Second::per_t::<u64>(Minute)) as u8;
625        let mut minute = self.minute.get()
626            + ((duration.as_secs() / Second::per_t::<u64>(Minute)) % Minute::per_t::<u64>(Hour))
627                as u8;
628        let mut hour = self.hour.get()
629            + ((duration.as_secs() / Second::per_t::<u64>(Hour)) % Hour::per_t::<u64>(Day)) as u8;
630        let mut is_next_day = false;
631
632        cascade!(nanosecond in 0..Nanosecond::per_t(Second) => second);
633        cascade!(second in 0..Second::per_t(Minute) => minute);
634        cascade!(minute in 0..Minute::per_t(Hour) => hour);
635        if hour >= Hour::per_t::<u8>(Day) {
636            hour -= Hour::per_t::<u8>(Day);
637            is_next_day = true;
638        }
639
640        (
641            is_next_day,
642            // Safety: The cascades above ensure the values are in range.
643            unsafe { Self::__from_hms_nanos_unchecked(hour, minute, second, nanosecond) },
644        )
645    }
646
647    /// Subtract the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow,
648    /// returning whether the date is the previous date as the first element of the tuple.
649    #[inline]
650    pub(crate) const fn adjusting_sub_std(self, duration: StdDuration) -> (bool, Self) {
651        let mut nanosecond =
652            self.nanosecond.get().cast_signed() - duration.subsec_nanos().cast_signed();
653        let mut second = self.second.get().cast_signed()
654            - (duration.as_secs() % Second::per_t::<u64>(Minute)) as i8;
655        let mut minute = self.minute.get().cast_signed()
656            - ((duration.as_secs() / Second::per_t::<u64>(Minute)) % Minute::per_t::<u64>(Hour))
657                as i8;
658        let mut hour = self.hour.get().cast_signed()
659            - ((duration.as_secs() / Second::per_t::<u64>(Hour)) % Hour::per_t::<u64>(Day)) as i8;
660        let mut is_previous_day = false;
661
662        cascade!(nanosecond in 0..Nanosecond::per_t(Second) => second);
663        cascade!(second in 0..Second::per_t(Minute) => minute);
664        cascade!(minute in 0..Minute::per_t(Hour) => hour);
665        if hour < 0 {
666            hour += Hour::per_t::<i8>(Day);
667            is_previous_day = true;
668        }
669
670        (
671            is_previous_day,
672            // Safety: The cascades above ensure the values are in range.
673            unsafe {
674                Self::__from_hms_nanos_unchecked(
675                    hour.cast_unsigned(),
676                    minute.cast_unsigned(),
677                    second.cast_unsigned(),
678                    nanosecond.cast_unsigned(),
679                )
680            },
681        )
682    }
683
684    /// Replace the clock hour.
685    ///
686    /// ```rust
687    /// # use time_macros::time;
688    /// assert_eq!(
689    ///     time!(01:02:03.004_005_006).replace_hour(7),
690    ///     Ok(time!(07:02:03.004_005_006))
691    /// );
692    /// assert!(time!(01:02:03.004_005_006).replace_hour(24).is_err()); // 24 isn't a valid hour
693    /// ```
694    #[must_use = "This method does not mutate the original `Time`."]
695    #[inline]
696    pub const fn replace_hour(mut self, hour: u8) -> Result<Self, error::ComponentRange> {
697        self.hour = ensure_ranged!(Hours: hour);
698        Ok(self)
699    }
700
701    /// Truncate the time to the hour, setting the minute, second, and subsecond components to zero.
702    ///
703    /// ```rust
704    /// # use time_macros::time;
705    /// assert_eq!(time!(01:02:03.004_005_006).truncate_to_hour(), time!(01:00));
706    /// ```
707    #[must_use = "This method does not mutate the original `Time`."]
708    #[inline]
709    pub const fn truncate_to_hour(mut self) -> Self {
710        self.minute = Minutes::MIN;
711        self.second = Seconds::MIN;
712        self.nanosecond = Nanoseconds::MIN;
713        self
714    }
715
716    /// Replace the minutes within the hour.
717    ///
718    /// ```rust
719    /// # use time_macros::time;
720    /// assert_eq!(
721    ///     time!(01:02:03.004_005_006).replace_minute(7),
722    ///     Ok(time!(01:07:03.004_005_006))
723    /// );
724    /// assert!(time!(01:02:03.004_005_006).replace_minute(60).is_err()); // 60 isn't a valid minute
725    /// ```
726    #[must_use = "This method does not mutate the original `Time`."]
727    #[inline]
728    pub const fn replace_minute(mut self, minute: u8) -> Result<Self, error::ComponentRange> {
729        self.minute = ensure_ranged!(Minutes: minute);
730        Ok(self)
731    }
732
733    /// Truncate the time to the minute, setting the second and subsecond components to zero.
734    ///
735    /// ```rust
736    /// # use time_macros::time;
737    /// assert_eq!(
738    ///     time!(01:02:03.004_005_006).truncate_to_minute(),
739    ///     time!(01:02)
740    /// );
741    /// ```
742    #[must_use = "This method does not mutate the original `Time`."]
743    #[inline]
744    pub const fn truncate_to_minute(mut self) -> Self {
745        self.second = Seconds::MIN;
746        self.nanosecond = Nanoseconds::MIN;
747        self
748    }
749
750    /// Replace the seconds within the minute.
751    ///
752    /// ```rust
753    /// # use time_macros::time;
754    /// assert_eq!(
755    ///     time!(01:02:03.004_005_006).replace_second(7),
756    ///     Ok(time!(01:02:07.004_005_006))
757    /// );
758    /// assert!(time!(01:02:03.004_005_006).replace_second(60).is_err()); // 60 isn't a valid second
759    /// ```
760    #[must_use = "This method does not mutate the original `Time`."]
761    #[inline]
762    pub const fn replace_second(mut self, second: u8) -> Result<Self, error::ComponentRange> {
763        self.second = ensure_ranged!(Seconds: second);
764        Ok(self)
765    }
766
767    /// Truncate the time to the second, setting the subsecond component to zero.
768    ///
769    /// ```rust
770    /// # use time_macros::time;
771    /// assert_eq!(
772    ///     time!(01:02:03.004_005_006).truncate_to_second(),
773    ///     time!(01:02:03)
774    /// );
775    /// ```
776    #[must_use = "This method does not mutate the original `Time`."]
777    #[inline]
778    pub const fn truncate_to_second(mut self) -> Self {
779        self.nanosecond = Nanoseconds::MIN;
780        self
781    }
782
783    /// Replace the milliseconds within the second.
784    ///
785    /// ```rust
786    /// # use time_macros::time;
787    /// assert_eq!(
788    ///     time!(01:02:03.004_005_006).replace_millisecond(7),
789    ///     Ok(time!(01:02:03.007))
790    /// );
791    /// assert!(
792    ///     time!(01:02:03.004_005_006)
793    ///         .replace_millisecond(1_000)
794    ///         .is_err() // 1_000 isn't a valid millisecond
795    /// );
796    /// ```
797    #[must_use = "This method does not mutate the original `Time`."]
798    #[inline]
799    pub const fn replace_millisecond(
800        mut self,
801        millisecond: u16,
802    ) -> Result<Self, error::ComponentRange> {
803        self.nanosecond =
804            ensure_ranged!(Nanoseconds: millisecond as u32 * Nanosecond::per_t::<u32>(Millisecond));
805        Ok(self)
806    }
807
808    /// Truncate the time to the millisecond, setting the microsecond and nanosecond components to
809    /// zero.
810    ///
811    /// ```rust
812    /// # use time_macros::time;
813    /// assert_eq!(
814    ///     time!(01:02:03.004_005_006).truncate_to_millisecond(),
815    ///     time!(01:02:03.004)
816    /// );
817    /// ```
818    #[must_use = "This method does not mutate the original `Time`."]
819    #[inline]
820    pub const fn truncate_to_millisecond(mut self) -> Self {
821        // Safety: Truncating to the millisecond will always produce a valid nanosecond.
822        self.nanosecond = unsafe {
823            Nanoseconds::new_unchecked(self.nanosecond.get() - (self.nanosecond.get() % 1_000_000))
824        };
825        self
826    }
827
828    /// Replace the microseconds within the second.
829    ///
830    /// ```rust
831    /// # use time_macros::time;
832    /// assert_eq!(
833    ///     time!(01:02:03.004_005_006).replace_microsecond(7_008),
834    ///     Ok(time!(01:02:03.007_008))
835    /// );
836    /// assert!(
837    ///     time!(01:02:03.004_005_006)
838    ///         .replace_microsecond(1_000_000)
839    ///         .is_err() // 1_000_000 isn't a valid microsecond
840    /// );
841    /// ```
842    #[must_use = "This method does not mutate the original `Time`."]
843    #[inline]
844    pub const fn replace_microsecond(
845        mut self,
846        microsecond: u32,
847    ) -> Result<Self, error::ComponentRange> {
848        self.nanosecond =
849            ensure_ranged!(Nanoseconds: microsecond * Nanosecond::per_t::<u32>(Microsecond));
850        Ok(self)
851    }
852
853    /// Truncate the time to the microsecond, setting the nanosecond component to zero.
854    ///
855    /// ```rust
856    /// # use time_macros::time;
857    /// assert_eq!(
858    ///     time!(01:02:03.004_005_006).truncate_to_microsecond(),
859    ///     time!(01:02:03.004_005)
860    /// );
861    /// ```
862    #[must_use = "This method does not mutate the original `Time`."]
863    #[inline]
864    pub const fn truncate_to_microsecond(mut self) -> Self {
865        // Safety: Truncating to the microsecond will always produce a valid nanosecond.
866        self.nanosecond = unsafe {
867            Nanoseconds::new_unchecked(self.nanosecond.get() - (self.nanosecond.get() % 1_000))
868        };
869        self
870    }
871
872    /// Replace the nanoseconds within the second.
873    ///
874    /// ```rust
875    /// # use time_macros::time;
876    /// assert_eq!(
877    ///     time!(01:02:03.004_005_006).replace_nanosecond(7_008_009),
878    ///     Ok(time!(01:02:03.007_008_009))
879    /// );
880    /// assert!(
881    ///     time!(01:02:03.004_005_006)
882    ///         .replace_nanosecond(1_000_000_000)
883    ///         .is_err() // 1_000_000_000 isn't a valid nanosecond
884    /// );
885    /// ```
886    #[must_use = "This method does not mutate the original `Time`."]
887    #[inline]
888    pub const fn replace_nanosecond(
889        mut self,
890        nanosecond: u32,
891    ) -> Result<Self, error::ComponentRange> {
892        self.nanosecond = ensure_ranged!(Nanoseconds: nanosecond);
893        Ok(self)
894    }
895}
896
897#[cfg(feature = "formatting")]
898impl Time {
899    /// Format the `Time` using the provided [format description](crate::format_description).
900    #[inline]
901    pub fn format_into(
902        self,
903        output: &mut (impl io::Write + ?Sized),
904        format: &(impl Formattable + ?Sized),
905    ) -> Result<usize, error::Format> {
906        format.format_into(output, &self, &mut Default::default(), PrivateMethod)
907    }
908
909    /// Format the `Time` using the provided [format description](crate::format_description).
910    ///
911    /// ```rust
912    /// # use time::format_description;
913    /// # use time_macros::time;
914    /// let format = format_description::parse_borrowed::<3>("[hour]:[minute]:[second]")?;
915    /// assert_eq!(time!(12:00).format(&format)?, "12:00:00");
916    /// # Ok::<_, time::Error>(())
917    /// ```
918    #[inline]
919    pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
920        format.format(&self, &mut Default::default(), PrivateMethod)
921    }
922}
923
924#[cfg(feature = "parsing")]
925impl Time {
926    /// Parse a `Time` from the input using the provided [format
927    /// description](crate::format_description).
928    ///
929    /// ```rust
930    /// # use time::Time;
931    /// # use time_macros::{time, format_description};
932    /// let format = format_description!("[hour]:[minute]:[second]");
933    /// assert_eq!(Time::parse("12:00:00", &format)?, time!(12:00));
934    /// # Ok::<_, time::Error>(())
935    /// ```
936    #[inline]
937    pub fn parse(
938        input: &str,
939        description: &(impl Parsable + ?Sized),
940    ) -> Result<Self, error::Parse> {
941        description.parse_time(input.as_bytes(), None, PrivateMethod)
942    }
943
944    /// Parse a `Time` from the input using the provided [format
945    /// description](crate::format_description) and default values.
946    ///
947    /// ```rust
948    /// # use time::Time;
949    /// # use time::parsing::Parsed;
950    /// # use time_macros::{time, format_description};
951    /// let format = format_description!("[hour]");
952    /// let defaults = Parsed::new().with_minute(30).expect("30 is a valid minute");
953    /// assert_eq!(
954    ///     Time::parse_with_defaults(b"12", &format, defaults)?,
955    ///     time!(12:30)
956    /// );
957    /// # Ok::<_, time::Error>(())
958    /// ```
959    #[inline]
960    pub fn parse_with_defaults(
961        input: &[u8],
962        description: &(impl Parsable + ?Sized),
963        defaults: Parsed,
964    ) -> Result<Self, error::Parse> {
965        description.parse_time(input, Some(defaults), PrivateMethod)
966    }
967}
968
969mod private {
970    /// Metadata for `Time`.
971    #[non_exhaustive]
972    #[derive(Debug)]
973    pub struct TimeMetadata;
974}
975use private::TimeMetadata;
976
977// This no longer needs special handling, as the format is fixed and doesn't require anything
978// advanced. Trait impls can't be deprecated and the info is still useful for other types
979// implementing `SmartDisplay`, so leave it as-is for now.
980impl SmartDisplay for Time {
981    type Metadata = TimeMetadata;
982
983    #[inline]
984    fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
985        let hour_width = if self.hour() < 10 { 1 } else { 2 };
986        let subsecond_width = match self.nanosecond() {
987            nanos if nanos % 10 != 0 => 9,
988            nanos if (nanos / 10) % 10 != 0 => 8,
989            nanos if (nanos / 100) % 10 != 0 => 7,
990            nanos if (nanos / 1_000) % 10 != 0 => 6,
991            nanos if (nanos / 10_000) % 10 != 0 => 5,
992            nanos if (nanos / 100_000) % 10 != 0 => 4,
993            nanos if (nanos / 1_000_000) % 10 != 0 => 3,
994            nanos if (nanos / 10_000_000) % 10 != 0 => 2,
995            _ => 1,
996        };
997        let total_width = hour_width + subsecond_width + 7;
998
999        Metadata::new(total_width, self, TimeMetadata)
1000    }
1001
1002    #[inline]
1003    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1004        fmt::Display::fmt(self, f)
1005    }
1006}
1007
1008impl Time {
1009    /// The maximum number of bytes that the `fmt_into_buffer` method will write, which is also used
1010    /// for the `Display` implementation.
1011    pub(crate) const DISPLAY_BUFFER_SIZE: usize = 18;
1012
1013    /// Format the `Time` into the provided buffer, returning the number of bytes written.
1014    #[inline]
1015    pub(crate) fn fmt_into_buffer(
1016        self,
1017        buf: &mut [MaybeUninit<u8>; Self::DISPLAY_BUFFER_SIZE],
1018    ) -> usize {
1019        let mut idx = 0;
1020
1021        // Safety: `self.hour()` is in the range required by its type.
1022        let hour =
1023            one_to_two_digits_no_padding(unsafe { Hours::new_unchecked(self.hour()) }.expand());
1024        // Safety:
1025        // - both `hour` and `buf` are valid for reads and writes of up to 2 bytes.
1026        // - `u8` is 1-aligned, so that is not a concern.
1027        // - `hour` points to static memory, while `buf` is a local variable, so they do not
1028        //   overlap.
1029        unsafe {
1030            hour.as_ptr()
1031                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), hour.len())
1032        };
1033        idx += hour.len();
1034
1035        buf[idx] = MaybeUninit::new(b':');
1036        idx += 1;
1037
1038        // Safety: See above.
1039        unsafe {
1040            two_digits_zero_padded(Minutes::new_unchecked(self.minute()).expand())
1041                .as_ptr()
1042                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2)
1043        };
1044        idx += 2;
1045
1046        buf[idx] = MaybeUninit::new(b':');
1047        idx += 1;
1048
1049        // Safety: See above.
1050        unsafe {
1051            two_digits_zero_padded(Seconds::new_unchecked(self.second()).expand())
1052                .as_ptr()
1053                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2)
1054        };
1055        idx += 2;
1056
1057        buf[idx] = MaybeUninit::new(b'.');
1058        idx += 1;
1059
1060        // Safety: `self.nanosecond()` is guaranteed to be less than 1,000,000,000.
1061        let subsecond = truncated_subsecond_from_nanos(unsafe {
1062            Nanoseconds::new_unchecked(self.nanosecond())
1063        });
1064        // Safety: See above, except `subsecond` is valid for 9 bytes.
1065        unsafe {
1066            subsecond
1067                .as_ptr()
1068                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), subsecond.len())
1069        };
1070        idx += subsecond.len();
1071
1072        idx
1073    }
1074}
1075
1076impl fmt::Display for Time {
1077    #[inline]
1078    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1079        let mut buf = [MaybeUninit::uninit(); Self::DISPLAY_BUFFER_SIZE];
1080        let len = self.fmt_into_buffer(&mut buf);
1081        // Safety: All bytes up to `len` have been initialized with ASCII characters.
1082        let s = unsafe { str_from_raw_parts(buf.as_ptr().cast(), len) };
1083        f.pad(s)
1084    }
1085}
1086
1087impl fmt::Debug for Time {
1088    #[inline]
1089    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1090        fmt::Display::fmt(self, f)
1091    }
1092}
1093
1094impl Add<Duration> for Time {
1095    type Output = Self;
1096
1097    /// Add the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow.
1098    ///
1099    /// ```rust
1100    /// # use time::ext::NumericalDuration;
1101    /// # use time_macros::time;
1102    /// assert_eq!(time!(12:00) + 2.hours(), time!(14:00));
1103    /// assert_eq!(time!(0:00:01) + (-2).seconds(), time!(23:59:59));
1104    /// ```
1105    #[inline]
1106    fn add(self, duration: Duration) -> Self::Output {
1107        self.adjusting_add(duration).1
1108    }
1109}
1110
1111impl AddAssign<Duration> for Time {
1112    #[inline]
1113    fn add_assign(&mut self, rhs: Duration) {
1114        *self = *self + rhs;
1115    }
1116}
1117
1118impl Add<StdDuration> for Time {
1119    type Output = Self;
1120
1121    /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow.
1122    ///
1123    /// ```rust
1124    /// # use time::ext::NumericalStdDuration;
1125    /// # use time_macros::time;
1126    /// assert_eq!(time!(12:00) + 2.std_hours(), time!(14:00));
1127    /// assert_eq!(time!(23:59:59) + 2.std_seconds(), time!(0:00:01));
1128    /// ```
1129    #[inline]
1130    fn add(self, duration: StdDuration) -> Self::Output {
1131        self.adjusting_add_std(duration).1
1132    }
1133}
1134
1135impl AddAssign<StdDuration> for Time {
1136    #[inline]
1137    fn add_assign(&mut self, rhs: StdDuration) {
1138        *self = *self + rhs;
1139    }
1140}
1141
1142impl Sub<Duration> for Time {
1143    type Output = Self;
1144
1145    /// Subtract the sub-day time of the [`Duration`] from the `Time`. Wraps on overflow.
1146    ///
1147    /// ```rust
1148    /// # use time::ext::NumericalDuration;
1149    /// # use time_macros::time;
1150    /// assert_eq!(time!(14:00) - 2.hours(), time!(12:00));
1151    /// assert_eq!(time!(23:59:59) - (-2).seconds(), time!(0:00:01));
1152    /// ```
1153    #[inline]
1154    fn sub(self, duration: Duration) -> Self::Output {
1155        self.adjusting_sub(duration).1
1156    }
1157}
1158
1159impl SubAssign<Duration> for Time {
1160    #[inline]
1161    fn sub_assign(&mut self, rhs: Duration) {
1162        *self = *self - rhs;
1163    }
1164}
1165
1166impl Sub<StdDuration> for Time {
1167    type Output = Self;
1168
1169    /// Subtract the sub-day time of the [`std::time::Duration`] from the `Time`. Wraps on overflow.
1170    ///
1171    /// ```rust
1172    /// # use time::ext::NumericalStdDuration;
1173    /// # use time_macros::time;
1174    /// assert_eq!(time!(14:00) - 2.std_hours(), time!(12:00));
1175    /// assert_eq!(time!(0:00:01) - 2.std_seconds(), time!(23:59:59));
1176    /// ```
1177    #[inline]
1178    fn sub(self, duration: StdDuration) -> Self::Output {
1179        self.adjusting_sub_std(duration).1
1180    }
1181}
1182
1183impl SubAssign<StdDuration> for Time {
1184    #[inline]
1185    fn sub_assign(&mut self, rhs: StdDuration) {
1186        *self = *self - rhs;
1187    }
1188}
1189
1190impl Sub for Time {
1191    type Output = Duration;
1192
1193    /// Subtract two `Time`s, returning the [`Duration`] between. This assumes both `Time`s are in
1194    /// the same calendar day.
1195    ///
1196    /// ```rust
1197    /// # use time::ext::NumericalDuration;
1198    /// # use time_macros::time;
1199    /// assert_eq!(time!(0:00) - time!(0:00), 0.seconds());
1200    /// assert_eq!(time!(1:00) - time!(0:00), 1.hours());
1201    /// assert_eq!(time!(0:00) - time!(1:00), (-1).hours());
1202    /// assert_eq!(time!(0:00) - time!(23:00), (-23).hours());
1203    /// ```
1204    #[inline]
1205    fn sub(self, rhs: Self) -> Self::Output {
1206        let hour_diff = self.hour.get().cast_signed() - rhs.hour.get().cast_signed();
1207        let minute_diff = self.minute.get().cast_signed() - rhs.minute.get().cast_signed();
1208        let second_diff = self.second.get().cast_signed() - rhs.second.get().cast_signed();
1209        let nanosecond_diff =
1210            self.nanosecond.get().cast_signed() - rhs.nanosecond.get().cast_signed();
1211
1212        let seconds = hour_diff.widen::<i32>() * Second::per_t::<i32>(Hour)
1213            + minute_diff.widen::<i32>() * Second::per_t::<i32>(Minute)
1214            + second_diff.widen::<i32>();
1215
1216        let (seconds, nanoseconds) = if seconds > 0 && nanosecond_diff < 0 {
1217            (
1218                seconds - 1,
1219                nanosecond_diff + Nanosecond::per_t::<i32>(Second),
1220            )
1221        } else if seconds < 0 && nanosecond_diff > 0 {
1222            (
1223                seconds + 1,
1224                nanosecond_diff - Nanosecond::per_t::<i32>(Second),
1225            )
1226        } else {
1227            (seconds, nanosecond_diff)
1228        };
1229
1230        // Safety: `nanoseconds` is in range due to the overflow handling.
1231        unsafe { Duration::new_unchecked(seconds.widen(), nanoseconds) }
1232    }
1233}