Coverage Report

Created: 2026-09-28 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/time-0.3.55/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::mem::MaybeUninit;
8
use core::ops::{Add, AddAssign, Sub, SubAssign};
9
use core::time::Duration as StdDuration;
10
use core::{fmt, hint};
11
#[cfg(feature = "formatting")]
12
use std::io;
13
14
use deranged::{ru8, ru32};
15
use num_conv::prelude::*;
16
use powerfmt::smart_display::{FormatterOptions, Metadata, SmartDisplay};
17
18
#[cfg(any(feature = "formatting", feature = "parsing"))]
19
use crate::PrivateMethod;
20
#[cfg(feature = "formatting")]
21
use crate::formatting::Formattable;
22
use crate::internal_macros::{cascade, ensure_ranged};
23
use 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")]
28
use crate::parsing::{Parsable, Parsed};
29
use crate::unit::*;
30
use crate::util::DateAdjustment;
31
use crate::{SignedDuration, 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)]
37
pub(crate) enum Padding {
38
    #[allow(clippy::missing_docs_in_private_items)]
39
    Optimize,
40
}
41
42
/// The type of the `hour` field of `Time`.
43
pub(crate) type Hours = ru8<0, { Hour::per_t::<u8>(Day) - 1 }>;
44
/// The type of the `minute` field of `Time`.
45
pub(crate) type Minutes = ru8<0, { Minute::per_t::<u8>(Hour) - 1 }>;
46
/// The type of the `second` field of `Time`.
47
pub(crate) type Seconds = ru8<0, { Second::per_t::<u8>(Minute) - 1 }>;
48
/// The type of the `nanosecond` field of `Time`.
49
pub(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))]
59
pub 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
87
impl Hash for Time {
88
    #[inline]
89
0
    fn hash<H>(&self, state: &mut H)
90
0
    where
91
0
        H: Hasher,
92
    {
93
0
        self.as_u64().hash(state)
94
0
    }
95
}
96
97
impl PartialEq for Time {
98
    #[inline]
99
0
    fn eq(&self, other: &Self) -> bool {
100
0
        self.as_u64().eq(&other.as_u64())
101
0
    }
102
}
103
104
impl PartialOrd for Time {
105
    #[inline]
106
0
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
107
0
        Some(self.cmp(other))
108
0
    }
109
}
110
111
impl Ord for Time {
112
    #[inline]
113
0
    fn cmp(&self, other: &Self) -> Ordering {
114
0
        self.as_u64().cmp(&other.as_u64())
115
0
    }
116
}
117
118
impl Time {
119
    /// Provide a representation of `Time` as a `u64`. This value can be used for equality, hashing,
120
    /// and ordering.
121
    #[inline]
122
0
    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
0
        unsafe { core::mem::transmute(self) }
127
0
    }
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
85.8k
    pub const unsafe fn __from_hms_nanos_unchecked(
163
85.8k
        hour: u8,
164
85.8k
        minute: u8,
165
85.8k
        second: u8,
166
85.8k
        nanosecond: u32,
167
85.8k
    ) -> Self {
168
        // Safety: The caller must uphold the safety invariants.
169
        unsafe {
170
85.8k
            Self::from_hms_nanos_ranged(
171
85.8k
                Hours::new_unchecked(hour),
172
85.8k
                Minutes::new_unchecked(minute),
173
85.8k
                Seconds::new_unchecked(second),
174
85.8k
                Nanoseconds::new_unchecked(nanosecond),
175
            )
176
        }
177
85.8k
    }
<time::time::Time>::__from_hms_nanos_unchecked
Line
Count
Source
162
85.8k
    pub const unsafe fn __from_hms_nanos_unchecked(
163
85.8k
        hour: u8,
164
85.8k
        minute: u8,
165
85.8k
        second: u8,
166
85.8k
        nanosecond: u32,
167
85.8k
    ) -> Self {
168
        // Safety: The caller must uphold the safety invariants.
169
        unsafe {
170
85.8k
            Self::from_hms_nanos_ranged(
171
85.8k
                Hours::new_unchecked(hour),
172
85.8k
                Minutes::new_unchecked(minute),
173
85.8k
                Seconds::new_unchecked(second),
174
85.8k
                Nanoseconds::new_unchecked(nanosecond),
175
            )
176
        }
177
85.8k
    }
Unexecuted instantiation: <time::time::Time>::__from_hms_nanos_unchecked
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
0
    pub const fn from_hms(hour: u8, minute: u8, second: u8) -> Result<Self, error::ComponentRange> {
194
0
        Ok(Self::from_hms_nanos_ranged(
195
0
            ensure_ranged!(Hours: hour),
196
0
            ensure_ranged!(Minutes: minute),
197
0
            ensure_ranged!(Seconds: second),
198
            Nanoseconds::MIN,
199
        ))
200
0
    }
