Coverage Report

Created: 2026-04-12 06:41

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