Unexecuted instantiation: <time::time::Time>::from_hms
Unexecuted instantiation: <time::time::Time>::from_hms
201
202
    /// Create a `Time` from the hour, minute, second, and nanosecond.
203
    #[inline]
204
85.8k
    pub(crate) const fn from_hms_nanos_ranged(
205
85.8k
        hour: Hours,
206
85.8k
        minute: Minutes,
207
85.8k
        second: Seconds,
208
85.8k
        nanosecond: Nanoseconds,
209
85.8k
    ) -> Self {
210
85.8k
        Self {
211
85.8k
            hour,
212
85.8k
            minute,
213
85.8k
            second,
214
85.8k
            nanosecond,
215
85.8k
            padding: Padding::Optimize,
216
85.8k
        }
217
85.8k
    }
<time::time::Time>::from_hms_nanos_ranged
Line
Count
Source
204
85.8k
    pub(crate) const fn from_hms_nanos_ranged(
205
85.8k
        hour: Hours,
206
85.8k
        minute: Minutes,
207
85.8k
        second: Seconds,
208
85.8k
        nanosecond: Nanoseconds,
209
85.8k
    ) -> Self {
210
85.8k
        Self {
211
85.8k
            hour,
212
85.8k
            minute,
213
85.8k
            second,
214
85.8k
            nanosecond,
215
85.8k
            padding: Padding::Optimize,
216
85.8k
        }
217
85.8k
    }
Unexecuted instantiation: <time::time::Time>::from_hms_nanos_ranged
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
0
    pub const fn from_hms_milli(
235
0
        hour: u8,
236
0
        minute: u8,
237
0
        second: u8,
238
0
        millisecond: u16,
239
0
    ) -> Result<Self, error::ComponentRange> {
240
0
        Ok(Self::from_hms_nanos_ranged(
241
0
            ensure_ranged!(Hours: hour),
242
0
            ensure_ranged!(Minutes: minute),
243
0
            ensure_ranged!(Seconds: second),
244
0
            ensure_ranged!(Nanoseconds: millisecond as u32 * Nanosecond::per_t::<u32>(Millisecond)),
245
        ))
246
0
    }
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
0
    pub const fn from_hms_micro(
264
0
        hour: u8,
265
0
        minute: u8,
266
0
        second: u8,
267
0
        microsecond: u32,
268
0
    ) -> Result<Self, error::ComponentRange> {
269
0
        Ok(Self::from_hms_nanos_ranged(
270
0
            ensure_ranged!(Hours: hour),
271
0
            ensure_ranged!(Minutes: minute),
272
0
            ensure_ranged!(Seconds: second),
273
0
            ensure_ranged!(Nanoseconds: microsecond * Nanosecond::per_t::<u32>(Microsecond)),
274
        ))
275
0
    }
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
0
    pub const fn from_hms_nano(
293
0
        hour: u8,
294
0
        minute: u8,
295
0
        second: u8,
296
0
        nanosecond: u32,
297
0
    ) -> Result<Self, error::ComponentRange> {
298
0
        Ok(Self::from_hms_nanos_ranged(
299
0
            ensure_ranged!(Hours: hour),
300
0
            ensure_ranged!(Minutes: minute),
301
0
            ensure_ranged!(Seconds: second),
302
0
            ensure_ranged!(Nanoseconds: nanosecond),
303
        ))
304
0
    }
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
0
    pub const fn as_hms(self) -> (u8, u8, u8) {
315
0
        (self.hour.get(), self.minute.get(), self.second.get())
316
0
    }
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
0
    pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) {
327
0
        (
328
0
            self.hour.get(),
329
0
            self.minute.get(),
330
0
            self.second.get(),
331
0
            (self.nanosecond.get() / Nanosecond::per_t::<u32>(Millisecond)) as u16,
332
0
        )
333
0
    }
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
0
    pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) {
347
0
        (
348
0
            self.hour.get(),
349
0
            self.minute.get(),
350
0
            self.second.get(),
351
0
            self.nanosecond.get() / Nanosecond::per_t::<u32>(Microsecond),
352
0
        )
353
0
    }
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
0
    pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) {
367
0
        (
368
0
            self.hour.get(),
369
0
            self.minute.get(),
370
0
            self.second.get(),
371
0
            self.nanosecond.get(),
372
0
        )
373
0
    }
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
85.8k
    pub const fn hour(self) -> u8 {
393
85.8k
        self.hour.get()
394
85.8k
    }
<time::time::Time>::hour
Line
Count
Source
392
85.8k
    pub const fn hour(self) -> u8 {
393
85.8k
        self.hour.get()
394
85.8k
    }
Unexecuted instantiation: <time::time::Time>::hour
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
85.8k
    pub const fn minute(self) -> u8 {
407
85.8k
        self.minute.get()
408
85.8k
    }
<time::time::Time>::minute
Line
Count
Source
406
85.8k
    pub const fn minute(self) -> u8 {
407
85.8k
        self.minute.get()
408
85.8k
    }
Unexecuted instantiation: <time::time::Time>::minute
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
85.8k
    pub const fn second(self) -> u8 {
421
85.8k
        self.second.get()
422
85.8k
    }
<time::time::Time>::second
Line
Count
Source
420
85.8k
    pub const fn second(self) -> u8 {
421
85.8k
        self.second.get()
422
85.8k
    }
Unexecuted instantiation: <time::time::Time>::second
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
0
    pub const fn millisecond(self) -> u16 {
435
0
        (self.nanosecond.get() / Nanosecond::per_t::<u32>(Millisecond)) as u16
436
0
    }
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
0
    pub const fn microsecond(self) -> u32 {
449
0
        self.nanosecond.get() / Nanosecond::per_t::<u32>(Microsecond)
450
0
    }
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
0
    pub const fn nanosecond(self) -> u32 {
463
0
        self.nanosecond.get()
464
0
    }
465
466
    /// Determine the [`SignedDuration`] 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
0
    pub const fn duration_until(self, other: Self) -> SignedDuration {
477
0
        let mut nanoseconds =
478
0
            other.nanosecond.get().cast_signed() - self.nanosecond.get().cast_signed();
479
0
        let seconds = other.second.get().cast_signed() - self.second.get().cast_signed();
480
0
        let minutes = other.minute.get().cast_signed() - self.minute.get().cast_signed();
481
0
        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
0
        unsafe {
486
0
            hint::assert_unchecked(
487
0
                nanoseconds
488
0
                    >= Nanoseconds::MIN.get().cast_signed() - Nanoseconds::MAX.get().cast_signed(),
489
0
            );
490
0
            hint::assert_unchecked(
491
0
                nanoseconds
492
0
                    <= Nanoseconds::MAX.get().cast_signed() - Nanoseconds::MIN.get().cast_signed(),
493
0
            );
494
0
            hint::assert_unchecked(
495
0
                seconds >= Seconds::MIN.get().cast_signed() - Seconds::MAX.get().cast_signed(),
496
0
            );
497
0
            hint::assert_unchecked(
498
0
                seconds <= Seconds::MAX.get().cast_signed() - Seconds::MIN.get().cast_signed(),
499
0
            );
500
0
            hint::assert_unchecked(
501
0
                minutes >= Minutes::MIN.get().cast_signed() - Minutes::MAX.get().cast_signed(),
502
0
            );
503
0
            hint::assert_unchecked(
504
0
                minutes <= Minutes::MAX.get().cast_signed() - Minutes::MIN.get().cast_signed(),
505
0
            );
506
0
            hint::assert_unchecked(
507
0
                hours >= Hours::MIN.get().cast_signed() - Hours::MAX.get().cast_signed(),
508
0
            );
509
0
            hint::assert_unchecked(
510
0
                hours <= Hours::MAX.get().cast_signed() - Hours::MIN.get().cast_signed(),
511
0
            );
512
0
        }
513
514
0
        let mut total_seconds = hours as i32 * Second::per_t::<i32>(Hour)
515
0
            + minutes as i32 * Second::per_t::<i32>(Minute)
516
0
            + seconds as i32;
517
518
0
        cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => total_seconds);
519
520
0
        if total_seconds < 0 {
521
0
            total_seconds += Second::per_t::<i32>(Day);
522
0
        }
523
524
        // Safety: The range of `nanoseconds` is guaranteed by the cascades above.
525
0
        unsafe { SignedDuration::new_unchecked(total_seconds as i64, nanoseconds) }
526
0
    }
527
528
    /// Determine the [`SignedDuration`] 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
0
    pub const fn duration_since(self, other: Self) -> SignedDuration {
539
0
        other.duration_until(self)
540
0
    }
541
542
    /// Add the sub-day time of the [`SignedDuration`] to the `Time`. Wraps on overflow, returning
543
    /// whether the date is different.
544
    #[inline]
545
0
    pub(crate) const fn adjusting_add(self, duration: SignedDuration) -> (DateAdjustment, Self) {
546
0
        let mut nanoseconds = self.nanosecond.get().cast_signed() + duration.subsec_nanoseconds();
547
0
        let mut seconds = self.second.get().cast_signed()
548
0
            + (duration.whole_seconds() % Second::per_t::<i64>(Minute)) as i8;
549
0
        let mut minutes = self.minute.get().cast_signed()
550
0
            + (duration.whole_minutes() % Minute::per_t::<i64>(Hour)) as i8;
551
0
        let mut hours = self.hour.get().cast_signed()
552
0
            + (duration.whole_hours() % Hour::per_t::<i64>(Day)) as i8;
553
0
        let mut date_adjustment = DateAdjustment::None;
554
555
0
        cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => seconds);
556
0
        cascade!(seconds in 0..Second::per_t(Minute) => minutes);
557
0
        cascade!(minutes in 0..Minute::per_t(Hour) => hours);
558
0
        if hours >= Hour::per_t(Day) {
559
0
            hours -= Hour::per_t::<i8>(Day);
560
0
            date_adjustment = DateAdjustment::Next;
561
0
        } else if hours < 0 {
562
0
            hours += Hour::per_t::<i8>(Day);
563
0
            date_adjustment = DateAdjustment::Previous;
564
0
        }
565
566
0
        (
567
0
            date_adjustment,
568
0
            // Safety: The cascades above ensure the values are in range.
569
0
            unsafe {
570
0
                Self::__from_hms_nanos_unchecked(
571
0
                    hours.cast_unsigned(),
572
0
                    minutes.cast_unsigned(),
573
0
                    seconds.cast_unsigned(),
574
0
                    nanoseconds.cast_unsigned(),
575
0
                )
576
0
            },
577
0
        )
578
0
    }
579
580
    /// Subtract the sub-day time of the [`SignedDuration`] to the `Time`. Wraps on overflow,
581
    /// returning whether the date is different.
582
    #[inline]
583
0
    pub(crate) const fn adjusting_sub(self, duration: SignedDuration) -> (DateAdjustment, Self) {
584
0
        let mut nanoseconds = self.nanosecond.get().cast_signed() - duration.subsec_nanoseconds();
585
0
        let mut seconds = self.second.get().cast_signed()
586
0
            - (duration.whole_seconds() % Second::per_t::<i64>(Minute)) as i8;
587
0
        let mut minutes = self.minute.get().cast_signed()
588
0
            - (duration.whole_minutes() % Minute::per_t::<i64>(Hour)) as i8;
589
0
        let mut hours = self.hour.get().cast_signed()
590
0
            - (duration.whole_hours() % Hour::per_t::<i64>(Day)) as i8;
591
0
        let mut date_adjustment = DateAdjustment::None;
592
593
0
        cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => seconds);
594
0
        cascade!(seconds in 0..Second::per_t(Minute) => minutes);
595
0
        cascade!(minutes in 0..Minute::per_t(Hour) => hours);
596
0
        if hours >= Hour::per_t(Day) {
597
0
            hours -= Hour::per_t::<i8>(Day);
598
0
            date_adjustment = DateAdjustment::Next;
599
0
        } else if hours < 0 {
600
0
            hours += Hour::per_t::<i8>(Day);
601
0
            date_adjustment = DateAdjustment::Previous;
602
0
        }
603
604
0
        (
605
0
            date_adjustment,
606
0
            // Safety: The cascades above ensure the values are in range.
607
0
            unsafe {
608
0
                Self::__from_hms_nanos_unchecked(
609
0
                    hours.cast_unsigned(),
610
0
                    minutes.cast_unsigned(),
611
0
                    seconds.cast_unsigned(),
612
0
                    nanoseconds.cast_unsigned(),
613
0
                )
614
0
            },
615
0
        )
616
0
    }
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
85.8k
    pub(crate) const fn adjusting_add_std(self, duration: StdDuration) -> (bool, Self) {
622
85.8k
        let mut nanosecond = self.nanosecond.get() + duration.subsec_nanos();
623
85.8k
        let mut second =
624
85.8k
            self.second.get() + (duration.as_secs() % Second::per_t::<u64>(Minute)) as u8;
625
85.8k
        let mut minute = self.minute.get()
626
85.8k
            + ((duration.as_secs() / Second::per_t::<u64>(Minute)) % Minute::per_t::<u64>(Hour))
627
85.8k
                as u8;
628
85.8k
        let mut hour = self.hour.get()
629
85.8k
            + ((duration.as_secs() / Second::per_t::<u64>(Hour)) % Hour::per_t::<u64>(Day)) as u8;
630
85.8k
        let mut is_next_day = false;
631
632
85.8k
        cascade!(nanosecond in 0..Nanosecond::per_t(Second) => second);
633
85.8k
        cascade!(second in 0..Second::per_t(Minute) => minute);
634
85.8k
        cascade!(minute in 0..Minute::per_t(Hour) => hour);
635
85.8k
        if hour >= Hour::per_t::<u8>(Day) {
636
0
            hour -= Hour::per_t::<u8>(Day);
637
0
            is_next_day = true;
638
85.8k
        }
639
640
85.8k
        (
641
85.8k
            is_next_day,
642
85.8k
            // Safety: The cascades above ensure the values are in range.
643
85.8k
            unsafe { Self::__from_hms_nanos_unchecked(hour, minute, second, nanosecond) },
644
85.8k
        )
645
85.8k
    }
<time::time::Time>::adjusting_add_std
Line
Count
Source
621
85.8k
    pub(crate) const fn adjusting_add_std(self, duration: StdDuration) -> (bool, Self) {
622
85.8k
        let mut nanosecond = self.nanosecond.get() + duration.subsec_nanos();
623
85.8k
        let mut second =
624
85.8k
            self.second.get() + (duration.as_secs() % Second::per_t::<u64>(Minute)) as u8;
625
85.8k
        let mut minute = self.minute.get()
626
85.8k
            + ((duration.as_secs() / Second::per_t::<u64>(Minute)) % Minute::per_t::<u64>(Hour))
627
85.8k
                as u8;
628
85.8k
        let mut hour = self.hour.get()
629
85.8k
            + ((duration.as_secs() / Second::per_t::<u64>(Hour)) % Hour::per_t::<u64>(Day)) as u8;
630
85.8k
        let mut is_next_day = false;
631
632
85.8k
        cascade!(nanosecond in 0..Nanosecond::per_t(Second) => second);
633
85.8k
        cascade!(second in 0..Second::per_t(Minute) => minute);
634
85.8k
        cascade!(minute in 0..Minute::per_t(Hour) => hour);
635
85.8k
        if hour >= Hour::per_t::<u8>(Day) {
636
0
            hour -= Hour::per_t::<u8>(Day);
637
0
            is_next_day = true;
638
85.8k
        }
639
640
85.8k
        (
641
85.8k
            is_next_day,
642
85.8k
            // Safety: The cascades above ensure the values are in range.
643
85.8k
            unsafe { Self::__from_hms_nanos_unchecked(hour, minute, second, nanosecond) },
644
85.8k
        )
645
85.8k
    }
Unexecuted instantiation: <time::time::Time>::adjusting_add_std
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
0
    pub(crate) const fn adjusting_sub_std(self, duration: StdDuration) -> (bool, Self) {
651
0
        let mut nanosecond =
652
0
            self.nanosecond.get().cast_signed() - duration.subsec_nanos().cast_signed();
653
0
        let mut second = self.second.get().cast_signed()
654
0
            - (duration.as_secs() % Second::per_t::<u64>(Minute)) as i8;
655
0
        let mut minute = self.minute.get().cast_signed()
656
0
            - ((duration.as_secs() / Second::per_t::<u64>(Minute)) % Minute::per_t::<u64>(Hour))
657
0
                as i8;
658
0
        let mut hour = self.hour.get().cast_signed()
659
0
            - ((duration.as_secs() / Second::per_t::<u64>(Hour)) % Hour::per_t::<u64>(Day)) as i8;
660
0
        let mut is_previous_day = false;
661
662
0
        cascade!(nanosecond in 0..Nanosecond::per_t(Second) => second);
663
0
        cascade!(second in 0..Second::per_t(Minute) => minute);
664
0
        cascade!(minute in 0..Minute::per_t(Hour) => hour);
665
0
        if hour < 0 {
666
0
            hour += Hour::per_t::<i8>(Day);
667
0
            is_previous_day = true;
668
0
        }
669
670
0
        (
671
0
            is_previous_day,
672
0
            // Safety: The cascades above ensure the values are in range.
673
0
            unsafe {
674
0
                Self::__from_hms_nanos_unchecked(
675
0
                    hour.cast_unsigned(),
676
0
                    minute.cast_unsigned(),
677
0
                    second.cast_unsigned(),
678
0
                    nanosecond.cast_unsigned(),
679
0
                )
680
0
            },
681
0
        )
682
0
    }
Unexecuted instantiation: <time::time::Time>::adjusting_sub_std
Unexecuted instantiation: <time::time::Time>::adjusting_sub_std
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
0
    pub const fn replace_hour(mut self, hour: u8) -> Result<Self, error::ComponentRange> {
697
0
        self.hour = ensure_ranged!(Hours: hour);
698
0
        Ok(self)
699
0
    }
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
0
    pub const fn truncate_to_hour(mut self) -> Self {
710
0
        self.minute = Minutes::MIN;
711
0
        self.second = Seconds::MIN;
712
0
        self.nanosecond = Nanoseconds::MIN;
713
0
        self
714
0
    }
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
0
    pub const fn replace_minute(mut self, minute: u8) -> Result<Self, error::ComponentRange> {
729
0
        self.minute = ensure_ranged!(Minutes: minute);
730
0
        Ok(self)
731
0
    }
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
0
    pub const fn truncate_to_minute(mut self) -> Self {
745
0
        self.second = Seconds::MIN;
746
0
        self.nanosecond = Nanoseconds::MIN;
747
0
        self
748
0
    }
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
0
    pub const fn replace_second(mut self, second: u8) -> Result<Self, error::ComponentRange> {
763
0
        self.second = ensure_ranged!(Seconds: second);
764
0
        Ok(self)
765
0
    }
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
0
    pub const fn truncate_to_second(mut self) -> Self {
779
0
        self.nanosecond = Nanoseconds::MIN;
780
0
        self
781
0
    }
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
0
    pub const fn replace_millisecond(
800
0
        mut self,
801
0
        millisecond: u16,
802
0
    ) -> Result<Self, error::ComponentRange> {
803
        self.nanosecond =
804
0
            ensure_ranged!(Nanoseconds: millisecond as u32 * Nanosecond::per_t::<u32>(Millisecond));
805
0
        Ok(self)
806
0
    }
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
0
    pub const fn truncate_to_millisecond(mut self) -> Self {
821
        // Safety: Truncating to the millisecond will always produce a valid nanosecond.
822
0
        self.nanosecond = unsafe {
823
0
            Nanoseconds::new_unchecked(self.nanosecond.get() - (self.nanosecond.get() % 1_000_000))
824
0
        };
825
0
        self
826
0
    }
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
0
    pub const fn replace_microsecond(
845
0
        mut self,
846
0
        microsecond: u32,
847
0
    ) -> Result<Self, error::ComponentRange> {
848
        self.nanosecond =
849
0
            ensure_ranged!(Nanoseconds: microsecond * Nanosecond::per_t::<u32>(Microsecond));
850
0
        Ok(self)
851
0
    }
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
0
    pub const fn truncate_to_microsecond(mut self) -> Self {
865
        // Safety: Truncating to the microsecond will always produce a valid nanosecond.
866
0
        self.nanosecond = unsafe {
867
0
            Nanoseconds::new_unchecked(self.nanosecond.get() - (self.nanosecond.get() % 1_000))
868
0
        };
869
0
        self
870
0
    }
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
0
    pub const fn replace_nanosecond(
889
0
        mut self,
890
0
        nanosecond: u32,
891
0
    ) -> Result<Self, error::ComponentRange> {
892
0
        self.nanosecond = ensure_ranged!(Nanoseconds: nanosecond);
893
0
        Ok(self)
894
0
    }
895
}
896
897
#[cfg(feature = "formatting")]
898
impl 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")]
925
impl 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
969
// This no longer needs special handling, as the format is fixed and doesn't require anything
970
// advanced. Trait impls can't be deprecated and the info is still useful for other types
971
// implementing `SmartDisplay`, so leave it as-is for now.
972
impl SmartDisplay for Time {
973
    type Metadata = ();
974
975
    #[inline]
976
0
    fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
977
0
        let hour_width = if self.hour() < 10 { 1 } else { 2 };
978
0
        let subsecond_width = match self.nanosecond() {
979
0
            nanos if nanos % 10 != 0 => 9,
980
0
            nanos if (nanos / 10) % 10 != 0 => 8,
981
0
            nanos if (nanos / 100) % 10 != 0 => 7,
982
0
            nanos if (nanos / 1_000) % 10 != 0 => 6,
983
0
            nanos if (nanos / 10_000) % 10 != 0 => 5,
984
0
            nanos if (nanos / 100_000) % 10 != 0 => 4,
985
0
            nanos if (nanos / 1_000_000) % 10 != 0 => 3,
986
0
            nanos if (nanos / 10_000_000) % 10 != 0 => 2,
987
0
            _ => 1,
988
        };
989
0
        let total_width = hour_width + subsecond_width + 7;
990
991
0
        Metadata::new(total_width, self, ())
992
0
    }
993
994
    #[inline]
995
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
996
0
        fmt::Display::fmt(self, f)
997
0
    }
998
}
999
1000
impl Time {
1001
    /// The maximum number of bytes that the `fmt_into_buffer` method will write, which is also used
1002
    /// for the `Display` implementation.
1003
    pub(crate) const DISPLAY_BUFFER_SIZE: usize = 18;
1004
1005
    /// Format the `Time` into the provided buffer, returning the number of bytes written.
1006
    #[inline]
1007
0
    pub(crate) fn fmt_into_buffer(
1008
0
        self,
1009
0
        buf: &mut [MaybeUninit<u8>; Self::DISPLAY_BUFFER_SIZE],
1010
0
    ) -> usize {
1011
0
        let mut idx = 0;
1012
1013
        // Safety: `self.hour()` is in the range required by its type.
1014
0
        let hour =
1015
0
            one_to_two_digits_no_padding(unsafe { Hours::new_unchecked(self.hour()) }.expand());
1016
        // Safety:
1017
        // - both `hour` and `buf` are valid for reads and writes of up to 2 bytes.
1018
        // - `u8` is 1-aligned, so that is not a concern.
1019
        // - `hour` points to static memory, while `buf` is a local variable, so they do not
1020
        //   overlap.
1021
        unsafe {
1022
0
            hour.as_ptr()
1023
0
                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), hour.len())
1024
        };
1025
0
        idx += hour.len();
1026
1027
0
        buf[idx] = MaybeUninit::new(b':');
1028
0
        idx += 1;
1029
1030
        // Safety: See above.
1031
        unsafe {
1032
0
            two_digits_zero_padded(Minutes::new_unchecked(self.minute()).expand())
1033
0
                .as_ptr()
1034
0
                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2)
1035
        };
1036
0
        idx += 2;
1037
1038
0
        buf[idx] = MaybeUninit::new(b':');
1039
0
        idx += 1;
1040
1041
        // Safety: See above.
1042
        unsafe {
1043
0
            two_digits_zero_padded(Seconds::new_unchecked(self.second()).expand())
1044
0
                .as_ptr()
1045
0
                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2)
1046
        };
1047
0
        idx += 2;
1048
1049
0
        buf[idx] = MaybeUninit::new(b'.');
1050
0
        idx += 1;
1051
1052
        // Safety: `self.nanosecond()` is guaranteed to be less than 1,000,000,000.
1053
0
        let subsecond = truncated_subsecond_from_nanos(unsafe {
1054
0
            Nanoseconds::new_unchecked(self.nanosecond())
1055
        });
1056
        // Safety: See above, except `subsecond` is valid for 9 bytes.
1057
        unsafe {
1058
0
            subsecond
1059
0
                .as_ptr()
1060
0
                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), subsecond.len())
1061
        };
1062
0
        idx += subsecond.len();
1063
1064
0
        idx
1065
0
    }
1066
}
1067
1068
impl fmt::Display for Time {
1069
    #[inline]
1070
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1071
0
        let mut buf = [MaybeUninit::uninit(); Self::DISPLAY_BUFFER_SIZE];
1072
0
        let len = self.fmt_into_buffer(&mut buf);
1073
        // Safety: All bytes up to `len` have been initialized with ASCII characters.
1074
0
        let s = unsafe { str_from_raw_parts(buf.as_ptr().cast(), len) };
1075
0
        f.pad(s)
1076
0
    }
1077
}
1078
1079
impl fmt::Debug for Time {
1080
    #[inline]
1081
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1082
0
        fmt::Display::fmt(self, f)
1083
0
    }
1084
}
1085
1086
impl Add<SignedDuration> for Time {
1087
    type Output = Self;
1088
1089
    /// Add the sub-day time of the [`SignedDuration`] to the `Time`. Wraps on overflow.
1090
    ///
1091
    /// ```rust
1092
    /// # use time::ext::NumericalDuration;
1093
    /// # use time_macros::time;
1094
    /// assert_eq!(time!(12:00) + 2.hours(), time!(14:00));
1095
    /// assert_eq!(time!(0:00:01) + (-2).seconds(), time!(23:59:59));
1096
    /// ```
1097
    #[inline]
1098
0
    fn add(self, duration: SignedDuration) -> Self::Output {
1099
0
        self.adjusting_add(duration).1
1100
0
    }
1101
}
1102
1103
impl AddAssign<SignedDuration> for Time {
1104
    #[inline]
1105
0
    fn add_assign(&mut self, rhs: SignedDuration) {
1106
0
        *self = *self + rhs;
1107
0
    }
1108
}
1109
1110
impl Add<StdDuration> for Time {
1111
    type Output = Self;
1112
1113
    /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow.
1114
    ///
1115
    /// ```rust
1116
    /// # use time::ext::NumericalStdDuration;
1117
    /// # use time_macros::time;
1118
    /// assert_eq!(time!(12:00) + 2.std_hours(), time!(14:00));
1119
    /// assert_eq!(time!(23:59:59) + 2.std_seconds(), time!(0:00:01));
1120
    /// ```
1121
    #[inline]
1122
0
    fn add(self, duration: StdDuration) -> Self::Output {
1123
0
        self.adjusting_add_std(duration).1
1124
0
    }
1125
}
1126
1127
impl AddAssign<StdDuration> for Time {
1128
    #[inline]
1129
0
    fn add_assign(&mut self, rhs: StdDuration) {
1130
0
        *self = *self + rhs;
1131
0
    }
1132
}
1133
1134
impl Sub<SignedDuration> for Time {
1135
    type Output = Self;
1136
1137
    /// Subtract the sub-day time of the [`SignedDuration`] from the `Time`. Wraps on overflow.
1138
    ///
1139
    /// ```rust
1140
    /// # use time::ext::NumericalDuration;
1141
    /// # use time_macros::time;
1142
    /// assert_eq!(time!(14:00) - 2.hours(), time!(12:00));
1143
    /// assert_eq!(time!(23:59:59) - (-2).seconds(), time!(0:00:01));
1144
    /// ```
1145
    #[inline]
1146
0
    fn sub(self, duration: SignedDuration) -> Self::Output {
1147
0
        self.adjusting_sub(duration).1
1148
0
    }
1149
}
1150
1151
impl SubAssign<SignedDuration> for Time {
1152
    #[inline]
1153
0
    fn sub_assign(&mut self, rhs: SignedDuration) {
1154
0
        *self = *self - rhs;
1155
0
    }
1156
}
1157
1158
impl Sub<StdDuration> for Time {
1159
    type Output = Self;
1160
1161
    /// Subtract the sub-day time of the [`std::time::Duration`] from the `Time`. Wraps on overflow.
1162
    ///
1163
    /// ```rust
1164
    /// # use time::ext::NumericalStdDuration;
1165
    /// # use time_macros::time;
1166
    /// assert_eq!(time!(14:00) - 2.std_hours(), time!(12:00));
1167
    /// assert_eq!(time!(0:00:01) - 2.std_seconds(), time!(23:59:59));
1168
    /// ```
1169
    #[inline]
1170
0
    fn sub(self, duration: StdDuration) -> Self::Output {
1171
0
        self.adjusting_sub_std(duration).1
1172
0
    }
1173
}
1174
1175
impl SubAssign<StdDuration> for Time {
1176
    #[inline]
1177
0
    fn sub_assign(&mut self, rhs: StdDuration) {
1178
0
        *self = *self - rhs;
1179
0
    }
1180
}
1181
1182
impl Sub for Time {
1183
    type Output = SignedDuration;
1184
1185
    /// Subtract two `Time`s, returning the [`SignedDuration`] between. This assumes both `Time`s
1186
    /// are in the same calendar day.
1187
    ///
1188
    /// ```rust
1189
    /// # use time::ext::NumericalDuration;
1190
    /// # use time_macros::time;
1191
    /// assert_eq!(time!(0:00) - time!(0:00), 0.seconds());
1192
    /// assert_eq!(time!(1:00) - time!(0:00), 1.hours());
1193
    /// assert_eq!(time!(0:00) - time!(1:00), (-1).hours());
1194
    /// assert_eq!(time!(0:00) - time!(23:00), (-23).hours());
1195
    /// ```
1196
    #[inline]
1197
0
    fn sub(self, rhs: Self) -> Self::Output {
1198
0
        let hour_diff = self.hour.get().cast_signed() - rhs.hour.get().cast_signed();
1199
0
        let minute_diff = self.minute.get().cast_signed() - rhs.minute.get().cast_signed();
1200
0
        let second_diff = self.second.get().cast_signed() - rhs.second.get().cast_signed();
1201
0
        let nanosecond_diff =
1202
0
            self.nanosecond.get().cast_signed() - rhs.nanosecond.get().cast_signed();
1203
1204
0
        let seconds = hour_diff.widen::<i32>() * Second::per_t::<i32>(Hour)
1205
0
            + minute_diff.widen::<i32>() * Second::per_t::<i32>(Minute)
1206
0
            + second_diff.widen::<i32>();
1207
1208
0
        let (seconds, nanoseconds) = if seconds > 0 && nanosecond_diff < 0 {
1209
0
            (
1210
0
                seconds - 1,
1211
0
                nanosecond_diff + Nanosecond::per_t::<i32>(Second),
1212
0
            )
1213
0
        } else if seconds < 0 && nanosecond_diff > 0 {
1214
0
            (
1215
0
                seconds + 1,
1216
0
                nanosecond_diff - Nanosecond::per_t::<i32>(Second),
1217
0
            )
1218
        } else {
1219
0
            (seconds, nanosecond_diff)
1220
        };
1221
1222
        // Safety: `nanoseconds` is in range due to the overflow handling.
1223
0
        unsafe { SignedDuration::new_unchecked(seconds.widen(), nanoseconds) }
1224
0
    }
1225
}