Coverage Report

Created: 2026-07-14 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/jiff-0.2.32/src/civil/time.rs
Line
Count
Source
1
use core::time::Duration as UnsignedDuration;
2
3
use crate::{
4
    civil::{Date, DateTime},
5
    duration::{Duration, SDuration},
6
    error::{civil::Error as E, unit::UnitConfigError, Error},
7
    fmt::{
8
        self,
9
        temporal::{self, DEFAULT_DATETIME_PARSER},
10
    },
11
    shared::util::itime::{ITime, ITimeNanosecond, ITimeSecond},
12
    util::{b, constant, round::Increment},
13
    RoundMode, SignedDuration, Span, SpanRound, Unit, Zoned,
14
};
15
16
/// A representation of civil "wall clock" time.
17
///
18
/// Conceptually, a `Time` value corresponds to the typical hours and minutes
19
/// that you might see on a clock. This type also contains the second and
20
/// fractional subsecond (to nanosecond precision) associated with a time.
21
///
22
/// # Civil time
23
///
24
/// A `Time` value behaves as if it corresponds precisely to a single
25
/// nanosecond within a day, where all days have `86,400` seconds. That is,
26
/// any given `Time` value corresponds to a nanosecond in the inclusive range
27
/// `[0, 86399999999999]`, where `0` corresponds to `00:00:00.000000000`
28
/// ([`Time::MIN`]) and `86399999999999` corresponds to `23:59:59.999999999`
29
/// ([`Time::MAX`]). Moreover, in civil time, all hours have the same number of
30
/// minutes, all minutes have the same number of seconds and all seconds have
31
/// the same number of nanoseconds.
32
///
33
/// # Parsing and printing
34
///
35
/// The `Time` type provides convenient trait implementations of
36
/// [`std::str::FromStr`] and [`std::fmt::Display`]:
37
///
38
/// ```
39
/// use jiff::civil::Time;
40
///
41
/// let t: Time = "15:22:45".parse()?;
42
/// assert_eq!(t.to_string(), "15:22:45");
43
///
44
/// # Ok::<(), Box<dyn std::error::Error>>(())
45
/// ```
46
///
47
/// A civil `Time` can also be parsed from something that _contains_ a
48
/// time, but with perhaps other data (such as an offset or time zone):
49
///
50
/// ```
51
/// use jiff::civil::Time;
52
///
53
/// let t: Time = "2024-06-19T15:22:45-04[America/New_York]".parse()?;
54
/// assert_eq!(t.to_string(), "15:22:45");
55
///
56
/// # Ok::<(), Box<dyn std::error::Error>>(())
57
/// ```
58
///
59
/// For more information on the specific format supported, see the
60
/// [`fmt::temporal`](crate::fmt::temporal) module documentation.
61
///
62
/// # Default value
63
///
64
/// For convenience, this type implements the `Default` trait. Its default
65
/// value is midnight. i.e., `00:00:00.000000000`.
66
///
67
/// # Leap seconds
68
///
69
/// Jiff does not support leap seconds. Jiff behaves as if they don't exist.
70
/// The only exception is that if one parses a time with a second component
71
/// of `60`, then it is automatically constrained to `59`:
72
///
73
/// ```
74
/// use jiff::civil::{Time, time};
75
///
76
/// let t: Time = "23:59:60".parse()?;
77
/// assert_eq!(t, time(23, 59, 59, 0));
78
///
79
/// # Ok::<(), Box<dyn std::error::Error>>(())
80
/// ```
81
///
82
/// # Comparisons
83
///
84
/// The `Time` type provides both `Eq` and `Ord` trait implementations to
85
/// facilitate easy comparisons. When a time `t1` occurs before a time `t2`,
86
/// then `t1 < t2`. For example:
87
///
88
/// ```
89
/// use jiff::civil::time;
90
///
91
/// let t1 = time(7, 30, 1, 0);
92
/// let t2 = time(8, 10, 0, 0);
93
/// assert!(t1 < t2);
94
/// ```
95
///
96
/// As mentioned above, `Time` values are not associated with timezones, and
97
/// thus transitions such as DST are not taken into account when comparing
98
/// `Time` values.
99
///
100
/// # Arithmetic
101
///
102
/// This type provides routines for adding and subtracting spans of time, as
103
/// well as computing the span of time between two `Time` values.
104
///
105
/// For adding or subtracting spans of time, one can use any of the following
106
/// routines:
107
///
108
/// * [`Time::wrapping_add`] or [`Time::wrapping_sub`] for wrapping arithmetic.
109
/// * [`Time::checked_add`] or [`Time::checked_sub`] for checked arithmetic.
110
/// * [`Time::saturating_add`] or [`Time::saturating_sub`] for saturating
111
/// arithmetic.
112
///
113
/// Additionally, wrapping arithmetic is available via the `Add` and `Sub`
114
/// trait implementations:
115
///
116
/// ```
117
/// use jiff::{civil::time, ToSpan};
118
///
119
/// let t = time(20, 10, 1, 0);
120
/// let span = 1.hours().minutes(49).seconds(59);
121
/// assert_eq!(t + span, time(22, 0, 0, 0));
122
///
123
/// // Overflow will result in wrap-around unless using checked
124
/// // arithmetic explicitly.
125
/// let t = time(23, 59, 59, 999_999_999);
126
/// assert_eq!(time(0, 0, 0, 0), t + 1.nanoseconds());
127
/// ```
128
///
129
/// Wrapping arithmetic is used by default because it corresponds to how clocks
130
/// showing the time of day behave in practice.
131
///
132
/// One can compute the span of time between two times using either
133
/// [`Time::until`] or [`Time::since`]. It's also possible to subtract two
134
/// `Time` values directly via a `Sub` trait implementation:
135
///
136
/// ```
137
/// use jiff::{civil::time, ToSpan};
138
///
139
/// let time1 = time(22, 0, 0, 0);
140
/// let time2 = time(20, 10, 1, 0);
141
/// assert_eq!(
142
///     time1 - time2,
143
///     1.hours().minutes(49).seconds(59).fieldwise(),
144
/// );
145
/// ```
146
///
147
/// The `until` and `since` APIs are polymorphic and allow re-balancing and
148
/// rounding the span returned. For example, the default largest unit is hours
149
/// (as exemplified above), but we can ask for smaller units:
150
///
151
/// ```
152
/// use jiff::{civil::time, ToSpan, Unit};
153
///
154
/// let time1 = time(23, 30, 0, 0);
155
/// let time2 = time(7, 0, 0, 0);
156
/// assert_eq!(
157
///     time1.since((Unit::Minute, time2))?,
158
///     990.minutes().fieldwise(),
159
/// );
160
///
161
/// # Ok::<(), Box<dyn std::error::Error>>(())
162
/// ```
163
///
164
/// Or even round the span returned:
165
///
166
/// ```
167
/// use jiff::{civil::{TimeDifference, time}, RoundMode, ToSpan, Unit};
168
///
169
/// let time1 = time(23, 30, 0, 0);
170
/// let time2 = time(23, 35, 59, 0);
171
/// assert_eq!(
172
///     time1.until(
173
///         TimeDifference::new(time2).smallest(Unit::Minute),
174
///     )?,
175
///     5.minutes().fieldwise(),
176
/// );
177
/// // `TimeDifference` uses truncation as a rounding mode by default,
178
/// // but you can set the rounding mode to break ties away from zero:
179
/// assert_eq!(
180
///     time1.until(
181
///         TimeDifference::new(time2)
182
///             .smallest(Unit::Minute)
183
///             .mode(RoundMode::HalfExpand),
184
///     )?,
185
///     // Rounds up to 6 minutes.
186
///     6.minutes().fieldwise(),
187
/// );
188
///
189
/// # Ok::<(), Box<dyn std::error::Error>>(())
190
/// ```
191
///
192
/// # Rounding
193
///
194
/// A `Time` can be rounded based on a [`TimeRound`] configuration of smallest
195
/// units, rounding increment and rounding mode. Here's an example showing how
196
/// to round to the nearest third hour:
197
///
198
/// ```
199
/// use jiff::{civil::{TimeRound, time}, Unit};
200
///
201
/// let t = time(16, 27, 29, 999_999_999);
202
/// assert_eq!(
203
///     t.round(TimeRound::new().smallest(Unit::Hour).increment(3))?,
204
///     time(15, 0, 0, 0),
205
/// );
206
/// // Or alternatively, make use of the `From<(Unit, i64)> for TimeRound`
207
/// // trait implementation:
208
/// assert_eq!(t.round((Unit::Hour, 3))?, time(15, 0, 0, 0));
209
///
210
/// # Ok::<(), Box<dyn std::error::Error>>(())
211
/// ```
212
///
213
/// See [`Time::round`] for more details.
214
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
215
pub struct Time {
216
    hour: i8,
217
    minute: i8,
218
    second: i8,
219
    subsec_nanosecond: i32,
220
}
221
222
impl Time {
223
    /// The minimum representable time value.
224
    ///
225
    /// This corresponds to `00:00:00.000000000`.
226
    pub const MIN: Time = Time::midnight();
227
228
    /// The maximum representable time value.
229
    ///
230
    /// This corresponds to `23:59:59.999999999`.
231
    pub const MAX: Time = Time::constant(23, 59, 59, 999_999_999);
232
233
    /// Creates a new `Time` value from its component hour, minute, second and
234
    /// fractional subsecond (up to nanosecond precision) values.
235
    ///
236
    /// To set the component values of a time after creating it, use
237
    /// [`TimeWith`] via [`Time::with`] to build a new [`Time`] from the fields
238
    /// of an existing time.
239
    ///
240
    /// # Errors
241
    ///
242
    /// This returns an error unless *all* of the following conditions are
243
    /// true:
244
    ///
245
    /// * `0 <= hour <= 23`
246
    /// * `0 <= minute <= 59`
247
    /// * `0 <= second <= 59`
248
    /// * `0 <= subsec_nanosecond <= 999,999,999`
249
    ///
250
    /// # Example
251
    ///
252
    /// This shows an example of a valid time:
253
    ///
254
    /// ```
255
    /// use jiff::civil::Time;
256
    ///
257
    /// let t = Time::new(21, 30, 5, 123_456_789).unwrap();
258
    /// assert_eq!(t.hour(), 21);
259
    /// assert_eq!(t.minute(), 30);
260
    /// assert_eq!(t.second(), 5);
261
    /// assert_eq!(t.millisecond(), 123);
262
    /// assert_eq!(t.microsecond(), 456);
263
    /// assert_eq!(t.nanosecond(), 789);
264
    /// ```
265
    ///
266
    /// This shows an example of an invalid time:
267
    ///
268
    /// ```
269
    /// use jiff::civil::Time;
270
    ///
271
    /// assert!(Time::new(21, 30, 60, 0).is_err());
272
    /// ```
273
    #[inline]
274
1.67k
    pub fn new(
275
1.67k
        hour: i8,
276
1.67k
        minute: i8,
277
1.67k
        second: i8,
278
1.67k
        subsec_nanosecond: i32,
279
1.67k
    ) -> Result<Time, Error> {
280
1.67k
        let hour = b::Hour::check(hour)?;
281
1.67k
        let minute = b::Minute::check(minute)?;
282
1.67k
        let second = b::Second::check(second)?;
283
1.67k
        let subsec_nanosecond = b::SubsecNanosecond::check(subsec_nanosecond)?;
284
1.67k
        Ok(Time::new_unchecked(hour, minute, second, subsec_nanosecond))
285
1.67k
    }
286
287
    #[inline]
288
3.01k
    const fn new_unchecked(
289
3.01k
        hour: i8,
290
3.01k
        minute: i8,
291
3.01k
        second: i8,
292
3.01k
        subsec_nanosecond: i32,
293
3.01k
    ) -> Time {
294
3.01k
        Time { hour, minute, second, subsec_nanosecond }
295
3.01k
    }
296
297
    /// Creates a new `Time` value in a `const` context.
298
    ///
299
    /// # Panics
300
    ///
301
    /// This panics if the given values do not correspond to a valid `Time`.
302
    /// All of the following conditions must be true:
303
    ///
304
    /// * `0 <= hour <= 23`
305
    /// * `0 <= minute <= 59`
306
    /// * `0 <= second <= 59`
307
    /// * `0 <= subsec_nanosecond <= 999,999,999`
308
    ///
309
    /// Similarly, when used in a const context, invalid parameters will
310
    /// prevent your Rust program from compiling.
311
    ///
312
    /// # Example
313
    ///
314
    /// This shows an example of a valid time in a `const` context:
315
    ///
316
    /// ```
317
    /// use jiff::civil::Time;
318
    ///
319
    /// const BEDTIME: Time = Time::constant(21, 30, 5, 123_456_789);
320
    /// assert_eq!(BEDTIME.hour(), 21);
321
    /// assert_eq!(BEDTIME.minute(), 30);
322
    /// assert_eq!(BEDTIME.second(), 5);
323
    /// assert_eq!(BEDTIME.millisecond(), 123);
324
    /// assert_eq!(BEDTIME.microsecond(), 456);
325
    /// assert_eq!(BEDTIME.nanosecond(), 789);
326
    /// assert_eq!(BEDTIME.subsec_nanosecond(), 123_456_789);
327
    /// ```
328
    #[inline]
329
1.33k
    pub const fn constant(
330
1.33k
        hour: i8,
331
1.33k
        minute: i8,
332
1.33k
        second: i8,
333
1.33k
        subsec_nanosecond: i32,
334
1.33k
    ) -> Time {
335
1.33k
        let hour =
336
1.33k
            constant::unwrapr!(b::Hour::checkc(hour as i64), "invalid hour",);
337
1.33k
        let minute = constant::unwrapr!(
338
1.33k
            b::Minute::checkc(minute as i64),
339
            "invalid minute",
340
        );
341
1.33k
        let second = constant::unwrapr!(
342
1.33k
            b::Second::checkc(second as i64),
343
            "invalid second",
344
        );
345
1.33k
        let subsec = constant::unwrapr!(
346
1.33k
            b::SubsecNanosecond::checkc(subsec_nanosecond as i64),
347
            "invalid nanosecond",
348
        );
349
1.33k
        Time::new_unchecked(hour, minute, second, subsec)
350
1.33k
    }
351
352
    /// Returns the first moment of time in a day.
353
    ///
354
    /// Specifically, this has the `hour`, `minute`, `second`, `millisecond`,
355
    /// `microsecond` and `nanosecond` fields all set to `0`.
356
    ///
357
    /// # Example
358
    ///
359
    /// ```
360
    /// use jiff::civil::Time;
361
    ///
362
    /// let t = Time::midnight();
363
    /// assert_eq!(t.hour(), 0);
364
    /// assert_eq!(t.minute(), 0);
365
    /// assert_eq!(t.second(), 0);
366
    /// assert_eq!(t.millisecond(), 0);
367
    /// assert_eq!(t.microsecond(), 0);
368
    /// assert_eq!(t.nanosecond(), 0);
369
    /// ```
370
    #[inline]
371
606
    pub const fn midnight() -> Time {
372
606
        Time::constant(0, 0, 0, 0)
373
606
    }
374
375
    /// Create a builder for constructing a `Time` from the fields of this
376
    /// time.
377
    ///
378
    /// See the methods on [`TimeWith`] for the different ways one can set the
379
    /// fields of a new `Time`.
380
    ///
381
    /// # Example
382
    ///
383
    /// Unlike [`Date`], a [`Time`] is valid for all possible valid values
384
    /// of its fields. That is, there is no way for two valid field values
385
    /// to combine into an invalid `Time`. So, for `Time`, this builder does
386
    /// have as much of a benefit versus an API design with methods like
387
    /// `Time::with_hour` and `Time::with_minute`. Nevertheless, this builder
388
    /// permits settings multiple fields at the same time and performing only
389
    /// one validity check. Moreover, this provides a consistent API with other
390
    /// date and time types in this crate.
391
    ///
392
    /// ```
393
    /// use jiff::civil::time;
394
    ///
395
    /// let t1 = time(0, 0, 24, 0);
396
    /// let t2 = t1.with().hour(15).minute(30).millisecond(10).build()?;
397
    /// assert_eq!(t2, time(15, 30, 24, 10_000_000));
398
    ///
399
    /// # Ok::<(), Box<dyn std::error::Error>>(())
400
    /// ```
401
    #[inline]
402
0
    pub fn with(self) -> TimeWith {
403
0
        TimeWith::new(self)
404
0
    }
405
406
    /// Returns the "hour" component of this time.
407
    ///
408
    /// The value returned is guaranteed to be in the range `0..=23`.
409
    ///
410
    /// # Example
411
    ///
412
    /// ```
413
    /// use jiff::civil::time;
414
    ///
415
    /// let t = time(13, 35, 56, 123_456_789);
416
    /// assert_eq!(t.hour(), 13);
417
    /// ```
418
    #[inline]
419
1.05k
    pub fn hour(self) -> i8 {
420
1.05k
        self.hour
421
1.05k
    }
422
423
    /// Returns the "minute" component of this time.
424
    ///
425
    /// The value returned is guaranteed to be in the range `0..=59`.
426
    ///
427
    /// # Example
428
    ///
429
    /// ```
430
    /// use jiff::civil::time;
431
    ///
432
    /// let t = time(13, 35, 56, 123_456_789);
433
    /// assert_eq!(t.minute(), 35);
434
    /// ```
435
    #[inline]
436
1.05k
    pub fn minute(self) -> i8 {
437
1.05k
        self.minute
438
1.05k
    }
439
440
    /// Returns the "second" component of this time.
441
    ///
442
    /// The value returned is guaranteed to be in the range `0..=59`.
443
    ///
444
    /// # Example
445
    ///
446
    /// ```
447
    /// use jiff::civil::time;
448
    ///
449
    /// let t = time(13, 35, 56, 123_456_789);
450
    /// assert_eq!(t.second(), 56);
451
    /// ```
452
    #[inline]
453
1.05k
    pub fn second(self) -> i8 {
454
1.05k
        self.second
455
1.05k
    }
456
457
    /// Returns the "millisecond" component of this time.
458
    ///
459
    /// The value returned is guaranteed to be in the range `0..=999`.
460
    ///
461
    /// # Example
462
    ///
463
    /// ```
464
    /// use jiff::civil::time;
465
    ///
466
    /// let t = time(13, 35, 56, 123_456_789);
467
    /// assert_eq!(t.millisecond(), 123);
468
    /// ```
469
    #[inline]
470
0
    pub fn millisecond(self) -> i16 {
471
0
        (self.subsec_nanosecond() / b::NANOS_PER_MILLI_32) as i16
472
0
    }
473
474
    /// Returns the "microsecond" component of this time.
475
    ///
476
    /// The value returned is guaranteed to be in the range `0..=999`.
477
    ///
478
    /// # Example
479
    ///
480
    /// ```
481
    /// use jiff::civil::time;
482
    ///
483
    /// let t = time(13, 35, 56, 123_456_789);
484
    /// assert_eq!(t.microsecond(), 456);
485
    /// ```
486
    #[inline]
487
0
    pub fn microsecond(self) -> i16 {
488
0
        ((self.subsec_nanosecond() / b::NANOS_PER_MICRO_32)
489
0
            % b::MICROS_PER_MILLI_32) as i16
490
0
    }
491
492
    /// Returns the "nanosecond" component of this time.
493
    ///
494
    /// The value returned is guaranteed to be in the range `0..=999`.
495
    ///
496
    /// # Example
497
    ///
498
    /// ```
499
    /// use jiff::civil::time;
500
    ///
501
    /// let t = time(13, 35, 56, 123_456_789);
502
    /// assert_eq!(t.nanosecond(), 789);
503
    /// ```
504
    #[inline]
505
0
    pub fn nanosecond(self) -> i16 {
506
0
        (self.subsec_nanosecond() % b::NANOS_PER_MICRO_32) as i16
507
0
    }
508
509
    /// Returns the fractional nanosecond for this `Time` value.
510
    ///
511
    /// If you want to set this value on `Time`, then use
512
    /// [`TimeWith::subsec_nanosecond`] via [`Time::with`].
513
    ///
514
    /// The value returned is guaranteed to be in the range `0..=999_999_999`.
515
    ///
516
    /// # Example
517
    ///
518
    /// This shows the relationship between constructing a `Time` value
519
    /// with routines like `with().millisecond()` and accessing the entire
520
    /// fractional part as a nanosecond:
521
    ///
522
    /// ```
523
    /// use jiff::civil::time;
524
    ///
525
    /// let t = time(15, 21, 35, 0).with().millisecond(987).build()?;
526
    /// assert_eq!(t.subsec_nanosecond(), 987_000_000);
527
    ///
528
    /// # Ok::<(), Box<dyn std::error::Error>>(())
529
    /// ```
530
    ///
531
    /// # Example: nanoseconds from a timestamp
532
    ///
533
    /// This shows how the fractional nanosecond part of a `Time` value
534
    /// manifests from a specific timestamp.
535
    ///
536
    /// ```
537
    /// use jiff::Timestamp;
538
    ///
539
    /// // 1,234 nanoseconds after the Unix epoch.
540
    /// let zdt = Timestamp::new(0, 1_234)?.in_tz("UTC")?;
541
    /// let time = zdt.datetime().time();
542
    /// assert_eq!(time.subsec_nanosecond(), 1_234);
543
    ///
544
    /// // 1,234 nanoseconds before the Unix epoch.
545
    /// let zdt = Timestamp::new(0, -1_234)?.in_tz("UTC")?;
546
    /// let time = zdt.datetime().time();
547
    /// // The nanosecond is equal to `1_000_000_000 - 1_234`.
548
    /// assert_eq!(time.subsec_nanosecond(), 999998766);
549
    /// // Looking at the other components of the time value might help.
550
    /// assert_eq!(time.hour(), 23);
551
    /// assert_eq!(time.minute(), 59);
552
    /// assert_eq!(time.second(), 59);
553
    ///
554
    /// # Ok::<(), Box<dyn std::error::Error>>(())
555
    /// ```
556
    #[inline]
557
2.11k
    pub fn subsec_nanosecond(self) -> i32 {
558
2.11k
        self.subsec_nanosecond
559
2.11k
    }
560
561
    /// Given a [`Date`], this constructs a [`DateTime`] value with its time
562
    /// component equal to this time.
563
    ///
564
    /// This is a convenience function for [`DateTime::from_parts`].
565
    ///
566
    /// # Example
567
    ///
568
    /// ```
569
    /// use jiff::civil::{DateTime, date, time};
570
    ///
571
    /// let d = date(2010, 3, 14);
572
    /// let t = time(2, 30, 0, 0);
573
    /// assert_eq!(DateTime::from_parts(d, t), t.to_datetime(d));
574
    /// ```
575
    #[inline]
576
0
    pub const fn to_datetime(self, date: Date) -> DateTime {
577
0
        DateTime::from_parts(date, self)
578
0
    }
579
580
    /// A convenience function for constructing a [`DateTime`] from this time
581
    /// on the date given by its components.
582
    ///
583
    /// # Panics
584
    ///
585
    /// This routine panics when [`Date::new`] with the given inputs would
586
    /// return an error. That is, when the given year-month-day does not
587
    /// correspond to a valid date. Namely, all of the following must be true:
588
    ///
589
    /// * The year must be in the range `-9999..=9999`.
590
    /// * The month must be in the range `1..=12`.
591
    /// * The day must be at least `1` and must be at most the number of days
592
    /// in the corresponding month. So for example, `2024-02-29` is valid but
593
    /// `2023-02-29` is not.
594
    ///
595
    /// Similarly, when used in a const context, invalid parameters will
596
    /// prevent your Rust program from compiling.
597
    ///
598
    /// # Example
599
    ///
600
    /// ```
601
    /// use jiff::civil::time;
602
    ///
603
    /// assert_eq!(
604
    ///     time(2, 30, 0, 0).on(2010, 3, 14).to_string(),
605
    ///     "2010-03-14T02:30:00",
606
    /// );
607
    /// ```
608
    ///
609
    /// One can also flip the order by making use of [`Date::at`]:
610
    ///
611
    /// ```
612
    /// use jiff::civil::date;
613
    ///
614
    /// assert_eq!(
615
    ///     date(2010, 3, 14).at(2, 30, 0, 0).to_string(),
616
    ///     "2010-03-14T02:30:00",
617
    /// );
618
    /// ```
619
    #[inline]
620
0
    pub const fn on(self, year: i16, month: i8, day: i8) -> DateTime {
621
0
        DateTime::from_parts(Date::constant(year, month, day), self)
622
0
    }
623
624
    /// Add the given span to this time and wrap around on overflow.
625
    ///
626
    /// This operation accepts three different duration types: [`Span`],
627
    /// [`SignedDuration`] or [`std::time::Duration`]. This is achieved via
628
    /// `From` trait implementations for the [`TimeArithmetic`] type.
629
    ///
630
    /// # Properties
631
    ///
632
    /// Given times `t1` and `t2`, and a span `s`, with `t2 = t1 + s`, it
633
    /// follows then that `t1 = t2 - s` for all values of `t1` and `s` that sum
634
    /// to `t2`.
635
    ///
636
    /// In short, subtracting the given span from the sum returned by this
637
    /// function is guaranteed to result in precisely the original time.
638
    ///
639
    /// # Example: available via addition operator
640
    ///
641
    /// This routine can be used via the `+` operator.
642
    ///
643
    /// ```
644
    /// use jiff::{civil::time, ToSpan};
645
    ///
646
    /// let t = time(20, 10, 1, 0);
647
    /// assert_eq!(
648
    ///     t + 1.hours().minutes(49).seconds(59),
649
    ///     time(22, 0, 0, 0),
650
    /// );
651
    /// ```
652
    ///
653
    /// # Example: add nanoseconds to a `Time`
654
    ///
655
    /// ```
656
    /// use jiff::{civil::time, ToSpan};
657
    ///
658
    /// let t = time(22, 35, 1, 0);
659
    /// assert_eq!(
660
    ///     time(22, 35, 3, 500_000_000),
661
    ///     t.wrapping_add(2_500_000_000i64.nanoseconds()),
662
    /// );
663
    /// ```
664
    ///
665
    /// # Example: add span with multiple units
666
    ///
667
    /// ```
668
    /// use jiff::{civil::time, ToSpan};
669
    ///
670
    /// let t = time(20, 10, 1, 0);
671
    /// assert_eq!(
672
    ///     time(22, 0, 0, 0),
673
    ///     t.wrapping_add(1.hours().minutes(49).seconds(59)),
674
    /// );
675
    /// ```
676
    ///
677
    /// # Example: adding an empty span is a no-op
678
    ///
679
    /// ```
680
    /// use jiff::{civil::time, Span};
681
    ///
682
    /// let t = time(20, 10, 1, 0);
683
    /// assert_eq!(t, t.wrapping_add(Span::new()));
684
    /// ```
685
    ///
686
    /// # Example: addition wraps on overflow
687
    ///
688
    /// ```
689
    /// use jiff::{civil::time, SignedDuration, ToSpan};
690
    ///
691
    /// let t = time(23, 59, 59, 999_999_999);
692
    /// assert_eq!(
693
    ///     t.wrapping_add(1.nanoseconds()),
694
    ///     time(0, 0, 0, 0),
695
    /// );
696
    /// assert_eq!(
697
    ///     t.wrapping_add(SignedDuration::from_nanos(1)),
698
    ///     time(0, 0, 0, 0),
699
    /// );
700
    /// assert_eq!(
701
    ///     t.wrapping_add(std::time::Duration::from_nanos(1)),
702
    ///     time(0, 0, 0, 0),
703
    /// );
704
    /// ```
705
    ///
706
    /// Similarly, if there are any non-zero units greater than hours in the
707
    /// given span, then they also result in wrapping behavior (i.e., they are
708
    /// ignored):
709
    ///
710
    /// ```
711
    /// use jiff::{civil::time, ToSpan};
712
    ///
713
    /// // doesn't matter what our time value is in this example
714
    /// let t = time(0, 0, 0, 0);
715
    /// assert_eq!(t, t.wrapping_add(1.days()));
716
    /// ```
717
    #[inline]
718
0
    pub fn wrapping_add<A: Into<TimeArithmetic>>(self, duration: A) -> Time {
719
0
        let duration: TimeArithmetic = duration.into();
720
0
        duration.wrapping_add(self)
721
0
    }
722
723
    #[inline]
724
0
    fn wrapping_add_span(self, span: Span) -> Time {
725
0
        let sum = self
726
0
            .to_nanosecond()
727
0
            .wrapping_add(
728
0
                i64::from(span.get_hours()).wrapping_mul(b::NANOS_PER_HOUR),
729
            )
730
0
            .wrapping_add(span.get_minutes().wrapping_mul(b::NANOS_PER_MIN))
731
0
            .wrapping_add(span.get_seconds().wrapping_mul(b::NANOS_PER_SEC))
732
0
            .wrapping_add(
733
0
                span.get_milliseconds().wrapping_mul(b::NANOS_PER_MILLI),
734
            )
735
0
            .wrapping_add(
736
0
                span.get_microseconds().wrapping_mul(b::NANOS_PER_MICRO),
737
            )
738
0
            .wrapping_add(span.get_nanoseconds());
739
0
        let civil_day_nanosecond = sum.rem_euclid(b::NANOS_PER_CIVIL_DAY);
740
0
        Time::from_nanosecond_unchecked(civil_day_nanosecond)
741
0
    }
742
743
    #[inline]
744
0
    fn wrapping_add_signed_duration(self, duration: SignedDuration) -> Time {
745
0
        let start = i128::from(self.to_nanosecond());
746
0
        let duration = duration.as_nanos();
747
0
        let end = start
748
0
            .wrapping_add(duration)
749
0
            .rem_euclid(b::NANOS_PER_CIVIL_DAY as i128)
750
0
            as i64;
751
0
        Time::from_nanosecond_unchecked(end)
752
0
    }
753
754
    #[inline]
755
0
    fn wrapping_add_unsigned_duration(
756
0
        self,
757
0
        duration: UnsignedDuration,
758
0
    ) -> Time {
759
0
        let start = i128::from(self.to_nanosecond());
760
        // OK because 96-bit unsigned integer can't overflow i128.
761
0
        let duration = i128::try_from(duration.as_nanos()).unwrap();
762
0
        let end = (start.wrapping_add(duration)
763
0
            % (b::NANOS_PER_CIVIL_DAY as i128)) as i64;
764
0
        Time::from_nanosecond_unchecked(end)
765
0
    }
766
767
    /// This routine is identical to [`Time::wrapping_add`] with the duration
768
    /// negated.
769
    ///
770
    /// # Example
771
    ///
772
    /// ```
773
    /// use jiff::{civil::time, SignedDuration, ToSpan};
774
    ///
775
    /// let t = time(0, 0, 0, 0);
776
    /// assert_eq!(
777
    ///     t.wrapping_sub(1.nanoseconds()),
778
    ///     time(23, 59, 59, 999_999_999),
779
    /// );
780
    /// assert_eq!(
781
    ///     t.wrapping_sub(SignedDuration::from_nanos(1)),
782
    ///     time(23, 59, 59, 999_999_999),
783
    /// );
784
    /// assert_eq!(
785
    ///     t.wrapping_sub(std::time::Duration::from_nanos(1)),
786
    ///     time(23, 59, 59, 999_999_999),
787
    /// );
788
    ///
789
    /// assert_eq!(
790
    ///     t.wrapping_sub(SignedDuration::MIN),
791
    ///     time(15, 30, 8, 999_999_999),
792
    /// );
793
    /// assert_eq!(
794
    ///     t.wrapping_sub(SignedDuration::MAX),
795
    ///     time(8, 29, 52, 1),
796
    /// );
797
    /// assert_eq!(
798
    ///     t.wrapping_sub(std::time::Duration::MAX),
799
    ///     time(16, 59, 44, 1),
800
    /// );
801
    /// ```
802
    #[inline]
803
0
    pub fn wrapping_sub<A: Into<TimeArithmetic>>(self, duration: A) -> Time {
804
0
        let duration: TimeArithmetic = duration.into();
805
0
        duration.wrapping_sub(self)
806
0
    }
807
808
    #[inline]
809
0
    fn wrapping_sub_unsigned_duration(
810
0
        self,
811
0
        duration: UnsignedDuration,
812
0
    ) -> Time {
813
0
        let start = self.to_nanosecond();
814
        // OK because 96-bit unsigned integer can't overflow i128.
815
0
        let duration = i128::try_from(duration.as_nanos()).unwrap();
816
0
        let duration = (duration % b::NANOS_PER_CIVIL_DAY as i128) as i64;
817
0
        let end =
818
0
            start.wrapping_sub(duration).rem_euclid(b::NANOS_PER_CIVIL_DAY);
819
0
        Time::from_nanosecond_unchecked(end)
820
0
    }
821
822
    /// Add the given span to this time and return an error if the result would
823
    /// otherwise overflow.
824
    ///
825
    /// This operation accepts three different duration types: [`Span`],
826
    /// [`SignedDuration`] or [`std::time::Duration`]. This is achieved via
827
    /// `From` trait implementations for the [`TimeArithmetic`] type.
828
    ///
829
    /// # Properties
830
    ///
831
    /// Given a time `t1` and a span `s`, and assuming `t2 = t1 + s` exists, it
832
    /// follows then that `t1 = t2 - s` for all values of `t1` and `s` that sum
833
    /// to a valid `t2`.
834
    ///
835
    /// In short, subtracting the given span from the sum returned by this
836
    /// function is guaranteed to result in precisely the original time.
837
    ///
838
    /// # Errors
839
    ///
840
    /// If the sum would overflow the minimum or maximum timestamp values, then
841
    /// an error is returned.
842
    ///
843
    /// If the given span has any non-zero units greater than hours, then an
844
    /// error is returned.
845
    ///
846
    /// # Example: add nanoseconds to a `Time`
847
    ///
848
    /// ```
849
    /// use jiff::{civil::time, ToSpan};
850
    ///
851
    /// let t = time(22, 35, 1, 0);
852
    /// assert_eq!(
853
    ///     time(22, 35, 3, 500_000_000),
854
    ///     t.checked_add(2_500_000_000i64.nanoseconds())?,
855
    /// );
856
    /// # Ok::<(), Box<dyn std::error::Error>>(())
857
    /// ```
858
    ///
859
    /// # Example: add span with multiple units
860
    ///
861
    /// ```
862
    /// use jiff::{civil::time, ToSpan};
863
    ///
864
    /// let t = time(20, 10, 1, 0);
865
    /// assert_eq!(
866
    ///     time(22, 0, 0, 0),
867
    ///     t.checked_add(1.hours().minutes(49).seconds(59))?,
868
    /// );
869
    /// # Ok::<(), Box<dyn std::error::Error>>(())
870
    /// ```
871
    ///
872
    /// # Example: adding an empty span is a no-op
873
    ///
874
    /// ```
875
    /// use jiff::{civil::time, Span};
876
    ///
877
    /// let t = time(20, 10, 1, 0);
878
    /// assert_eq!(t, t.checked_add(Span::new())?);
879
    ///
880
    /// # Ok::<(), Box<dyn std::error::Error>>(())
881
    /// ```
882
    ///
883
    /// # Example: error on overflow
884
    ///
885
    /// ```
886
    /// use jiff::{civil::time, ToSpan};
887
    ///
888
    /// // okay
889
    /// let t = time(23, 59, 59, 999_999_998);
890
    /// assert_eq!(
891
    ///     t.with().nanosecond(999).build()?,
892
    ///     t.checked_add(1.nanoseconds())?,
893
    /// );
894
    ///
895
    /// // not okay
896
    /// let t = time(23, 59, 59, 999_999_999);
897
    /// assert!(t.checked_add(1.nanoseconds()).is_err());
898
    ///
899
    /// # Ok::<(), Box<dyn std::error::Error>>(())
900
    /// ```
901
    ///
902
    /// Similarly, if there are any non-zero units greater than hours in the
903
    /// given span, then they also result in overflow (and thus an error):
904
    ///
905
    /// ```
906
    /// use jiff::{civil::time, ToSpan};
907
    ///
908
    /// // doesn't matter what our time value is in this example
909
    /// let t = time(0, 0, 0, 0);
910
    /// assert!(t.checked_add(1.days()).is_err());
911
    /// ```
912
    ///
913
    /// # Example: adding absolute durations
914
    ///
915
    /// This shows how to add signed and unsigned absolute durations to a
916
    /// `Time`. As with adding a `Span`, any overflow that occurs results in
917
    /// an error.
918
    ///
919
    /// ```
920
    /// use std::time::Duration;
921
    ///
922
    /// use jiff::{civil::time, SignedDuration};
923
    ///
924
    /// let t = time(23, 0, 0, 0);
925
    ///
926
    /// let dur = SignedDuration::from_mins(30);
927
    /// assert_eq!(t.checked_add(dur)?, time(23, 30, 0, 0));
928
    /// assert_eq!(t.checked_add(-dur)?, time(22, 30, 0, 0));
929
    ///
930
    /// let dur = Duration::new(0, 1);
931
    /// assert_eq!(t.checked_add(dur)?, time(23, 0, 0, 1));
932
    ///
933
    /// # Ok::<(), Box<dyn std::error::Error>>(())
934
    /// ```
935
    #[inline]
936
0
    pub fn checked_add<A: Into<TimeArithmetic>>(
937
0
        self,
938
0
        duration: A,
939
0
    ) -> Result<Time, Error> {
940
0
        let duration: TimeArithmetic = duration.into();
941
0
        duration.checked_add(self)
942
0
    }
943
944
    #[inline]
945
0
    fn checked_add_span(self, span: &Span) -> Result<Time, Error> {
946
0
        let (time, span) = self.overflowing_add(span)?;
947
0
        if span.smallest_non_time_non_zero_unit_error().is_some() {
948
0
            return Err(Error::from(E::OverflowTimeNanoseconds));
949
0
        }
950
0
        Ok(time)
951
0
    }
952
953
    #[inline]
954
0
    fn checked_add_duration(
955
0
        self,
956
0
        duration: SignedDuration,
957
0
    ) -> Result<Time, Error> {
958
        // NOTE: Every approach here just seems so circuitous...
959
        // Checking when we convert to the same primitive representation.
960
        // Checking when we add.
961
        // Checking that the result is in bounds.
962
        // Just seems very wateful and annoying.
963
0
        let start = self.to_nanosecond();
964
0
        let duration =
965
0
            duration.as_nanos64().ok_or(E::OverflowTimeNanoseconds)?;
966
0
        let end =
967
0
            start.checked_add(duration).ok_or(E::OverflowTimeNanoseconds)?;
968
0
        let end = b::CivilDayNanosecond::check(end)?;
969
        // NOTE: Should this constructor be fallible? I don't think
970
        // so. I think this is the only place we want to check the bounds?
971
0
        Ok(Time::from_nanosecond_unchecked(end))
972
0
    }
973
974
    /// This routine is identical to [`Time::checked_add`] with the duration
975
    /// negated.
976
    ///
977
    /// # Errors
978
    ///
979
    /// This has the same error conditions as [`Time::checked_add`].
980
    ///
981
    /// # Example
982
    ///
983
    /// ```
984
    /// use std::time::Duration;
985
    ///
986
    /// use jiff::{civil::time, SignedDuration, ToSpan};
987
    ///
988
    /// let t = time(22, 0, 0, 0);
989
    /// assert_eq!(
990
    ///     t.checked_sub(1.hours().minutes(49).seconds(59))?,
991
    ///     time(20, 10, 1, 0),
992
    /// );
993
    /// assert_eq!(
994
    ///     t.checked_sub(SignedDuration::from_hours(1))?,
995
    ///     time(21, 0, 0, 0),
996
    /// );
997
    /// assert_eq!(
998
    ///     t.checked_sub(Duration::from_secs(60 * 60))?,
999
    ///     time(21, 0, 0, 0),
1000
    /// );
1001
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1002
    /// ```
1003
    #[inline]
1004
0
    pub fn checked_sub<A: Into<TimeArithmetic>>(
1005
0
        self,
1006
0
        duration: A,
1007
0
    ) -> Result<Time, Error> {
1008
0
        let duration: TimeArithmetic = duration.into();
1009
0
        duration.checked_neg().and_then(|ta| ta.checked_add(self))
1010
0
    }
1011
1012
    /// This routine is identical to [`Time::checked_add`], except the
1013
    /// result saturates on overflow. That is, instead of overflow, either
1014
    /// [`Time::MIN`] or [`Time::MAX`] is returned.
1015
    ///
1016
    /// # Example
1017
    ///
1018
    /// ```
1019
    /// use jiff::{civil::{Time, time}, SignedDuration, ToSpan};
1020
    ///
1021
    /// // no saturation
1022
    /// let t = time(23, 59, 59, 999_999_998);
1023
    /// assert_eq!(
1024
    ///     t.with().nanosecond(999).build()?,
1025
    ///     t.saturating_add(1.nanoseconds()),
1026
    /// );
1027
    ///
1028
    /// // saturates
1029
    /// let t = time(23, 59, 59, 999_999_999);
1030
    /// assert_eq!(Time::MAX, t.saturating_add(1.nanoseconds()));
1031
    /// assert_eq!(Time::MAX, t.saturating_add(SignedDuration::MAX));
1032
    /// assert_eq!(Time::MIN, t.saturating_add(SignedDuration::MIN));
1033
    /// assert_eq!(Time::MAX, t.saturating_add(std::time::Duration::MAX));
1034
    ///
1035
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1036
    /// ```
1037
    ///
1038
    /// Similarly, if there are any non-zero units greater than hours in the
1039
    /// given span, then they also result in overflow (and thus saturation):
1040
    ///
1041
    /// ```
1042
    /// use jiff::{civil::{Time, time}, ToSpan};
1043
    ///
1044
    /// // doesn't matter what our time value is in this example
1045
    /// let t = time(0, 0, 0, 0);
1046
    /// assert_eq!(Time::MAX, t.saturating_add(1.days()));
1047
    /// ```
1048
    #[inline]
1049
0
    pub fn saturating_add<A: Into<TimeArithmetic>>(self, duration: A) -> Time {
1050
0
        let duration: TimeArithmetic = duration.into();
1051
0
        self.checked_add(duration).unwrap_or_else(|_| {
1052
0
            if duration.is_negative() {
1053
0
                Time::MIN
1054
            } else {
1055
0
                Time::MAX
1056
            }
1057
0
        })
1058
0
    }
1059
1060
    /// This routine is identical to [`Time::saturating_add`] with the duration
1061
    /// negated.
1062
    ///
1063
    /// # Example
1064
    ///
1065
    /// ```
1066
    /// use jiff::{civil::{Time, time}, SignedDuration, ToSpan};
1067
    ///
1068
    /// // no saturation
1069
    /// //let t = time(0, 0, 0, 1);
1070
    /// //assert_eq!(
1071
    /// //    t.with().nanosecond(0).build()?,
1072
    /// //    t.saturating_sub(1.nanoseconds()),
1073
    /// //);
1074
    ///
1075
    /// // saturates
1076
    /// let t = time(0, 0, 0, 0);
1077
    /// assert_eq!(Time::MIN, t.saturating_sub(1.nanoseconds()));
1078
    /// //assert_eq!(Time::MIN, t.saturating_sub(SignedDuration::MAX));
1079
    /// //assert_eq!(Time::MAX, t.saturating_sub(SignedDuration::MIN));
1080
    /// //assert_eq!(Time::MIN, t.saturating_sub(std::time::Duration::MAX));
1081
    ///
1082
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1083
    /// ```
1084
    #[inline]
1085
0
    pub fn saturating_sub<A: Into<TimeArithmetic>>(self, duration: A) -> Time {
1086
0
        let duration: TimeArithmetic = duration.into();
1087
0
        let Ok(duration) = duration.checked_neg() else { return Time::MIN };
1088
0
        self.saturating_add(duration)
1089
0
    }
1090
1091
    /// Adds the given span to the this time value, and returns the resulting
1092
    /// time with any overflowing amount in the span returned.
1093
    ///
1094
    /// This isn't part of the public API because it seems a little odd, and
1095
    /// I'm unsure of its use case. Overall this routine is a bit specialized
1096
    /// and I'm not sure how generally useful it is. But it is used in crucial
1097
    /// points in other parts of this crate.
1098
    ///
1099
    /// If you want this public, please file an issue and discuss your use
1100
    /// case: https://github.com/BurntSushi/jiff/issues/new
1101
    #[inline]
1102
0
    pub(crate) fn overflowing_add(
1103
0
        self,
1104
0
        span: &Span,
1105
0
    ) -> Result<(Time, Span), Error> {
1106
0
        if let Some(err) = span.smallest_non_time_non_zero_unit_error() {
1107
0
            return Err(err);
1108
0
        }
1109
1110
0
        let span = span.to_invariant_duration().as_nanos();
1111
0
        let time = i128::from(self.to_nanosecond());
1112
0
        let sum = span + time;
1113
0
        let days = sum.div_euclid(i128::from(b::NANOS_PER_CIVIL_DAY)) as i64;
1114
0
        let rem = sum.rem_euclid(i128::from(b::NANOS_PER_CIVIL_DAY)) as i64;
1115
0
        let span = Span::new().try_days(days)?;
1116
0
        Ok((Time::from_nanosecond_unchecked(rem), span))
1117
0
    }
1118
1119
    /// Like `overflowing_add`, but with `SignedDuration`.
1120
    ///
1121
    /// This is used for datetime arithmetic, when adding to the time
1122
    /// component overflows into days (always 24 hours).
1123
    #[inline]
1124
0
    pub(crate) fn overflowing_add_duration(
1125
0
        self,
1126
0
        duration: SignedDuration,
1127
0
    ) -> Result<(Time, SignedDuration), Error> {
1128
0
        if self.subsec_nanosecond() != 0 || duration.subsec_nanos() != 0 {
1129
0
            return self.overflowing_add_duration_general(duration);
1130
0
        }
1131
0
        let start = i64::from(self.to_second());
1132
0
        let duration_secs = duration.as_secs();
1133
        // This can fail if the duration is near its min or max values, and
1134
        // thus we fall back to the more general (but slower) implementation
1135
        // that uses 128-bit integers.
1136
0
        let Some(sum) = start.checked_add(duration_secs) else {
1137
0
            return self.overflowing_add_duration_general(duration);
1138
        };
1139
0
        let days = b::SpanDays::check(sum.div_euclid(b::SECS_PER_CIVIL_DAY))?;
1140
1141
0
        let rem = sum.rem_euclid(b::SECS_PER_CIVIL_DAY) as i32;
1142
0
        let time = Time::from_second_unchecked(rem);
1143
0
        Ok((time, SignedDuration::from_civil_days32(days)))
1144
0
    }
1145
1146
    /// Like `overflowing_add`, but with `SignedDuration`.
1147
    ///
1148
    /// This is used for datetime arithmetic, when adding to the time
1149
    /// component overflows into days (always 24 hours).
1150
    #[inline(never)]
1151
    #[cold]
1152
0
    fn overflowing_add_duration_general(
1153
0
        self,
1154
0
        duration: SignedDuration,
1155
0
    ) -> Result<(Time, SignedDuration), Error> {
1156
0
        let start = i128::from(self.to_nanosecond());
1157
0
        let duration = duration.as_nanos();
1158
        // This can never fail because the maximum duration fits into a
1159
        // 96-bit integer, and adding any 96-bit integer to any 64-bit
1160
        // integer can never overflow a 128-bit integer.
1161
0
        let sum = start + duration;
1162
0
        let days = b::SpanDays::check128(
1163
0
            sum.div_euclid(i128::from(b::NANOS_PER_CIVIL_DAY)),
1164
0
        )?;
1165
0
        let rem = sum.rem_euclid(i128::from(b::NANOS_PER_CIVIL_DAY)) as i64;
1166
0
        let time = Time::from_nanosecond_unchecked(rem);
1167
0
        Ok((time, SignedDuration::from_civil_days32(days)))
1168
0
    }
1169
1170
    /// Returns a span representing the elapsed time from this time until
1171
    /// the given `other` time.
1172
    ///
1173
    /// When `other` is earlier than this time, the span returned will be
1174
    /// negative.
1175
    ///
1176
    /// Depending on the input provided, the span returned is rounded. It may
1177
    /// also be balanced down to smaller units than the default. By default,
1178
    /// the span returned is balanced such that the biggest possible unit is
1179
    /// hours.
1180
    ///
1181
    /// This operation is configured by providing a [`TimeDifference`]
1182
    /// value. Since this routine accepts anything that implements
1183
    /// `Into<TimeDifference>`, once can pass a `Time` directly. One
1184
    /// can also pass a `(Unit, Time)`, where `Unit` is treated as
1185
    /// [`TimeDifference::largest`].
1186
    ///
1187
    /// # Properties
1188
    ///
1189
    /// As long as no rounding is requested, it is guaranteed that adding the
1190
    /// span returned to the `other` time will always equal this time.
1191
    ///
1192
    /// # Errors
1193
    ///
1194
    /// An error can occur if `TimeDifference` is misconfigured. For example,
1195
    /// if the smallest unit provided is bigger than the largest unit, or if
1196
    /// the largest unit is bigger than [`Unit::Hour`].
1197
    ///
1198
    /// It is guaranteed that if one provides a time with the default
1199
    /// [`TimeDifference`] configuration, then this routine will never fail.
1200
    ///
1201
    /// # Examples
1202
    ///
1203
    /// ```
1204
    /// use jiff::{civil::time, ToSpan};
1205
    ///
1206
    /// let t1 = time(22, 35, 1, 0);
1207
    /// let t2 = time(22, 35, 3, 500_000_000);
1208
    /// assert_eq!(t1.until(t2)?, 2.seconds().milliseconds(500).fieldwise());
1209
    /// // Flipping the dates is fine, but you'll get a negative span.
1210
    /// assert_eq!(t2.until(t1)?, -2.seconds().milliseconds(500).fieldwise());
1211
    ///
1212
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1213
    /// ```
1214
    ///
1215
    /// # Example: using smaller units
1216
    ///
1217
    /// This example shows how to contract the span returned to smaller units.
1218
    /// This makes use of a `From<(Unit, Time)> for TimeDifference`
1219
    /// trait implementation.
1220
    ///
1221
    /// ```
1222
    /// use jiff::{civil::time, Unit, ToSpan};
1223
    ///
1224
    /// let t1 = time(3, 24, 30, 3500);
1225
    /// let t2 = time(15, 30, 0, 0);
1226
    ///
1227
    /// // The default limits spans to using "hours" as the biggest unit.
1228
    /// let span = t1.until(t2)?;
1229
    /// assert_eq!(span.to_string(), "PT12H5M29.9999965S");
1230
    ///
1231
    /// // But we can ask for smaller units, like capping the biggest unit
1232
    /// // to minutes instead of hours.
1233
    /// let span = t1.until((Unit::Minute, t2))?;
1234
    /// assert_eq!(span.to_string(), "PT725M29.9999965S");
1235
    ///
1236
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1237
    /// ```
1238
    #[inline]
1239
0
    pub fn until<A: Into<TimeDifference>>(
1240
0
        self,
1241
0
        other: A,
1242
0
    ) -> Result<Span, Error> {
1243
0
        let args: TimeDifference = other.into();
1244
0
        let span = args.until_with_largest_unit(self)?;
1245
0
        if args.rounding_may_change_span() {
1246
0
            span.round(args.round)
1247
        } else {
1248
0
            Ok(span)
1249
        }
1250
0
    }
1251
1252
    /// This routine is identical to [`Time::until`], but the order of the
1253
    /// parameters is flipped.
1254
    ///
1255
    /// # Errors
1256
    ///
1257
    /// This has the same error conditions as [`Time::until`].
1258
    ///
1259
    /// # Example
1260
    ///
1261
    /// This routine can be used via the `-` operator. Since the default
1262
    /// configuration is used and because a `Span` can represent the difference
1263
    /// between any two possible times, it will never panic.
1264
    ///
1265
    /// ```
1266
    /// use jiff::{civil::time, ToSpan};
1267
    ///
1268
    /// let earlier = time(1, 0, 0, 0);
1269
    /// let later = time(22, 30, 0, 0);
1270
    /// assert_eq!(later - earlier, 21.hours().minutes(30).fieldwise());
1271
    /// ```
1272
    #[inline]
1273
0
    pub fn since<A: Into<TimeDifference>>(
1274
0
        self,
1275
0
        other: A,
1276
0
    ) -> Result<Span, Error> {
1277
0
        let args: TimeDifference = other.into();
1278
0
        let span = -args.until_with_largest_unit(self)?;
1279
0
        if args.rounding_may_change_span() {
1280
0
            span.round(args.round)
1281
        } else {
1282
0
            Ok(span)
1283
        }
1284
0
    }
1285
1286
    /// Returns an absolute duration representing the elapsed time from this
1287
    /// time until the given `other` time.
1288
    ///
1289
    /// When `other` occurs before this time, then the duration returned will
1290
    /// be negative.
1291
    ///
1292
    /// Unlike [`Time::until`], this returns a duration corresponding to a
1293
    /// 96-bit integer of nanoseconds between two times. In this case of
1294
    /// computing durations between civil times where all days are assumed to
1295
    /// be 24 hours long, the duration returned will always be less than 24
1296
    /// hours.
1297
    ///
1298
    /// # Fallibility
1299
    ///
1300
    /// This routine never panics or returns an error. Since there are no
1301
    /// configuration options that can be incorrectly provided, no error is
1302
    /// possible when calling this routine. In contrast, [`Time::until`] can
1303
    /// return an error in some cases due to misconfiguration. But like this
1304
    /// routine, [`Time::until`] never panics or returns an error in its
1305
    /// default configuration.
1306
    ///
1307
    /// # When should I use this versus [`Time::until`]?
1308
    ///
1309
    /// See the type documentation for [`SignedDuration`] for the section on
1310
    /// when one should use [`Span`] and when one should use `SignedDuration`.
1311
    /// In short, use `Span` (and therefore `Time::until`) unless you have a
1312
    /// specific reason to do otherwise.
1313
    ///
1314
    /// # Example
1315
    ///
1316
    /// ```
1317
    /// use jiff::{civil::time, SignedDuration};
1318
    ///
1319
    /// let t1 = time(22, 35, 1, 0);
1320
    /// let t2 = time(22, 35, 3, 500_000_000);
1321
    /// assert_eq!(t1.duration_until(t2), SignedDuration::new(2, 500_000_000));
1322
    /// // Flipping the time is fine, but you'll get a negative duration.
1323
    /// assert_eq!(t2.duration_until(t1), -SignedDuration::new(2, 500_000_000));
1324
    /// ```
1325
    ///
1326
    /// # Example: difference with [`Time::until`]
1327
    ///
1328
    /// Since the difference between two civil times is always expressed in
1329
    /// units of hours or smaller, and units of hours or smaller are always
1330
    /// uniform, there is no "expressive" difference between this routine and
1331
    /// `Time::until`. The only difference is that this routine returns a
1332
    /// `SignedDuration` and `Time::until` returns a [`Span`]. Moreover, since
1333
    /// the difference is always less than 24 hours, the return values can
1334
    /// always be infallibly and losslessly converted between each other:
1335
    ///
1336
    /// ```
1337
    /// use jiff::{civil::time, SignedDuration, Span};
1338
    ///
1339
    /// let t1 = time(22, 35, 1, 0);
1340
    /// let t2 = time(22, 35, 3, 500_000_000);
1341
    /// let dur = t1.duration_until(t2);
1342
    /// // Guaranteed to never fail because the duration
1343
    /// // between two civil times never exceeds the limits
1344
    /// // of a `Span`.
1345
    /// let span = Span::try_from(dur).unwrap();
1346
    /// assert_eq!(span, Span::new().seconds(2).milliseconds(500).fieldwise());
1347
    /// // Guaranteed to succeed and always return the original
1348
    /// // duration because the units are always hours or smaller,
1349
    /// // and thus uniform. This means a relative datetime is
1350
    /// // never required to do this conversion.
1351
    /// let dur = SignedDuration::try_from(span).unwrap();
1352
    /// assert_eq!(dur, SignedDuration::new(2, 500_000_000));
1353
    /// ```
1354
    ///
1355
    /// This conversion guarantee also applies to [`Time::until`] since it
1356
    /// always returns a balanced span. That is, it never returns spans like
1357
    /// `1 second 1000 milliseconds`. (Those cannot be losslessly converted to
1358
    /// a `SignedDuration` since a `SignedDuration` is only represented as a
1359
    /// single 96-bit integer of nanoseconds.)
1360
    ///
1361
    /// # Example: getting an unsigned duration
1362
    ///
1363
    /// If you're looking to find the duration between two times as a
1364
    /// [`std::time::Duration`], you'll need to use this method to get a
1365
    /// [`SignedDuration`] and then convert it to a `std::time::Duration`:
1366
    ///
1367
    /// ```
1368
    /// use std::time::Duration;
1369
    ///
1370
    /// use jiff::{civil::time, SignedDuration, Span};
1371
    ///
1372
    /// let t1 = time(22, 35, 1, 0);
1373
    /// let t2 = time(22, 35, 3, 500_000_000);
1374
    /// let dur = Duration::try_from(t1.duration_until(t2))?;;
1375
    /// assert_eq!(dur, Duration::new(2, 500_000_000));
1376
    ///
1377
    /// // Note that unsigned durations cannot represent all
1378
    /// // possible differences! If the duration would be negative,
1379
    /// // then the conversion fails:
1380
    /// assert!(Duration::try_from(t2.duration_until(t1)).is_err());
1381
    ///
1382
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1383
    /// ```
1384
    #[inline]
1385
0
    pub fn duration_until(self, other: Time) -> SignedDuration {
1386
0
        SignedDuration::time_until(self, other)
1387
0
    }
1388
1389
    /// This routine is identical to [`Time::duration_until`], but the order of
1390
    /// the parameters is flipped.
1391
    ///
1392
    /// # Example
1393
    ///
1394
    /// ```
1395
    /// use jiff::{civil::time, SignedDuration};
1396
    ///
1397
    /// let earlier = time(1, 0, 0, 0);
1398
    /// let later = time(22, 30, 0, 0);
1399
    /// assert_eq!(
1400
    ///     later.duration_since(earlier),
1401
    ///     SignedDuration::from_secs((21 * 60 * 60) + (30 * 60)),
1402
    /// );
1403
    /// ```
1404
    #[inline]
1405
0
    pub fn duration_since(self, other: Time) -> SignedDuration {
1406
0
        SignedDuration::time_until(other, self)
1407
0
    }
1408
1409
    /// Rounds this time according to the [`TimeRound`] configuration given.
1410
    ///
1411
    /// The principal option is [`TimeRound::smallest`], which allows one
1412
    /// to configure the smallest units in the returned time. Rounding
1413
    /// is what determines whether that unit should keep its current value
1414
    /// or whether it should be incremented. Moreover, the amount it should
1415
    /// be incremented can be configured via [`TimeRound::increment`].
1416
    /// Finally, the rounding strategy itself can be configured via
1417
    /// [`TimeRound::mode`].
1418
    ///
1419
    /// Note that this routine is generic and accepts anything that
1420
    /// implements `Into<TimeRound>`. Some notable implementations are:
1421
    ///
1422
    /// * `From<Unit> for Round`, which will automatically create a
1423
    /// `TimeRound::new().smallest(unit)` from the unit provided.
1424
    /// * `From<(Unit, i64)> for Round`, which will automatically create a
1425
    /// `TimeRound::new().smallest(unit).increment(number)` from the unit
1426
    /// and increment provided.
1427
    ///
1428
    /// # Errors
1429
    ///
1430
    /// This returns an error if the smallest unit configured on the given
1431
    /// [`TimeRound`] is bigger than hours.
1432
    ///
1433
    /// The rounding increment must divide evenly into the next highest unit
1434
    /// after the smallest unit configured (and must not be equivalent to it).
1435
    /// For example, if the smallest unit is [`Unit::Nanosecond`], then *some*
1436
    /// of the valid values for the rounding increment are `1`, `2`, `4`, `5`,
1437
    /// `100` and `500`. Namely, any integer that divides evenly into `1,000`
1438
    /// nanoseconds since there are `1,000` nanoseconds in the next highest
1439
    /// unit (microseconds).
1440
    ///
1441
    /// This can never fail because of overflow for any input. The only
1442
    /// possible errors are "configuration" errors.
1443
    ///
1444
    /// # Example
1445
    ///
1446
    /// This is a basic example that demonstrates rounding a datetime to the
1447
    /// nearest second. This also demonstrates calling this method with the
1448
    /// smallest unit directly, instead of constructing a `TimeRound` manually.
1449
    ///
1450
    /// ```
1451
    /// use jiff::{civil::time, Unit};
1452
    ///
1453
    /// let t = time(15, 45, 10, 123_456_789);
1454
    /// assert_eq!(
1455
    ///     t.round(Unit::Second)?,
1456
    ///     time(15, 45, 10, 0),
1457
    /// );
1458
    /// let t = time(15, 45, 10, 500_000_001);
1459
    /// assert_eq!(
1460
    ///     t.round(Unit::Second)?,
1461
    ///     time(15, 45, 11, 0),
1462
    /// );
1463
    ///
1464
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1465
    /// ```
1466
    ///
1467
    /// # Example: changing the rounding mode
1468
    ///
1469
    /// The default rounding mode is [`RoundMode::HalfExpand`], which
1470
    /// breaks ties by rounding away from zero. But other modes like
1471
    /// [`RoundMode::Trunc`] can be used too:
1472
    ///
1473
    /// ```
1474
    /// use jiff::{civil::{TimeRound, time}, RoundMode, Unit};
1475
    ///
1476
    /// let t = time(15, 45, 10, 999_999_999);
1477
    /// assert_eq!(
1478
    ///     t.round(Unit::Second)?,
1479
    ///     time(15, 45, 11, 0),
1480
    /// );
1481
    /// // The default will round up to the next second for any fraction
1482
    /// // greater than or equal to 0.5. But truncation will always round
1483
    /// // toward zero.
1484
    /// assert_eq!(
1485
    ///     t.round(
1486
    ///         TimeRound::new().smallest(Unit::Second).mode(RoundMode::Trunc),
1487
    ///     )?,
1488
    ///     time(15, 45, 10, 0),
1489
    /// );
1490
    ///
1491
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1492
    /// ```
1493
    ///
1494
    /// # Example: rounding to the nearest 5 minute increment
1495
    ///
1496
    /// ```
1497
    /// use jiff::{civil::time, Unit};
1498
    ///
1499
    /// // rounds down
1500
    /// let t = time(15, 27, 29, 999_999_999);
1501
    /// assert_eq!(t.round((Unit::Minute, 5))?, time(15, 25, 0, 0));
1502
    /// // rounds up
1503
    /// let t = time(15, 27, 30, 0);
1504
    /// assert_eq!(t.round((Unit::Minute, 5))?, time(15, 30, 0, 0));
1505
    ///
1506
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1507
    /// ```
1508
    ///
1509
    /// # Example: rounding wraps around on overflow
1510
    ///
1511
    /// This example demonstrates that it's possible for this operation to
1512
    /// overflow, and as a result, have the time wrap around.
1513
    ///
1514
    /// ```
1515
    /// use jiff::{civil::Time, Unit};
1516
    ///
1517
    /// let t = Time::MAX;
1518
    /// assert_eq!(t.round(Unit::Hour)?, Time::MIN);
1519
    ///
1520
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1521
    /// ```
1522
    #[inline]
1523
0
    pub fn round<R: Into<TimeRound>>(self, options: R) -> Result<Time, Error> {
1524
0
        let options: TimeRound = options.into();
1525
0
        options.round(self)
1526
0
    }
1527
1528
    /// Return an iterator of periodic times determined by the given span.
1529
    ///
1530
    /// The given span may be negative, in which case, the iterator will move
1531
    /// backwards through time. The iterator won't stop until either the span
1532
    /// itself overflows, or it would otherwise exceed the minimum or maximum
1533
    /// `Time` value.
1534
    ///
1535
    /// # Example: visiting every third hour
1536
    ///
1537
    /// This shows how to visit each third hour of a 24 hour time interval:
1538
    ///
1539
    /// ```
1540
    /// use jiff::{civil::{Time, time}, ToSpan};
1541
    ///
1542
    /// let start = Time::MIN;
1543
    /// let mut every_third_hour = vec![];
1544
    /// for t in start.series(3.hours()) {
1545
    ///     every_third_hour.push(t);
1546
    /// }
1547
    /// assert_eq!(every_third_hour, vec![
1548
    ///     time(0, 0, 0, 0),
1549
    ///     time(3, 0, 0, 0),
1550
    ///     time(6, 0, 0, 0),
1551
    ///     time(9, 0, 0, 0),
1552
    ///     time(12, 0, 0, 0),
1553
    ///     time(15, 0, 0, 0),
1554
    ///     time(18, 0, 0, 0),
1555
    ///     time(21, 0, 0, 0),
1556
    /// ]);
1557
    /// ```
1558
    ///
1559
    /// Or go backwards every 6.5 hours:
1560
    ///
1561
    /// ```
1562
    /// use jiff::{civil::{Time, time}, ToSpan};
1563
    ///
1564
    /// let start = time(23, 0, 0, 0);
1565
    /// let times: Vec<Time> = start.series(-6.hours().minutes(30)).collect();
1566
    /// assert_eq!(times, vec![
1567
    ///     time(23, 0, 0, 0),
1568
    ///     time(16, 30, 0, 0),
1569
    ///     time(10, 0, 0, 0),
1570
    ///     time(3, 30, 0, 0),
1571
    /// ]);
1572
    /// ```
1573
    #[inline]
1574
0
    pub fn series(self, period: Span) -> TimeSeries {
1575
0
        TimeSeries { start: self, period, step: 0 }
1576
0
    }
1577
}
1578
1579
/// Parsing and formatting using a "printf"-style API.
1580
impl Time {
1581
    /// Parses a civil time in `input` matching the given `format`.
1582
    ///
1583
    /// The format string uses a "printf"-style API where conversion
1584
    /// specifiers can be used as place holders to match components of
1585
    /// a datetime. For details on the specifiers supported, see the
1586
    /// [`fmt::strtime`] module documentation.
1587
    ///
1588
    /// # Errors
1589
    ///
1590
    /// This returns an error when parsing failed. This might happen because
1591
    /// the format string itself was invalid, or because the input didn't match
1592
    /// the format string.
1593
    ///
1594
    /// This also returns an error if there wasn't sufficient information to
1595
    /// construct a civil time. For example, if an offset wasn't parsed.
1596
    ///
1597
    /// # Example
1598
    ///
1599
    /// This example shows how to parse a civil time:
1600
    ///
1601
    /// ```
1602
    /// use jiff::civil::Time;
1603
    ///
1604
    /// // Parse with a 12-hour clock.
1605
    /// let time = Time::strptime("%I:%M%P", "4:30pm")?;
1606
    /// assert_eq!(time.to_string(), "16:30:00");
1607
    ///
1608
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1609
    /// ```
1610
    #[inline]
1611
0
    pub fn strptime(
1612
0
        format: impl AsRef<[u8]>,
1613
0
        input: impl AsRef<[u8]>,
1614
0
    ) -> Result<Time, Error> {
1615
0
        fmt::strtime::parse(format, input).and_then(|tm| tm.to_time())
1616
0
    }
1617
1618
    /// Formats this civil time according to the given `format`.
1619
    ///
1620
    /// The format string uses a "printf"-style API where conversion
1621
    /// specifiers can be used as place holders to format components of
1622
    /// a datetime. For details on the specifiers supported, see the
1623
    /// [`fmt::strtime`] module documentation.
1624
    ///
1625
    /// # Errors and panics
1626
    ///
1627
    /// While this routine itself does not error or panic, using the value
1628
    /// returned may result in a panic if formatting fails. See the
1629
    /// documentation on [`fmt::strtime::Display`] for more information.
1630
    ///
1631
    /// To format in a way that surfaces errors without panicking, use either
1632
    /// [`fmt::strtime::format`] or [`fmt::strtime::BrokenDownTime::format`].
1633
    ///
1634
    /// # Example
1635
    ///
1636
    /// This example shows how to format a civil time in a 12 hour clock with
1637
    /// no padding for the hour:
1638
    ///
1639
    /// ```
1640
    /// use jiff::civil::time;
1641
    ///
1642
    /// let t = time(16, 30, 59, 0);
1643
    /// let string = t.strftime("%-I:%M%P").to_string();
1644
    /// assert_eq!(string, "4:30pm");
1645
    /// ```
1646
    ///
1647
    /// Note that one can round a `Time` before formatting. For example, to
1648
    /// round to the nearest minute:
1649
    ///
1650
    /// ```
1651
    /// use jiff::{civil::time, Unit};
1652
    ///
1653
    /// let t = time(16, 30, 59, 0);
1654
    /// let string = t.round(Unit::Minute)?.strftime("%-I:%M%P").to_string();
1655
    /// assert_eq!(string, "4:31pm");
1656
    ///
1657
    /// # Ok::<(), Box<dyn std::error::Error>>(())
1658
    /// ```
1659
    #[inline]
1660
0
    pub fn strftime<'f, F: 'f + ?Sized + AsRef<[u8]>>(
1661
0
        &self,
1662
0
        format: &'f F,
1663
0
    ) -> fmt::strtime::Display<'f> {
1664
0
        fmt::strtime::Display { fmt: format.as_ref(), tm: (*self).into() }
1665
0
    }
1666
}
1667
1668
/// Crate internal APIs.
1669
///
1670
/// Many of these are mirrors of the public API, but on ranged types. These
1671
/// are often much more convenient to use in composition with other parts of
1672
/// the crate that also use ranged integer types. And this often permits the
1673
/// routines to be infallible and (possibly) zero-cost.
1674
impl Time {
1675
    /// Set the fractional parts of this time to the given units.
1676
    ///
1677
    /// Callers must ensure that each integer is in the range `0..=999`.
1678
    #[inline]
1679
0
    fn with_subsec_parts_unchecked(
1680
0
        self,
1681
0
        millisecond: i16,
1682
0
        microsecond: i16,
1683
0
        nanosecond: i16,
1684
0
    ) -> Time {
1685
0
        let subsec_nanosecond = (i32::from(millisecond)
1686
0
            * b::NANOS_PER_MILLI_32)
1687
0
            + (i32::from(microsecond) * b::NANOS_PER_MICRO_32)
1688
0
            + i32::from(nanosecond);
1689
0
        Time { subsec_nanosecond, ..self }
1690
0
    }
1691
1692
    #[inline]
1693
0
    pub(crate) fn until_nanoseconds(self, other: Time) -> i64 {
1694
0
        other.to_nanosecond() - self.to_nanosecond()
1695
0
    }
1696
1697
    /// Converts this time value to the number of seconds that has elapsed
1698
    /// since `00:00:00`. This completely ignores seconds. Callers should
1699
    /// likely ensure that the fractional second component is zero.
1700
    ///
1701
    /// The maximum possible value that can be returned represents the time
1702
    /// `23:59:59`.
1703
    #[inline]
1704
0
    pub(crate) fn to_second(&self) -> i32 {
1705
0
        self.to_itime_const().to_second().second
1706
0
    }
1707
1708
    /// Converts the given second to a time value. The second should correspond
1709
    /// to the number of seconds that have elapsed since `00:00:00`. The
1710
    /// fractional second component of the `Time` returned is always `0`.
1711
    ///
1712
    /// Callers must ensure that the given `second` is valid for
1713
    /// `b::CivilDaySecond`.
1714
    #[cfg_attr(feature = "perf-inline", inline(always))]
1715
0
    pub(crate) fn from_second_unchecked(second: i32) -> Time {
1716
0
        debug_assert!(b::CivilDaySecond::check(second).is_ok());
1717
0
        Time::from_itime_const(ITimeSecond { second }.to_time())
1718
0
    }
1719
1720
    /// Converts this time value to the number of nanoseconds that has elapsed
1721
    /// since `00:00:00.000000000`.
1722
    ///
1723
    /// The maximum possible value that can be returned represents the time
1724
    /// `23:59:59.999999999`.
1725
    #[inline]
1726
0
    pub(crate) fn to_nanosecond(&self) -> i64 {
1727
0
        self.to_itime_const().to_nanosecond().nanosecond
1728
0
    }
1729
1730
    #[inline]
1731
0
    pub(crate) fn to_duration(&self) -> SignedDuration {
1732
0
        let mut dur = SignedDuration::from_hours(i64::from(self.hour()));
1733
0
        dur += SignedDuration::from_mins(i64::from(self.minute()));
1734
0
        dur += SignedDuration::from_secs(i64::from(self.second()));
1735
0
        dur += SignedDuration::new_without_nano_overflow(
1736
0
            0,
1737
0
            self.subsec_nanosecond(),
1738
0
        );
1739
0
        dur
1740
0
    }
1741
1742
    /// Converts the given nanosecond to a time value. The nanosecond should
1743
    /// correspond to the number of nanoseconds that have elapsed since
1744
    /// `00:00:00.000000000`.
1745
    ///
1746
    /// Callers must ensure that the given `nanosecond` is valid for
1747
    /// `b::CivilDayNanosecond`.
1748
    #[cfg_attr(feature = "perf-inline", inline(always))]
1749
0
    pub(crate) fn from_nanosecond_unchecked(nanosecond: i64) -> Time {
1750
0
        debug_assert!(b::CivilDayNanosecond::check(nanosecond).is_ok());
1751
0
        Time::from_itime_const(ITimeNanosecond { nanosecond }.to_time())
1752
0
    }
1753
1754
    /// Like `from_nanosecond_unchecked`, but for a signed duration.
1755
    #[cfg_attr(feature = "perf-inline", inline(always))]
1756
0
    pub(crate) fn from_duration_unchecked(dur: SignedDuration) -> Time {
1757
0
        let second = dur.as_secs();
1758
0
        debug_assert!(b::CivilDaySecond::check(second).is_ok());
1759
0
        let mut time = ITimeSecond { second: second as i32 }.to_time();
1760
0
        time.subsec_nanosecond = dur.subsec_nanos();
1761
0
        Time::from_itime_const(time)
1762
0
    }
1763
1764
    #[inline]
1765
2.84k
    pub(crate) const fn to_itime_const(&self) -> ITime {
1766
2.84k
        ITime {
1767
2.84k
            hour: self.hour,
1768
2.84k
            minute: self.minute,
1769
2.84k
            second: self.second,
1770
2.84k
            subsec_nanosecond: self.subsec_nanosecond,
1771
2.84k
        }
1772
2.84k
    }
1773
1774
    #[inline]
1775
4.22k
    pub(crate) const fn from_itime_const(itime: ITime) -> Time {
1776
4.22k
        Time {
1777
4.22k
            hour: itime.hour,
1778
4.22k
            minute: itime.minute,
1779
4.22k
            second: itime.second,
1780
4.22k
            subsec_nanosecond: itime.subsec_nanosecond,
1781
4.22k
        }
1782
4.22k
    }
1783
}
1784
1785
impl Default for Time {
1786
    #[inline]
1787
0
    fn default() -> Time {
1788
0
        Time::midnight()
1789
0
    }
1790
}
1791
1792
/// Converts a `Time` into a human readable time string.
1793
///
1794
/// (This `Debug` representation currently emits the same string as the
1795
/// `Display` representation, but this is not a guarantee.)
1796
///
1797
/// Options currently supported:
1798
///
1799
/// * [`std::fmt::Formatter::precision`] can be set to control the precision
1800
/// of the fractional second component.
1801
///
1802
/// # Example
1803
///
1804
/// ```
1805
/// use jiff::civil::time;
1806
///
1807
/// let t = time(7, 0, 0, 123_000_000);
1808
/// assert_eq!(format!("{t:.6?}"), "07:00:00.123000");
1809
/// // Precision values greater than 9 are clamped to 9.
1810
/// assert_eq!(format!("{t:.300?}"), "07:00:00.123000000");
1811
/// // A precision of 0 implies the entire fractional
1812
/// // component is always truncated.
1813
/// assert_eq!(format!("{t:.0?}"), "07:00:00");
1814
///
1815
/// # Ok::<(), Box<dyn std::error::Error>>(())
1816
/// ```
1817
impl core::fmt::Debug for Time {
1818
    #[inline]
1819
0
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1820
0
        core::fmt::Display::fmt(self, f)
1821
0
    }
1822
}
1823
1824
/// Converts a `Time` into an ISO 8601 compliant string.
1825
///
1826
/// # Formatting options supported
1827
///
1828
/// * [`std::fmt::Formatter::precision`] can be set to control the precision
1829
/// of the fractional second component. When not set, the minimum precision
1830
/// required to losslessly render the value is used.
1831
///
1832
/// # Example
1833
///
1834
/// ```
1835
/// use jiff::civil::time;
1836
///
1837
/// // No fractional seconds:
1838
/// let t = time(7, 0, 0, 0);
1839
/// assert_eq!(format!("{t}"), "07:00:00");
1840
///
1841
/// // With fractional seconds:
1842
/// let t = time(7, 0, 0, 123_000_000);
1843
/// assert_eq!(format!("{t}"), "07:00:00.123");
1844
///
1845
/// # Ok::<(), Box<dyn std::error::Error>>(())
1846
/// ```
1847
///
1848
/// # Example: setting the precision
1849
///
1850
/// ```
1851
/// use jiff::civil::time;
1852
///
1853
/// let t = time(7, 0, 0, 123_000_000);
1854
/// assert_eq!(format!("{t:.6}"), "07:00:00.123000");
1855
/// // Precision values greater than 9 are clamped to 9.
1856
/// assert_eq!(format!("{t:.300}"), "07:00:00.123000000");
1857
/// // A precision of 0 implies the entire fractional
1858
/// // component is always truncated.
1859
/// assert_eq!(format!("{t:.0}"), "07:00:00");
1860
///
1861
/// # Ok::<(), Box<dyn std::error::Error>>(())
1862
/// ```
1863
impl core::fmt::Display for Time {
1864
    #[inline]
1865
0
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1866
        use crate::fmt::StdFmtWrite;
1867
1868
0
        let precision =
1869
0
            f.precision().map(|p| u8::try_from(p).unwrap_or(u8::MAX));
1870
0
        temporal::DateTimePrinter::new()
1871
0
            .precision(precision)
1872
0
            .print_time(self, StdFmtWrite(f))
1873
0
            .map_err(|_| core::fmt::Error)
1874
0
    }
1875
}
1876
1877
impl core::str::FromStr for Time {
1878
    type Err = Error;
1879
1880
    #[inline]
1881
0
    fn from_str(string: &str) -> Result<Time, Error> {
1882
0
        DEFAULT_DATETIME_PARSER.parse_time(string)
1883
0
    }
1884
}
1885
1886
/// Adds a span of time. This uses wrapping arithmetic.
1887
///
1888
/// For checked arithmetic, see [`Time::checked_add`].
1889
impl core::ops::Add<Span> for Time {
1890
    type Output = Time;
1891
1892
    #[inline]
1893
0
    fn add(self, rhs: Span) -> Time {
1894
0
        self.wrapping_add(rhs)
1895
0
    }
1896
}
1897
1898
/// Adds a span of time in place. This uses wrapping arithmetic.
1899
///
1900
/// For checked arithmetic, see [`Time::checked_add`].
1901
impl core::ops::AddAssign<Span> for Time {
1902
    #[inline]
1903
0
    fn add_assign(&mut self, rhs: Span) {
1904
0
        *self = *self + rhs;
1905
0
    }
1906
}
1907
1908
/// Subtracts a span of time. This uses wrapping arithmetic.
1909
///
1910
/// For checked arithmetic, see [`Time::checked_sub`].
1911
impl core::ops::Sub<Span> for Time {
1912
    type Output = Time;
1913
1914
    #[inline]
1915
0
    fn sub(self, rhs: Span) -> Time {
1916
0
        self.wrapping_sub(rhs)
1917
0
    }
1918
}
1919
1920
/// Subtracts a span of time in place. This uses wrapping arithmetic.
1921
///
1922
/// For checked arithmetic, see [`Time::checked_sub`].
1923
impl core::ops::SubAssign<Span> for Time {
1924
    #[inline]
1925
0
    fn sub_assign(&mut self, rhs: Span) {
1926
0
        *self = *self - rhs;
1927
0
    }
1928
}
1929
1930
/// Computes the span of time between two times.
1931
///
1932
/// This will return a negative span when the time being subtracted is greater.
1933
///
1934
/// Since this uses the default configuration for calculating a span between
1935
/// two times (no rounding and largest units is hours), this will never panic
1936
/// or fail in any way.
1937
///
1938
/// To configure the largest unit or enable rounding, use [`Time::since`].
1939
impl core::ops::Sub for Time {
1940
    type Output = Span;
1941
1942
    #[inline]
1943
0
    fn sub(self, rhs: Time) -> Span {
1944
0
        self.since(rhs).expect("since never fails when given Time")
1945
0
    }
1946
}
1947
1948
/// Adds a signed duration of time. This uses wrapping arithmetic.
1949
///
1950
/// For checked arithmetic, see [`Time::checked_add`].
1951
impl core::ops::Add<SignedDuration> for Time {
1952
    type Output = Time;
1953
1954
    #[inline]
1955
0
    fn add(self, rhs: SignedDuration) -> Time {
1956
0
        self.wrapping_add(rhs)
1957
0
    }
1958
}
1959
1960
/// Adds a signed duration of time in place. This uses wrapping arithmetic.
1961
///
1962
/// For checked arithmetic, see [`Time::checked_add`].
1963
impl core::ops::AddAssign<SignedDuration> for Time {
1964
    #[inline]
1965
0
    fn add_assign(&mut self, rhs: SignedDuration) {
1966
0
        *self = *self + rhs;
1967
0
    }
1968
}
1969
1970
/// Subtracts a signed duration of time. This uses wrapping arithmetic.
1971
///
1972
/// For checked arithmetic, see [`Time::checked_sub`].
1973
impl core::ops::Sub<SignedDuration> for Time {
1974
    type Output = Time;
1975
1976
    #[inline]
1977
0
    fn sub(self, rhs: SignedDuration) -> Time {
1978
0
        self.wrapping_sub(rhs)
1979
0
    }
1980
}
1981
1982
/// Subtracts a signed duration of time in place. This uses wrapping arithmetic.
1983
///
1984
/// For checked arithmetic, see [`Time::checked_sub`].
1985
impl core::ops::SubAssign<SignedDuration> for Time {
1986
    #[inline]
1987
0
    fn sub_assign(&mut self, rhs: SignedDuration) {
1988
0
        *self = *self - rhs;
1989
0
    }
1990
}
1991
1992
/// Adds an unsigned duration of time. This uses wrapping arithmetic.
1993
///
1994
/// For checked arithmetic, see [`Time::checked_add`].
1995
impl core::ops::Add<UnsignedDuration> for Time {
1996
    type Output = Time;
1997
1998
    #[inline]
1999
0
    fn add(self, rhs: UnsignedDuration) -> Time {
2000
0
        self.wrapping_add(rhs)
2001
0
    }
2002
}
2003
2004
/// Adds an unsigned duration of time in place. This uses wrapping arithmetic.
2005
///
2006
/// For checked arithmetic, see [`Time::checked_add`].
2007
impl core::ops::AddAssign<UnsignedDuration> for Time {
2008
    #[inline]
2009
0
    fn add_assign(&mut self, rhs: UnsignedDuration) {
2010
0
        *self = *self + rhs;
2011
0
    }
2012
}
2013
2014
/// Subtracts an unsigned duration of time. This uses wrapping arithmetic.
2015
///
2016
/// For checked arithmetic, see [`Time::checked_sub`].
2017
impl core::ops::Sub<UnsignedDuration> for Time {
2018
    type Output = Time;
2019
2020
    #[inline]
2021
0
    fn sub(self, rhs: UnsignedDuration) -> Time {
2022
0
        self.wrapping_sub(rhs)
2023
0
    }
2024
}
2025
2026
/// Subtracts an unsigned duration of time in place. This uses wrapping
2027
/// arithmetic.
2028
///
2029
/// For checked arithmetic, see [`Time::checked_sub`].
2030
impl core::ops::SubAssign<UnsignedDuration> for Time {
2031
    #[inline]
2032
0
    fn sub_assign(&mut self, rhs: UnsignedDuration) {
2033
0
        *self = *self - rhs;
2034
0
    }
2035
}
2036
2037
impl From<DateTime> for Time {
2038
    #[inline]
2039
0
    fn from(dt: DateTime) -> Time {
2040
0
        dt.time()
2041
0
    }
2042
}
2043
2044
impl From<Zoned> for Time {
2045
    #[inline]
2046
0
    fn from(zdt: Zoned) -> Time {
2047
0
        zdt.datetime().time()
2048
0
    }
2049
}
2050
2051
impl<'a> From<&'a Zoned> for Time {
2052
    #[inline]
2053
0
    fn from(zdt: &'a Zoned) -> Time {
2054
0
        zdt.datetime().time()
2055
0
    }
2056
}
2057
2058
#[cfg(feature = "defmt")]
2059
impl defmt::Format for Time {
2060
    fn format(&self, f: defmt::Formatter) {
2061
        use crate::fmt::{temporal::DEFAULT_DATETIME_PRINTER, DefmtWrite};
2062
2063
        defmt::unwrap!(
2064
            DEFAULT_DATETIME_PRINTER.print_time(self, DefmtWrite(f))
2065
        );
2066
    }
2067
}
2068
2069
#[cfg(feature = "serde")]
2070
impl serde_core::Serialize for Time {
2071
    #[inline]
2072
    fn serialize<S: serde_core::Serializer>(
2073
        &self,
2074
        serializer: S,
2075
    ) -> Result<S::Ok, S::Error> {
2076
        serializer.collect_str(self)
2077
    }
2078
}
2079
2080
#[cfg(feature = "serde")]
2081
impl<'de> serde_core::Deserialize<'de> for Time {
2082
    #[inline]
2083
    fn deserialize<D: serde_core::Deserializer<'de>>(
2084
        deserializer: D,
2085
    ) -> Result<Time, D::Error> {
2086
        use serde_core::de;
2087
2088
        struct TimeVisitor;
2089
2090
        impl<'de> de::Visitor<'de> for TimeVisitor {
2091
            type Value = Time;
2092
2093
            fn expecting(
2094
                &self,
2095
                f: &mut core::fmt::Formatter,
2096
            ) -> core::fmt::Result {
2097
                f.write_str("a time string")
2098
            }
2099
2100
            #[inline]
2101
            fn visit_bytes<E: de::Error>(
2102
                self,
2103
                value: &[u8],
2104
            ) -> Result<Time, E> {
2105
                DEFAULT_DATETIME_PARSER
2106
                    .parse_time(value)
2107
                    .map_err(de::Error::custom)
2108
            }
2109
2110
            #[inline]
2111
            fn visit_str<E: de::Error>(self, value: &str) -> Result<Time, E> {
2112
                self.visit_bytes(value.as_bytes())
2113
            }
2114
        }
2115
2116
        deserializer.deserialize_str(TimeVisitor)
2117
    }
2118
}
2119
2120
#[cfg(test)]
2121
impl quickcheck::Arbitrary for Time {
2122
    fn arbitrary(g: &mut quickcheck::Gen) -> Time {
2123
        let hour = b::Hour::arbitrary(g);
2124
        let minute = b::Minute::arbitrary(g);
2125
        let second = b::Second::arbitrary(g);
2126
        let subsec_nanosecond = b::SubsecNanosecond::arbitrary(g);
2127
        Time::new(hour, minute, second, subsec_nanosecond).unwrap()
2128
    }
2129
2130
    fn shrink(&self) -> alloc::boxed::Box<dyn Iterator<Item = Time>> {
2131
        alloc::boxed::Box::new(
2132
            (
2133
                self.hour(),
2134
                self.minute(),
2135
                self.second(),
2136
                self.subsec_nanosecond(),
2137
            )
2138
                .shrink()
2139
                .filter_map(
2140
                    |(hour, minute, second, subsec_nanosecond)| {
2141
                        Time::new(hour, minute, second, subsec_nanosecond).ok()
2142
                    },
2143
                ),
2144
        )
2145
    }
2146
}
2147
2148
/// An iterator over periodic times, created by [`Time::series`].
2149
///
2150
/// It is exhausted when the next value would exceed the limits of a [`Span`]
2151
/// or [`Time`] value.
2152
///
2153
/// This iterator is created by [`Time::series`].
2154
#[derive(Clone, Debug)]
2155
pub struct TimeSeries {
2156
    start: Time,
2157
    period: Span,
2158
    step: i64,
2159
}
2160
2161
impl Iterator for TimeSeries {
2162
    type Item = Time;
2163
2164
    #[inline]
2165
0
    fn next(&mut self) -> Option<Time> {
2166
0
        let span = self.period.checked_mul(self.step).ok()?;
2167
0
        self.step = self.step.checked_add(1)?;
2168
0
        let time = self.start.checked_add(span).ok()?;
2169
0
        Some(time)
2170
0
    }
2171
}
2172
2173
impl core::iter::FusedIterator for TimeSeries {}
2174
2175
/// Options for [`Time::checked_add`] and [`Time::checked_sub`].
2176
///
2177
/// This type provides a way to ergonomically add one of a few different
2178
/// duration types to a [`Time`].
2179
///
2180
/// The main way to construct values of this type is with its `From` trait
2181
/// implementations:
2182
///
2183
/// * `From<Span> for TimeArithmetic` adds (or subtracts) the given span to the
2184
/// receiver time.
2185
/// * `From<SignedDuration> for TimeArithmetic` adds (or subtracts)
2186
/// the given signed duration to the receiver time.
2187
/// * `From<std::time::Duration> for TimeArithmetic` adds (or subtracts)
2188
/// the given unsigned duration to the receiver time.
2189
///
2190
/// # Example
2191
///
2192
/// ```
2193
/// use std::time::Duration;
2194
///
2195
/// use jiff::{civil::time, SignedDuration, ToSpan};
2196
///
2197
/// let t = time(0, 0, 0, 0);
2198
/// assert_eq!(t.checked_add(2.hours())?, time(2, 0, 0, 0));
2199
/// assert_eq!(t.checked_add(SignedDuration::from_hours(2))?, time(2, 0, 0, 0));
2200
/// assert_eq!(t.checked_add(Duration::from_secs(2 * 60 * 60))?, time(2, 0, 0, 0));
2201
///
2202
/// # Ok::<(), Box<dyn std::error::Error>>(())
2203
/// ```
2204
#[derive(Clone, Copy, Debug)]
2205
pub struct TimeArithmetic {
2206
    duration: Duration,
2207
}
2208
2209
impl TimeArithmetic {
2210
    #[inline]
2211
0
    fn wrapping_add(self, time: Time) -> Time {
2212
0
        match self.duration {
2213
0
            Duration::Span(span) => time.wrapping_add_span(span),
2214
0
            Duration::Signed(sdur) => time.wrapping_add_signed_duration(sdur),
2215
0
            Duration::Unsigned(udur) => {
2216
0
                time.wrapping_add_unsigned_duration(udur)
2217
            }
2218
        }
2219
0
    }
2220
2221
    #[inline]
2222
0
    fn wrapping_sub(self, time: Time) -> Time {
2223
0
        match self.duration {
2224
0
            Duration::Span(span) => time.wrapping_add_span(span.negate()),
2225
0
            Duration::Signed(sdur) => {
2226
0
                if let Some(sdur) = sdur.checked_neg() {
2227
0
                    time.wrapping_add_signed_duration(sdur)
2228
                } else {
2229
0
                    let udur = UnsignedDuration::new(
2230
0
                        i64::MIN.unsigned_abs(),
2231
0
                        sdur.subsec_nanos().unsigned_abs(),
2232
                    );
2233
0
                    time.wrapping_add_unsigned_duration(udur)
2234
                }
2235
            }
2236
0
            Duration::Unsigned(udur) => {
2237
0
                time.wrapping_sub_unsigned_duration(udur)
2238
            }
2239
        }
2240
0
    }
2241
2242
    #[inline]
2243
0
    fn checked_add(self, time: Time) -> Result<Time, Error> {
2244
0
        match self.duration.to_signed()? {
2245
0
            SDuration::Span(span) => time.checked_add_span(span),
2246
0
            SDuration::Absolute(sdur) => time.checked_add_duration(sdur),
2247
        }
2248
0
    }
2249
2250
    #[inline]
2251
0
    fn checked_neg(self) -> Result<TimeArithmetic, Error> {
2252
0
        let duration = self.duration.checked_neg()?;
2253
0
        Ok(TimeArithmetic { duration })
2254
0
    }
2255
2256
    #[inline]
2257
0
    fn is_negative(&self) -> bool {
2258
0
        self.duration.is_negative()
2259
0
    }
2260
}
2261
2262
impl From<Span> for TimeArithmetic {
2263
0
    fn from(span: Span) -> TimeArithmetic {
2264
0
        let duration = Duration::from(span);
2265
0
        TimeArithmetic { duration }
2266
0
    }
2267
}
2268
2269
impl From<SignedDuration> for TimeArithmetic {
2270
0
    fn from(sdur: SignedDuration) -> TimeArithmetic {
2271
0
        let duration = Duration::from(sdur);
2272
0
        TimeArithmetic { duration }
2273
0
    }
2274
}
2275
2276
impl From<UnsignedDuration> for TimeArithmetic {
2277
0
    fn from(udur: UnsignedDuration) -> TimeArithmetic {
2278
0
        let duration = Duration::from(udur);
2279
0
        TimeArithmetic { duration }
2280
0
    }
2281
}
2282
2283
impl<'a> From<&'a Span> for TimeArithmetic {
2284
0
    fn from(span: &'a Span) -> TimeArithmetic {
2285
0
        TimeArithmetic::from(*span)
2286
0
    }
2287
}
2288
2289
impl<'a> From<&'a SignedDuration> for TimeArithmetic {
2290
0
    fn from(sdur: &'a SignedDuration) -> TimeArithmetic {
2291
0
        TimeArithmetic::from(*sdur)
2292
0
    }
2293
}
2294
2295
impl<'a> From<&'a UnsignedDuration> for TimeArithmetic {
2296
0
    fn from(udur: &'a UnsignedDuration) -> TimeArithmetic {
2297
0
        TimeArithmetic::from(*udur)
2298
0
    }
2299
}
2300
2301
/// Options for [`Time::since`] and [`Time::until`].
2302
///
2303
/// This type provides a way to configure the calculation of spans between two
2304
/// [`Time`] values. In particular, both `Time::since` and `Time::until` accept
2305
/// anything that implements `Into<TimeDifference>`. There are a few key trait
2306
/// implementations that make this convenient:
2307
///
2308
/// * `From<Time> for TimeDifference` will construct a configuration consisting
2309
/// of just the time. So for example, `time1.until(time2)` will return the span
2310
/// from `time1` to `time2`.
2311
/// * `From<DateTime> for TimeDifference` will construct a configuration
2312
/// consisting of just the time from the given datetime. So for example,
2313
/// `time.since(datetime)` returns the span from `datetime.time()` to `time`.
2314
/// * `From<(Unit, Time)>` is a convenient way to specify the largest units
2315
/// that should be present on the span returned. By default, the largest units
2316
/// are hours. Using this trait implementation is equivalent to
2317
/// `TimeDifference::new(time).largest(unit)`.
2318
/// * `From<(Unit, DateTime)>` is like the one above, but with the time from
2319
/// the given datetime.
2320
///
2321
/// One can also provide a `TimeDifference` value directly. Doing so
2322
/// is necessary to use the rounding features of calculating a span. For
2323
/// example, setting the smallest unit (defaults to [`Unit::Nanosecond`]), the
2324
/// rounding mode (defaults to [`RoundMode::Trunc`]) and the rounding increment
2325
/// (defaults to `1`). The defaults are selected such that no rounding occurs.
2326
///
2327
/// Rounding a span as part of calculating it is provided as a convenience.
2328
/// Callers may choose to round the span as a distinct step via
2329
/// [`Span::round`].
2330
///
2331
/// # Example
2332
///
2333
/// This example shows how to round a span between two datetimes to the nearest
2334
/// half-hour, with ties breaking away from zero.
2335
///
2336
/// ```
2337
/// use jiff::{civil::{Time, TimeDifference}, RoundMode, ToSpan, Unit};
2338
///
2339
/// let t1 = "08:14:00.123456789".parse::<Time>()?;
2340
/// let t2 = "15:00".parse::<Time>()?;
2341
/// let span = t1.until(
2342
///     TimeDifference::new(t2)
2343
///         .smallest(Unit::Minute)
2344
///         .mode(RoundMode::HalfExpand)
2345
///         .increment(30),
2346
/// )?;
2347
/// assert_eq!(span, 7.hours().fieldwise());
2348
///
2349
/// // One less minute, and because of the HalfExpand mode, the span would
2350
/// // get rounded down.
2351
/// let t2 = "14:59".parse::<Time>()?;
2352
/// let span = t1.until(
2353
///     TimeDifference::new(t2)
2354
///         .smallest(Unit::Minute)
2355
///         .mode(RoundMode::HalfExpand)
2356
///         .increment(30),
2357
/// )?;
2358
/// assert_eq!(span, 6.hours().minutes(30).fieldwise());
2359
///
2360
/// # Ok::<(), Box<dyn std::error::Error>>(())
2361
/// ```
2362
#[derive(Clone, Copy, Debug)]
2363
pub struct TimeDifference {
2364
    time: Time,
2365
    round: SpanRound<'static>,
2366
}
2367
2368
impl TimeDifference {
2369
    /// Create a new default configuration for computing the span between
2370
    /// the given time and some other time (specified as the receiver in
2371
    /// [`Time::since`] or [`Time::until`]).
2372
    #[inline]
2373
0
    pub fn new(time: Time) -> TimeDifference {
2374
        // We use truncation rounding by default since it seems that's
2375
        // what is generally expected when computing the difference between
2376
        // datetimes.
2377
        //
2378
        // See: https://github.com/tc39/proposal-temporal/issues/1122
2379
0
        let round = SpanRound::new().mode(RoundMode::Trunc);
2380
0
        TimeDifference { time, round }
2381
0
    }
2382
2383
    /// Set the smallest units allowed in the span returned.
2384
    ///
2385
    /// # Errors
2386
    ///
2387
    /// The smallest units must be no greater than the largest units. If this
2388
    /// is violated, then computing a span with this configuration will result
2389
    /// in an error.
2390
    ///
2391
    /// The smallest unit must be no bigger than `Unit::Hour`.
2392
    ///
2393
    /// # Example
2394
    ///
2395
    /// This shows how to round a span between two times to units no less than
2396
    /// seconds.
2397
    ///
2398
    /// ```
2399
    /// use jiff::{civil::{Time, TimeDifference}, RoundMode, ToSpan, Unit};
2400
    ///
2401
    /// let t1 = "08:14:02.5001".parse::<Time>()?;
2402
    /// let t2 = "08:30:03.0001".parse::<Time>()?;
2403
    /// let span = t1.until(
2404
    ///     TimeDifference::new(t2)
2405
    ///         .smallest(Unit::Second)
2406
    ///         .mode(RoundMode::HalfExpand),
2407
    /// )?;
2408
    /// assert_eq!(span, 16.minutes().seconds(1).fieldwise());
2409
    ///
2410
    /// # Ok::<(), Box<dyn std::error::Error>>(())
2411
    /// ```
2412
    #[inline]
2413
0
    pub fn smallest(self, unit: Unit) -> TimeDifference {
2414
0
        TimeDifference { round: self.round.smallest(unit), ..self }
2415
0
    }
2416
2417
    /// Set the largest units allowed in the span returned.
2418
    ///
2419
    /// When a largest unit is not specified, computing a span between times
2420
    /// behaves as if it were set to [`Unit::Hour`].
2421
    ///
2422
    /// # Errors
2423
    ///
2424
    /// The largest units, when set, must be at least as big as the smallest
2425
    /// units (which defaults to [`Unit::Nanosecond`]). If this is violated,
2426
    /// then computing a span with this configuration will result in an error.
2427
    ///
2428
    /// The largest unit must be no bigger than `Unit::Hour`.
2429
    ///
2430
    /// # Example
2431
    ///
2432
    /// This shows how to round a span between two times to units no
2433
    /// bigger than seconds.
2434
    ///
2435
    /// ```
2436
    /// use jiff::{civil::{Time, TimeDifference}, ToSpan, Unit};
2437
    ///
2438
    /// let t1 = "08:14".parse::<Time>()?;
2439
    /// let t2 = "08:30".parse::<Time>()?;
2440
    /// let span = t1.until(TimeDifference::new(t2).largest(Unit::Second))?;
2441
    /// assert_eq!(span, 960.seconds().fieldwise());
2442
    ///
2443
    /// # Ok::<(), Box<dyn std::error::Error>>(())
2444
    /// ```
2445
    #[inline]
2446
0
    pub fn largest(self, unit: Unit) -> TimeDifference {
2447
0
        TimeDifference { round: self.round.largest(unit), ..self }
2448
0
    }
2449
2450
    /// Set the rounding mode.
2451
    ///
2452
    /// This defaults to [`RoundMode::Trunc`] since it's plausible that
2453
    /// rounding "up" in the context of computing the span between two times
2454
    /// could be surprising in a number of cases. The [`RoundMode::HalfExpand`]
2455
    /// mode corresponds to typical rounding you might have learned about in
2456
    /// school. But a variety of other rounding modes exist.
2457
    ///
2458
    /// # Example
2459
    ///
2460
    /// This shows how to always round "up" towards positive infinity.
2461
    ///
2462
    /// ```
2463
    /// use jiff::{civil::{Time, TimeDifference}, RoundMode, ToSpan, Unit};
2464
    ///
2465
    /// let t1 = "08:10".parse::<Time>()?;
2466
    /// let t2 = "08:11".parse::<Time>()?;
2467
    /// let span = t1.until(
2468
    ///     TimeDifference::new(t2)
2469
    ///         .smallest(Unit::Hour)
2470
    ///         .mode(RoundMode::Ceil),
2471
    /// )?;
2472
    /// // Only one minute elapsed, but we asked to always round up!
2473
    /// assert_eq!(span, 1.hour().fieldwise());
2474
    ///
2475
    /// // Since `Ceil` always rounds toward positive infinity, the behavior
2476
    /// // flips for a negative span.
2477
    /// let span = t1.since(
2478
    ///     TimeDifference::new(t2)
2479
    ///         .smallest(Unit::Hour)
2480
    ///         .mode(RoundMode::Ceil),
2481
    /// )?;
2482
    /// assert_eq!(span, 0.hour().fieldwise());
2483
    ///
2484
    /// # Ok::<(), Box<dyn std::error::Error>>(())
2485
    /// ```
2486
    #[inline]
2487
0
    pub fn mode(self, mode: RoundMode) -> TimeDifference {
2488
0
        TimeDifference { round: self.round.mode(mode), ..self }
2489
0
    }
2490
2491
    /// Set the rounding increment for the smallest unit.
2492
    ///
2493
    /// The default value is `1`. Other values permit rounding the smallest
2494
    /// unit to the nearest integer increment specified. For example, if the
2495
    /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
2496
    /// `30` would result in rounding in increments of a half hour. That is,
2497
    /// the only minute value that could result would be `0` or `30`.
2498
    ///
2499
    /// # Errors
2500
    ///
2501
    /// The rounding increment must divide evenly into the next highest unit
2502
    /// after the smallest unit configured (and must not be equivalent to it).
2503
    /// For example, if the smallest unit is [`Unit::Nanosecond`], then *some*
2504
    /// of the valid values for the rounding increment are `1`, `2`, `4`, `5`,
2505
    /// `100` and `500`. Namely, any integer that divides evenly into `1,000`
2506
    /// nanoseconds since there are `1,000` nanoseconds in the next highest
2507
    /// unit (microseconds).
2508
    ///
2509
    /// In all cases, the increment must be greater than zero and less than
2510
    /// or equal to `1_000_000_000`.
2511
    ///
2512
    /// The error will occur when computing the span, and not when setting
2513
    /// the increment here.
2514
    ///
2515
    /// # Example
2516
    ///
2517
    /// This shows how to round the span between two times to the nearest 5
2518
    /// minute increment.
2519
    ///
2520
    /// ```
2521
    /// use jiff::{civil::{Time, TimeDifference}, RoundMode, ToSpan, Unit};
2522
    ///
2523
    /// let t1 = "08:19".parse::<Time>()?;
2524
    /// let t2 = "12:52".parse::<Time>()?;
2525
    /// let span = t1.until(
2526
    ///     TimeDifference::new(t2)
2527
    ///         .smallest(Unit::Minute)
2528
    ///         .increment(5)
2529
    ///         .mode(RoundMode::HalfExpand),
2530
    /// )?;
2531
    /// assert_eq!(span, 4.hour().minutes(35).fieldwise());
2532
    ///
2533
    /// # Ok::<(), Box<dyn std::error::Error>>(())
2534
    /// ```
2535
    #[inline]
2536
0
    pub fn increment(self, increment: i64) -> TimeDifference {
2537
0
        TimeDifference { round: self.round.increment(increment), ..self }
2538
0
    }
2539
2540
    /// Returns true if and only if this configuration could change the span
2541
    /// via rounding.
2542
    #[inline]
2543
0
    fn rounding_may_change_span(&self) -> bool {
2544
0
        self.round.rounding_may_change_span()
2545
0
    }
2546
2547
    /// Returns the span of time from `t1` to the time in this configuration.
2548
    /// The biggest units allowed are determined by the `smallest` and
2549
    /// `largest` settings, but defaults to `Unit::Hour`.
2550
    #[inline]
2551
0
    fn until_with_largest_unit(&self, t1: Time) -> Result<Span, Error> {
2552
0
        if self.round.get_smallest() >= Unit::Day {
2553
0
            return Err(Error::from(UnitConfigError::CivilTime {
2554
0
                given: self.round.get_smallest(),
2555
0
            }));
2556
0
        }
2557
2558
0
        let largest = self.round.get_largest().unwrap_or(Unit::Hour);
2559
0
        if largest >= Unit::Day {
2560
0
            return Err(Error::from(UnitConfigError::CivilTime {
2561
0
                given: largest,
2562
0
            }));
2563
0
        }
2564
2565
0
        let t2 = self.time;
2566
0
        if t1 == t2 {
2567
0
            return Ok(Span::new());
2568
0
        }
2569
0
        let start = t1.to_duration();
2570
0
        let end = t2.to_duration();
2571
0
        let span = Span::from_invariant_duration(largest, end - start)
2572
0
            .expect("difference in civil times is always in bounds");
2573
0
        Ok(span)
2574
0
    }
2575
}
2576
2577
impl From<Time> for TimeDifference {
2578
    #[inline]
2579
0
    fn from(time: Time) -> TimeDifference {
2580
0
        TimeDifference::new(time)
2581
0
    }
2582
}
2583
2584
impl From<DateTime> for TimeDifference {
2585
    #[inline]
2586
0
    fn from(dt: DateTime) -> TimeDifference {
2587
0
        TimeDifference::from(Time::from(dt))
2588
0
    }
2589
}
2590
2591
impl From<Zoned> for TimeDifference {
2592
    #[inline]
2593
0
    fn from(zdt: Zoned) -> TimeDifference {
2594
0
        TimeDifference::from(Time::from(zdt))
2595
0
    }
2596
}
2597
2598
impl<'a> From<&'a Zoned> for TimeDifference {
2599
    #[inline]
2600
0
    fn from(zdt: &'a Zoned) -> TimeDifference {
2601
0
        TimeDifference::from(zdt.datetime())
2602
0
    }
2603
}
2604
2605
impl From<(Unit, Time)> for TimeDifference {
2606
    #[inline]
2607
0
    fn from((largest, time): (Unit, Time)) -> TimeDifference {
2608
0
        TimeDifference::from(time).largest(largest)
2609
0
    }
2610
}
2611
2612
impl From<(Unit, DateTime)> for TimeDifference {
2613
    #[inline]
2614
0
    fn from((largest, dt): (Unit, DateTime)) -> TimeDifference {
2615
0
        TimeDifference::from((largest, Time::from(dt)))
2616
0
    }
2617
}
2618
2619
impl From<(Unit, Zoned)> for TimeDifference {
2620
    #[inline]
2621
0
    fn from((largest, zdt): (Unit, Zoned)) -> TimeDifference {
2622
0
        TimeDifference::from((largest, Time::from(zdt)))
2623
0
    }
2624
}
2625
2626
impl<'a> From<(Unit, &'a Zoned)> for TimeDifference {
2627
    #[inline]
2628
0
    fn from((largest, zdt): (Unit, &'a Zoned)) -> TimeDifference {
2629
0
        TimeDifference::from((largest, zdt.datetime()))
2630
0
    }
2631
}
2632
2633
/// Options for [`Time::round`].
2634
///
2635
/// This type provides a way to configure the rounding of a civil time.
2636
/// In particular, `Time::round` accepts anything that implements the
2637
/// `Into<TimeRound>` trait. There are some trait implementations that
2638
/// therefore make calling `Time::round` in some common cases more ergonomic:
2639
///
2640
/// * `From<Unit> for TimeRound` will construct a rounding configuration that
2641
/// rounds to the unit given. Specifically, `TimeRound::new().smallest(unit)`.
2642
/// * `From<(Unit, i64)> for TimeRound` is like the one above, but also
2643
/// specifies the rounding increment for [`TimeRound::increment`].
2644
///
2645
/// Note that in the default configuration, no rounding occurs.
2646
///
2647
/// # Example
2648
///
2649
/// This example shows how to round a time to the nearest second:
2650
///
2651
/// ```
2652
/// use jiff::{civil::{Time, time}, Unit};
2653
///
2654
/// let t: Time = "16:24:59.5".parse()?;
2655
/// assert_eq!(
2656
///     t.round(Unit::Second)?,
2657
///     // The second rounds up and causes minutes to increase.
2658
///     time(16, 25, 0, 0),
2659
/// );
2660
///
2661
/// # Ok::<(), Box<dyn std::error::Error>>(())
2662
/// ```
2663
///
2664
/// The above makes use of the fact that `Unit` implements
2665
/// `Into<TimeRound>`. If you want to change the rounding mode to, say,
2666
/// truncation, then you'll need to construct a `TimeRound` explicitly
2667
/// since there are no convenience `Into` trait implementations for
2668
/// [`RoundMode`].
2669
///
2670
/// ```
2671
/// use jiff::{civil::{Time, TimeRound, time}, RoundMode, Unit};
2672
///
2673
/// let t: Time = "2024-06-20 16:24:59.5".parse()?;
2674
/// assert_eq!(
2675
///     t.round(
2676
///         TimeRound::new().smallest(Unit::Second).mode(RoundMode::Trunc),
2677
///     )?,
2678
///     // The second just gets truncated as if it wasn't there.
2679
///     time(16, 24, 59, 0),
2680
/// );
2681
///
2682
/// # Ok::<(), Box<dyn std::error::Error>>(())
2683
/// ```
2684
#[derive(Clone, Copy, Debug)]
2685
pub struct TimeRound {
2686
    smallest: Unit,
2687
    mode: RoundMode,
2688
    increment: i64,
2689
}
2690
2691
impl TimeRound {
2692
    /// Create a new default configuration for rounding a [`Time`].
2693
    #[inline]
2694
0
    pub fn new() -> TimeRound {
2695
0
        TimeRound {
2696
0
            smallest: Unit::Nanosecond,
2697
0
            mode: RoundMode::HalfExpand,
2698
0
            increment: 1,
2699
0
        }
2700
0
    }
2701
2702
    /// Set the smallest units allowed in the time returned after rounding.
2703
    ///
2704
    /// Any units below the smallest configured unit will be used, along with
2705
    /// the rounding increment and rounding mode, to determine the value of the
2706
    /// smallest unit. For example, when rounding `03:25:30` to the
2707
    /// nearest minute, the `30` second unit will result in rounding the minute
2708
    /// unit of `25` up to `26` and zeroing out everything below minutes.
2709
    ///
2710
    /// This defaults to [`Unit::Nanosecond`].
2711
    ///
2712
    /// # Errors
2713
    ///
2714
    /// The smallest units must be no greater than [`Unit::Hour`].
2715
    ///
2716
    /// # Example
2717
    ///
2718
    /// ```
2719
    /// use jiff::{civil::{TimeRound, time}, Unit};
2720
    ///
2721
    /// let t = time(3, 25, 30, 0);
2722
    /// assert_eq!(
2723
    ///     t.round(TimeRound::new().smallest(Unit::Minute))?,
2724
    ///     time(3, 26, 0, 0),
2725
    /// );
2726
    /// // Or, utilize the `From<Unit> for TimeRound` impl:
2727
    /// assert_eq!(t.round(Unit::Minute)?, time(3, 26, 0, 0));
2728
    ///
2729
    /// # Ok::<(), Box<dyn std::error::Error>>(())
2730
    /// ```
2731
    #[inline]
2732
0
    pub fn smallest(self, unit: Unit) -> TimeRound {
2733
0
        TimeRound { smallest: unit, ..self }
2734
0
    }
2735
2736
    /// Set the rounding mode.
2737
    ///
2738
    /// This defaults to [`RoundMode::HalfExpand`], which rounds away from
2739
    /// zero. It matches the kind of rounding you might have been taught in
2740
    /// school.
2741
    ///
2742
    /// # Example
2743
    ///
2744
    /// This shows how to always round times up towards positive infinity.
2745
    ///
2746
    /// ```
2747
    /// use jiff::{civil::{Time, TimeRound, time}, RoundMode, Unit};
2748
    ///
2749
    /// let t: Time = "03:25:01".parse()?;
2750
    /// assert_eq!(
2751
    ///     t.round(
2752
    ///         TimeRound::new()
2753
    ///             .smallest(Unit::Minute)
2754
    ///             .mode(RoundMode::Ceil),
2755
    ///     )?,
2756
    ///     time(3, 26, 0, 0),
2757
    /// );
2758
    ///
2759
    /// # Ok::<(), Box<dyn std::error::Error>>(())
2760
    /// ```
2761
    #[inline]
2762
0
    pub fn mode(self, mode: RoundMode) -> TimeRound {
2763
0
        TimeRound { mode, ..self }
2764
0
    }
2765
2766
    /// Set the rounding increment for the smallest unit.
2767
    ///
2768
    /// The default value is `1`. Other values permit rounding the smallest
2769
    /// unit to the nearest integer increment specified. For example, if the
2770
    /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
2771
    /// `30` would result in rounding in increments of a half hour. That is,
2772
    /// the only minute value that could result would be `0` or `30`.
2773
    ///
2774
    /// # Errors
2775
    ///
2776
    /// The rounding increment must divide evenly into the
2777
    /// next highest unit above the smallest unit set. The rounding increment
2778
    /// must also not be equal to the next highest unit. For example, if the
2779
    /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
2780
    /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
2781
    /// Namely, any integer that divides evenly into `1,000` nanoseconds since
2782
    /// there are `1,000` nanoseconds in the next highest unit (microseconds).
2783
    ///
2784
    /// In all cases, the increment must be greater than zero and less than or
2785
    /// equal to `1_000_000_000`.
2786
    ///
2787
    /// # Example
2788
    ///
2789
    /// This example shows how to round a time to the nearest 10 minute
2790
    /// increment.
2791
    ///
2792
    /// ```
2793
    /// use jiff::{civil::{Time, TimeRound, time}, RoundMode, Unit};
2794
    ///
2795
    /// let t: Time = "03:24:59".parse()?;
2796
    /// assert_eq!(t.round((Unit::Minute, 10))?, time(3, 20, 0, 0));
2797
    ///
2798
    /// # Ok::<(), Box<dyn std::error::Error>>(())
2799
    /// ```
2800
    #[inline]
2801
0
    pub fn increment(self, increment: i64) -> TimeRound {
2802
0
        TimeRound { increment, ..self }
2803
0
    }
2804
2805
    /// Does the actual rounding.
2806
0
    fn round(&self, t: Time) -> Result<Time, Error> {
2807
0
        let increment = Increment::for_time(self.smallest, self.increment)?;
2808
0
        let rounded = increment.round(self.mode, t.to_duration())?;
2809
0
        if rounded.as_secs() == i64::from(b::CivilDaySecond::MAX + 1) {
2810
0
            return Ok(Time::MIN);
2811
0
        }
2812
        // OK because the maximum value for `rounded` is the number of
2813
        // nanoseconds in a civil day. In which case, that wraps around to
2814
        // `Time::MIN` and we handle that case above. `rounded` can't be any
2815
        // bigger because of the requirement that the rounding increment divide
2816
        // evenly into the next biggest unit (and thus all such increments must
2817
        // divide evenly into a single civil day).
2818
0
        Ok(Time::from_duration_unchecked(rounded))
2819
0
    }
2820
}
2821
2822
impl Default for TimeRound {
2823
    #[inline]
2824
0
    fn default() -> TimeRound {
2825
0
        TimeRound::new()
2826
0
    }
2827
}
2828
2829
impl From<Unit> for TimeRound {
2830
    #[inline]
2831
0
    fn from(unit: Unit) -> TimeRound {
2832
0
        TimeRound::default().smallest(unit)
2833
0
    }
2834
}
2835
2836
impl From<(Unit, i64)> for TimeRound {
2837
    #[inline]
2838
0
    fn from((unit, increment): (Unit, i64)) -> TimeRound {
2839
0
        TimeRound::from(unit).increment(increment)
2840
0
    }
2841
}
2842
2843
/// A builder for setting the fields on a [`Time`].
2844
///
2845
/// This builder is constructed via [`Time::with`].
2846
///
2847
/// # Example
2848
///
2849
/// Unlike [`Date`], a [`Time`] is valid for all possible valid values of its
2850
/// fields. That is, there is no way for two valid field values to combine
2851
/// into an invalid `Time`. So, for `Time`, this builder does have as much of
2852
/// a benefit versus an API design with methods like `Time::with_hour` and
2853
/// `Time::with_minute`. Nevertheless, this builder permits settings multiple
2854
/// fields at the same time and performing only one validity check. Moreover,
2855
/// this provides a consistent API with other date and time types in this
2856
/// crate.
2857
///
2858
/// ```
2859
/// use jiff::civil::time;
2860
///
2861
/// let t1 = time(0, 0, 24, 0);
2862
/// let t2 = t1.with().hour(15).minute(30).millisecond(10).build()?;
2863
/// assert_eq!(t2, time(15, 30, 24, 10_000_000));
2864
///
2865
/// # Ok::<(), Box<dyn std::error::Error>>(())
2866
/// ```
2867
#[derive(Clone, Copy, Debug)]
2868
pub struct TimeWith {
2869
    original: Time,
2870
    hour: Option<i8>,
2871
    minute: Option<i8>,
2872
    second: Option<i8>,
2873
    millisecond: Option<i16>,
2874
    microsecond: Option<i16>,
2875
    nanosecond: Option<i16>,
2876
    subsec_nanosecond: Option<i32>,
2877
}
2878
2879
impl TimeWith {
2880
    #[inline]
2881
0
    fn new(original: Time) -> TimeWith {
2882
0
        TimeWith {
2883
0
            original,
2884
0
            hour: None,
2885
0
            minute: None,
2886
0
            second: None,
2887
0
            millisecond: None,
2888
0
            microsecond: None,
2889
0
            nanosecond: None,
2890
0
            subsec_nanosecond: None,
2891
0
        }
2892
0
    }
2893
2894
    /// Create a new `Time` from the fields set on this configuration.
2895
    ///
2896
    /// An error occurs when the fields combine to an invalid time. This only
2897
    /// occurs when at least one field has an invalid value, or if at least
2898
    /// one of `millisecond`, `microsecond` or `nanosecond` is set _and_
2899
    /// `subsec_nanosecond` is set. Otherwise, if all fields are valid, then
2900
    /// the entire `Time` is guaranteed to be valid.
2901
    ///
2902
    /// For any fields not set on this configuration, the values are taken from
2903
    /// the [`Time`] that originally created this configuration. When no values
2904
    /// are set, this routine is guaranteed to succeed and will always return
2905
    /// the original time without modification.
2906
    ///
2907
    /// # Example
2908
    ///
2909
    /// This creates a time but with its fractional nanosecond component
2910
    /// stripped:
2911
    ///
2912
    /// ```
2913
    /// use jiff::civil::time;
2914
    ///
2915
    /// let t = time(14, 27, 30, 123_456_789);
2916
    /// assert_eq!(t.with().subsec_nanosecond(0).build()?, time(14, 27, 30, 0));
2917
    ///
2918
    /// # Ok::<(), Box<dyn std::error::Error>>(())
2919
    /// ```
2920
    ///
2921
    /// # Example: error for invalid time
2922
    ///
2923
    /// ```
2924
    /// use jiff::civil::time;
2925
    ///
2926
    /// let t = time(14, 27, 30, 0);
2927
    /// assert!(t.with().hour(24).build().is_err());
2928
    /// ```
2929
    ///
2930
    /// # Example: error for ambiguous sub-second value
2931
    ///
2932
    /// ```
2933
    /// use jiff::civil::time;
2934
    ///
2935
    /// let t = time(14, 27, 30, 123_456_789);
2936
    /// // Setting both the individual sub-second fields and the entire
2937
    /// // fractional component could lead to a misleading configuration. So
2938
    /// // if it's done, it results in an error in all cases. Callers must
2939
    /// // choose one or the other.
2940
    /// assert!(t.with().microsecond(1).subsec_nanosecond(0).build().is_err());
2941
    /// ```
2942
    #[inline]
2943
0
    pub fn build(self) -> Result<Time, Error> {
2944
0
        let hour = match self.hour {
2945
0
            None => self.original.hour(),
2946
0
            Some(hour) => b::Hour::check(hour)?,
2947
        };
2948
0
        let minute = match self.minute {
2949
0
            None => self.original.minute(),
2950
0
            Some(minute) => b::Minute::check(minute)?,
2951
        };
2952
0
        let second = match self.second {
2953
0
            None => self.original.second(),
2954
0
            Some(second) => b::Second::check(second)?,
2955
        };
2956
0
        let millisecond = match self.millisecond {
2957
0
            None => self.original.millisecond(),
2958
0
            Some(millisecond) => b::Millisecond::check(millisecond)?,
2959
        };
2960
0
        let microsecond = match self.microsecond {
2961
0
            None => self.original.microsecond(),
2962
0
            Some(microsecond) => b::Microsecond::check(microsecond)?,
2963
        };
2964
0
        let nanosecond = match self.nanosecond {
2965
0
            None => self.original.nanosecond(),
2966
0
            Some(nanosecond) => b::Nanosecond::check(nanosecond)?,
2967
        };
2968
0
        let subsec_nanosecond = match self.subsec_nanosecond {
2969
0
            None => self.original.subsec_nanosecond(),
2970
0
            Some(subsec_nanosecond) => {
2971
0
                if self.millisecond.is_some() {
2972
0
                    return Err(Error::from(E::IllegalTimeWithMillisecond));
2973
0
                }
2974
0
                if self.microsecond.is_some() {
2975
0
                    return Err(Error::from(E::IllegalTimeWithMicrosecond));
2976
0
                }
2977
0
                if self.nanosecond.is_some() {
2978
0
                    return Err(Error::from(E::IllegalTimeWithNanosecond));
2979
0
                }
2980
0
                b::SubsecNanosecond::check(subsec_nanosecond)?
2981
            }
2982
        };
2983
0
        if self.subsec_nanosecond.is_some() {
2984
0
            Ok(Time::new_unchecked(hour, minute, second, subsec_nanosecond))
2985
        } else {
2986
0
            Ok(Time::new_unchecked(hour, minute, second, 0)
2987
0
                .with_subsec_parts_unchecked(
2988
0
                    millisecond,
2989
0
                    microsecond,
2990
0
                    nanosecond,
2991
0
                ))
2992
        }
2993
0
    }
2994
2995
    /// Set the hour field on a [`Time`].
2996
    ///
2997
    /// One can access this value via [`Time::hour`].
2998
    ///
2999
    /// This overrides any previous hour settings.
3000
    ///
3001
    /// # Errors
3002
    ///
3003
    /// This returns an error when [`TimeWith::build`] is called if the given
3004
    /// hour is outside the range `0..=23`.
3005
    ///
3006
    /// # Example
3007
    ///
3008
    /// ```
3009
    /// use jiff::civil::time;
3010
    ///
3011
    /// let t1 = time(15, 21, 59, 0);
3012
    /// assert_eq!(t1.hour(), 15);
3013
    /// let t2 = t1.with().hour(3).build()?;
3014
    /// assert_eq!(t2.hour(), 3);
3015
    ///
3016
    /// # Ok::<(), Box<dyn std::error::Error>>(())
3017
    /// ```
3018
    #[inline]
3019
0
    pub fn hour(self, hour: i8) -> TimeWith {
3020
0
        TimeWith { hour: Some(hour), ..self }
3021
0
    }
3022
3023
    /// Set the minute field on a [`Time`].
3024
    ///
3025
    /// One can access this value via [`Time::minute`].
3026
    ///
3027
    /// This overrides any previous minute settings.
3028
    ///
3029
    /// # Errors
3030
    ///
3031
    /// This returns an error when [`TimeWith::build`] is called if the given
3032
    /// minute is outside the range `0..=59`.
3033
    ///
3034
    /// # Example
3035
    ///
3036
    /// ```
3037
    /// use jiff::civil::time;
3038
    ///
3039
    /// let t1 = time(15, 21, 59, 0);
3040
    /// assert_eq!(t1.minute(), 21);
3041
    /// let t2 = t1.with().minute(3).build()?;
3042
    /// assert_eq!(t2.minute(), 3);
3043
    ///
3044
    /// # Ok::<(), Box<dyn std::error::Error>>(())
3045
    /// ```
3046
    #[inline]
3047
0
    pub fn minute(self, minute: i8) -> TimeWith {
3048
0
        TimeWith { minute: Some(minute), ..self }
3049
0
    }
3050
3051
    /// Set the second field on a [`Time`].
3052
    ///
3053
    /// One can access this value via [`Time::second`].
3054
    ///
3055
    /// This overrides any previous second settings.
3056
    ///
3057
    /// # Errors
3058
    ///
3059
    /// This returns an error when [`TimeWith::build`] is called if the given
3060
    /// second is outside the range `0..=59`.
3061
    ///
3062
    /// # Example
3063
    ///
3064
    /// ```
3065
    /// use jiff::civil::time;
3066
    ///
3067
    /// let t1 = time(15, 21, 59, 0);
3068
    /// assert_eq!(t1.second(), 59);
3069
    /// let t2 = t1.with().second(3).build()?;
3070
    /// assert_eq!(t2.second(), 3);
3071
    ///
3072
    /// # Ok::<(), Box<dyn std::error::Error>>(())
3073
    /// ```
3074
    #[inline]
3075
0
    pub fn second(self, second: i8) -> TimeWith {
3076
0
        TimeWith { second: Some(second), ..self }
3077
0
    }
3078
3079
    /// Set the millisecond field on a [`Time`].
3080
    ///
3081
    /// One can access this value via [`Time::millisecond`].
3082
    ///
3083
    /// This overrides any previous millisecond settings.
3084
    ///
3085
    /// Note that this only sets the millisecond component. It does
3086
    /// not change the microsecond or nanosecond components. To set
3087
    /// the fractional second component to nanosecond precision, use
3088
    /// [`TimeWith::subsec_nanosecond`].
3089
    ///
3090
    /// # Errors
3091
    ///
3092
    /// This returns an error when [`TimeWith::build`] is called if the given
3093
    /// millisecond is outside the range `0..=999`, or if both this and
3094
    /// [`TimeWith::subsec_nanosecond`] are set.
3095
    ///
3096
    /// # Example
3097
    ///
3098
    /// This shows the relationship between [`Time::millisecond`] and
3099
    /// [`Time::subsec_nanosecond`]:
3100
    ///
3101
    /// ```
3102
    /// use jiff::civil::time;
3103
    ///
3104
    /// let t = time(15, 21, 35, 0).with().millisecond(123).build()?;
3105
    /// assert_eq!(t.subsec_nanosecond(), 123_000_000);
3106
    ///
3107
    /// # Ok::<(), Box<dyn std::error::Error>>(())
3108
    /// ```
3109
    #[inline]
3110
0
    pub fn millisecond(self, millisecond: i16) -> TimeWith {
3111
0
        TimeWith { millisecond: Some(millisecond), ..self }
3112
0
    }
3113
3114
    /// Set the microsecond field on a [`Time`].
3115
    ///
3116
    /// One can access this value via [`Time::microsecond`].
3117
    ///
3118
    /// This overrides any previous microsecond settings.
3119
    ///
3120
    /// Note that this only sets the microsecond component. It does
3121
    /// not change the millisecond or nanosecond components. To set
3122
    /// the fractional second component to nanosecond precision, use
3123
    /// [`TimeWith::subsec_nanosecond`].
3124
    ///
3125
    /// # Errors
3126
    ///
3127
    /// This returns an error when [`TimeWith::build`] is called if the given
3128
    /// microsecond is outside the range `0..=999`, or if both this and
3129
    /// [`TimeWith::subsec_nanosecond`] are set.
3130
    ///
3131
    /// # Example
3132
    ///
3133
    /// This shows the relationship between [`Time::microsecond`] and
3134
    /// [`Time::subsec_nanosecond`]:
3135
    ///
3136
    /// ```
3137
    /// use jiff::civil::time;
3138
    ///
3139
    /// let t = time(15, 21, 35, 0).with().microsecond(123).build()?;
3140
    /// assert_eq!(t.subsec_nanosecond(), 123_000);
3141
    ///
3142
    /// # Ok::<(), Box<dyn std::error::Error>>(())
3143
    /// ```
3144
    #[inline]
3145
0
    pub fn microsecond(self, microsecond: i16) -> TimeWith {
3146
0
        TimeWith { microsecond: Some(microsecond), ..self }
3147
0
    }
3148
3149
    /// Set the nanosecond field on a [`Time`].
3150
    ///
3151
    /// One can access this value via [`Time::nanosecond`].
3152
    ///
3153
    /// This overrides any previous nanosecond settings.
3154
    ///
3155
    /// Note that this only sets the nanosecond component. It does
3156
    /// not change the millisecond or microsecond components. To set
3157
    /// the fractional second component to nanosecond precision, use
3158
    /// [`TimeWith::subsec_nanosecond`].
3159
    ///
3160
    /// # Errors
3161
    ///
3162
    /// This returns an error when [`TimeWith::build`] is called if the given
3163
    /// nanosecond is outside the range `0..=999`, or if both this and
3164
    /// [`TimeWith::subsec_nanosecond`] are set.
3165
    ///
3166
    /// # Example
3167
    ///
3168
    /// This shows the relationship between [`Time::nanosecond`] and
3169
    /// [`Time::subsec_nanosecond`]:
3170
    ///
3171
    /// ```
3172
    /// use jiff::civil::time;
3173
    ///
3174
    /// let t = time(15, 21, 35, 0).with().nanosecond(123).build()?;
3175
    /// assert_eq!(t.subsec_nanosecond(), 123);
3176
    ///
3177
    /// # Ok::<(), Box<dyn std::error::Error>>(())
3178
    /// ```
3179
    #[inline]
3180
0
    pub fn nanosecond(self, nanosecond: i16) -> TimeWith {
3181
0
        TimeWith { nanosecond: Some(nanosecond), ..self }
3182
0
    }
3183
3184
    /// Set the subsecond nanosecond field on a [`Time`].
3185
    ///
3186
    /// If you want to access this value on `Time`, then use
3187
    /// [`Time::subsec_nanosecond`].
3188
    ///
3189
    /// This overrides any previous subsecond nanosecond settings.
3190
    ///
3191
    /// Note that this sets the entire fractional second component to
3192
    /// nanosecond precision, and overrides any individual millisecond,
3193
    /// microsecond or nanosecond settings. To set individual components,
3194
    /// use [`TimeWith::millisecond`], [`TimeWith::microsecond`] or
3195
    /// [`TimeWith::nanosecond`].
3196
    ///
3197
    /// # Errors
3198
    ///
3199
    /// This returns an error when [`TimeWith::build`] is called if the given
3200
    /// subsecond nanosecond is outside the range `0..=999,999,999`, or if both
3201
    /// this and one of [`TimeWith::millisecond`], [`TimeWith::microsecond`] or
3202
    /// [`TimeWith::nanosecond`] are set.
3203
    ///
3204
    /// # Example
3205
    ///
3206
    /// This shows the relationship between constructing a `Time` value with
3207
    /// subsecond nanoseconds and its individual subsecond fields:
3208
    ///
3209
    /// ```
3210
    /// use jiff::civil::time;
3211
    ///
3212
    /// let t1 = time(15, 21, 35, 0);
3213
    /// let t2 = t1.with().subsec_nanosecond(123_456_789).build()?;
3214
    /// assert_eq!(t2.millisecond(), 123);
3215
    /// assert_eq!(t2.microsecond(), 456);
3216
    /// assert_eq!(t2.nanosecond(), 789);
3217
    ///
3218
    /// # Ok::<(), Box<dyn std::error::Error>>(())
3219
    /// ```
3220
    #[inline]
3221
0
    pub fn subsec_nanosecond(self, subsec_nanosecond: i32) -> TimeWith {
3222
0
        TimeWith { subsec_nanosecond: Some(subsec_nanosecond), ..self }
3223
0
    }
3224
}
3225
3226
#[cfg(test)]
3227
mod tests {
3228
    use std::io::Cursor;
3229
3230
    use crate::{civil::time, span::span_eq, ToSpan};
3231
3232
    use super::*;
3233
3234
    #[test]
3235
    fn min() {
3236
        let t = Time::MIN;
3237
        assert_eq!(t.hour(), 0);
3238
        assert_eq!(t.minute(), 0);
3239
        assert_eq!(t.second(), 0);
3240
        assert_eq!(t.subsec_nanosecond(), 0);
3241
    }
3242
3243
    #[test]
3244
    fn max() {
3245
        let t = Time::MAX;
3246
        assert_eq!(t.hour(), 23);
3247
        assert_eq!(t.minute(), 59);
3248
        assert_eq!(t.second(), 59);
3249
        assert_eq!(t.subsec_nanosecond(), 999_999_999);
3250
    }
3251
3252
    #[test]
3253
    fn invalid() {
3254
        assert!(Time::new(24, 0, 0, 0).is_err());
3255
        assert!(Time::new(23, 60, 0, 0).is_err());
3256
        assert!(Time::new(23, 59, 60, 0).is_err());
3257
        assert!(Time::new(23, 59, 61, 0).is_err());
3258
        assert!(Time::new(-1, 0, 0, 0).is_err());
3259
        assert!(Time::new(0, -1, 0, 0).is_err());
3260
        assert!(Time::new(0, 0, -1, 0).is_err());
3261
3262
        assert!(Time::new(0, 0, 0, 1_000_000_000).is_err());
3263
        assert!(Time::new(0, 0, 0, -1).is_err());
3264
        assert!(Time::new(23, 59, 59, 1_000_000_000).is_err());
3265
        assert!(Time::new(23, 59, 59, -1).is_err());
3266
    }
3267
3268
    #[test]
3269
    fn rounding_cross_midnight() {
3270
        let t1 = time(23, 59, 59, 999_999_999);
3271
3272
        let t2 = t1.round(Unit::Nanosecond).unwrap();
3273
        assert_eq!(t2, t1);
3274
3275
        let t2 = t1.round(Unit::Millisecond).unwrap();
3276
        assert_eq!(t2, time(0, 0, 0, 0));
3277
3278
        let t2 = t1.round(Unit::Microsecond).unwrap();
3279
        assert_eq!(t2, time(0, 0, 0, 0));
3280
3281
        let t2 = t1.round(Unit::Millisecond).unwrap();
3282
        assert_eq!(t2, time(0, 0, 0, 0));
3283
3284
        let t2 = t1.round(Unit::Second).unwrap();
3285
        assert_eq!(t2, time(0, 0, 0, 0));
3286
3287
        let t2 = t1.round(Unit::Minute).unwrap();
3288
        assert_eq!(t2, time(0, 0, 0, 0));
3289
3290
        let t2 = t1.round(Unit::Hour).unwrap();
3291
        assert_eq!(t2, time(0, 0, 0, 0));
3292
3293
        let t1 = time(22, 15, 0, 0);
3294
        assert_eq!(
3295
            time(22, 30, 0, 0),
3296
            t1.round(TimeRound::new().smallest(Unit::Minute).increment(30))
3297
                .unwrap()
3298
        );
3299
    }
3300
3301
    #[cfg(not(miri))]
3302
    quickcheck::quickcheck! {
3303
        fn prop_ordering_same_as_civil_nanosecond(
3304
            ns1: i64,
3305
            ns2: i64
3306
        ) -> quickcheck::TestResult {
3307
            let Ok(ns1) = b::CivilDayNanosecond::check(ns1) else {
3308
                return quickcheck::TestResult::discard();
3309
            };
3310
            let Ok(ns2) = b::CivilDayNanosecond::check(ns2) else {
3311
                return quickcheck::TestResult::discard();
3312
            };
3313
            let t1 = Time::from_nanosecond_unchecked(ns1);
3314
            let t2 = Time::from_nanosecond_unchecked(ns2);
3315
            quickcheck::TestResult::from_bool(t1.cmp(&t2) == ns1.cmp(&ns2))
3316
        }
3317
3318
        fn prop_checked_add_then_sub(
3319
            time: Time,
3320
            nano_span: i64
3321
        ) -> quickcheck::TestResult {
3322
            let Ok(nano_span) = b::CivilDayNanosecond::check(nano_span) else {
3323
                return quickcheck::TestResult::discard();
3324
            };
3325
            let span = Span::new().nanoseconds(nano_span);
3326
            let Ok(sum) = time.checked_add(span) else {
3327
                return quickcheck::TestResult::discard()
3328
            };
3329
            let diff = sum.checked_sub(span).unwrap();
3330
            quickcheck::TestResult::from_bool(time == diff)
3331
        }
3332
3333
        fn prop_wrapping_add_then_sub(
3334
            time: Time,
3335
            nano_span: i64
3336
        ) -> quickcheck::TestResult {
3337
            let Ok(nano_span) = b::CivilDayNanosecond::check(nano_span) else {
3338
                return quickcheck::TestResult::discard();
3339
            };
3340
            let span = Span::new().nanoseconds(nano_span);
3341
            let sum = time.wrapping_add(span);
3342
            let diff = sum.wrapping_sub(span);
3343
            quickcheck::TestResult::from_bool(time == diff)
3344
        }
3345
3346
        fn prop_checked_add_equals_wrapping_add(
3347
            time: Time,
3348
            nano_span: i64
3349
        ) -> quickcheck::TestResult {
3350
            let Ok(nano_span) = b::CivilDayNanosecond::check(nano_span) else {
3351
                return quickcheck::TestResult::discard();
3352
            };
3353
            let span = Span::new().nanoseconds(nano_span);
3354
            let Ok(sum_checked) = time.checked_add(span) else {
3355
                return quickcheck::TestResult::discard()
3356
            };
3357
            let sum_wrapped = time.wrapping_add(span);
3358
            quickcheck::TestResult::from_bool(sum_checked == sum_wrapped)
3359
        }
3360
3361
        fn prop_checked_sub_equals_wrapping_sub(
3362
            time: Time,
3363
            nano_span: i64
3364
        ) -> quickcheck::TestResult {
3365
            let Ok(nano_span) = b::CivilDayNanosecond::check(nano_span) else {
3366
                return quickcheck::TestResult::discard();
3367
            };
3368
            let span = Span::new().nanoseconds(nano_span);
3369
            let Ok(diff_checked) = time.checked_sub(span) else {
3370
                return quickcheck::TestResult::discard()
3371
            };
3372
            let diff_wrapped = time.wrapping_sub(span);
3373
            quickcheck::TestResult::from_bool(diff_checked == diff_wrapped)
3374
        }
3375
3376
        fn prop_until_then_add(t1: Time, t2: Time) -> bool {
3377
            let span = t1.until(t2).unwrap();
3378
            t1.checked_add(span).unwrap() == t2
3379
        }
3380
3381
        fn prop_until_then_sub(t1: Time, t2: Time) -> bool {
3382
            let span = t1.until(t2).unwrap();
3383
            t2.checked_sub(span).unwrap() == t1
3384
        }
3385
3386
        fn prop_since_then_add(t1: Time, t2: Time) -> bool {
3387
            let span = t1.since(t2).unwrap();
3388
            t2.checked_add(span).unwrap() == t1
3389
        }
3390
3391
        fn prop_since_then_sub(t1: Time, t2: Time) -> bool {
3392
            let span = t1.since(t2).unwrap();
3393
            t1.checked_sub(span).unwrap() == t2
3394
        }
3395
3396
        fn prop_until_is_since_negated(t1: Time, t2: Time) -> bool {
3397
            t1.until(t2).unwrap().get_nanoseconds()
3398
                == t1.since(t2).unwrap().negate().get_nanoseconds()
3399
        }
3400
    }
3401
3402
    #[test]
3403
    fn overflowing_add() {
3404
        let t1 = time(23, 30, 0, 0);
3405
        let (t2, span) = t1.overflowing_add(&5.hours()).unwrap();
3406
        assert_eq!(t2, time(4, 30, 0, 0));
3407
        span_eq!(span, 1.days());
3408
    }
3409
3410
    #[test]
3411
    fn overflowing_add_overflows() {
3412
        let t1 = time(23, 30, 0, 0);
3413
        let span = Span::new()
3414
            .hours(b::SpanHours::MAX)
3415
            .minutes(b::SpanMinutes::MAX)
3416
            .seconds(b::SpanSeconds::MAX)
3417
            .milliseconds(b::SpanMilliseconds::MAX)
3418
            .microseconds(b::SpanMicroseconds::MAX)
3419
            .nanoseconds(b::SpanNanoseconds::MAX);
3420
        assert!(t1.overflowing_add(&span).is_err());
3421
    }
3422
3423
    #[test]
3424
    fn overflowing_add_span_negative() {
3425
        let t1 = time(0, 0, 0, 0);
3426
3427
        let (t2, span) = t1.overflowing_add(&1.second()).unwrap();
3428
        assert_eq!(t2, time(0, 0, 1, 0));
3429
        span_eq!(span, 0.days());
3430
3431
        let (t2, span) = t1.overflowing_add(&-1.second()).unwrap();
3432
        assert_eq!(t2, time(23, 59, 59, 0));
3433
        span_eq!(span, -1.days());
3434
3435
        let (t2, span) = t1.overflowing_add(&1.nanosecond()).unwrap();
3436
        assert_eq!(t2, time(0, 0, 0, 1));
3437
        span_eq!(span, 0.days());
3438
3439
        let (t2, span) = t1.overflowing_add(&-1.nanosecond()).unwrap();
3440
        assert_eq!(t2, time(23, 59, 59, 999_999_999));
3441
        span_eq!(span, -1.days());
3442
3443
        let (t2, span) =
3444
            t1.overflowing_add(&1.second().nanoseconds(2)).unwrap();
3445
        assert_eq!(t2, time(0, 0, 1, 2));
3446
        span_eq!(span, 0.days());
3447
3448
        let (t2, span) =
3449
            t1.overflowing_add(&-1.second().nanoseconds(2)).unwrap();
3450
        assert_eq!(t2, time(23, 59, 58, 999_999_998));
3451
        span_eq!(span, -1.days());
3452
    }
3453
3454
    #[test]
3455
    fn overflowing_add_duration_negative() {
3456
        let t1 = time(0, 0, 0, 0);
3457
3458
        let (t2, dur) =
3459
            t1.overflowing_add_duration(SignedDuration::from_secs(1)).unwrap();
3460
        assert_eq!(t2, time(0, 0, 1, 0));
3461
        assert_eq!(dur, SignedDuration::ZERO);
3462
3463
        let (t2, dur) = t1
3464
            .overflowing_add_duration(SignedDuration::from_secs(-1))
3465
            .unwrap();
3466
        assert_eq!(t2, time(23, 59, 59, 0));
3467
        assert_eq!(dur, SignedDuration::from_hours(-24));
3468
3469
        let (t2, dur) = t1
3470
            .overflowing_add_duration(SignedDuration::from_nanos(1))
3471
            .unwrap();
3472
        assert_eq!(t2, time(0, 0, 0, 1));
3473
        assert_eq!(dur, SignedDuration::ZERO);
3474
3475
        let (t2, dur) = t1
3476
            .overflowing_add_duration(SignedDuration::from_nanos(-1))
3477
            .unwrap();
3478
        assert_eq!(t2, time(23, 59, 59, 999_999_999));
3479
        assert_eq!(dur, SignedDuration::from_hours(-24));
3480
3481
        let (t2, dur) =
3482
            t1.overflowing_add_duration(SignedDuration::new(1, 2)).unwrap();
3483
        assert_eq!(t2, time(0, 0, 1, 2));
3484
        assert_eq!(dur, SignedDuration::ZERO);
3485
3486
        let (t2, dur) =
3487
            t1.overflowing_add_duration(SignedDuration::new(-1, -2)).unwrap();
3488
        assert_eq!(t2, time(23, 59, 58, 999_999_998));
3489
        assert_eq!(dur, SignedDuration::from_hours(-24));
3490
    }
3491
3492
    #[test]
3493
    fn time_size() {
3494
        #[cfg(debug_assertions)]
3495
        {
3496
            assert_eq!(8, core::mem::size_of::<Time>());
3497
        }
3498
        #[cfg(not(debug_assertions))]
3499
        {
3500
            assert_eq!(8, core::mem::size_of::<Time>());
3501
        }
3502
    }
3503
3504
    // This test checks that a wrapping subtraction with the minimum signed
3505
    // duration is as expected.
3506
    #[test]
3507
    fn wrapping_sub_signed_duration_min() {
3508
        let max = -SignedDuration::MIN.as_nanos();
3509
        let got = i128::from(time(15, 30, 8, 999_999_999).to_nanosecond());
3510
        let expected = max.rem_euclid(i128::from(b::NANOS_PER_CIVIL_DAY));
3511
        assert_eq!(got, expected);
3512
    }
3513
3514
    // This test checks that a wrapping subtraction with the maximum signed
3515
    // duration is as expected.
3516
    #[test]
3517
    fn wrapping_sub_signed_duration_max() {
3518
        let max = -SignedDuration::MAX.as_nanos();
3519
        let got = i128::from(time(8, 29, 52, 1).to_nanosecond());
3520
        let expected = max.rem_euclid(i128::from(b::NANOS_PER_CIVIL_DAY));
3521
        assert_eq!(got, expected);
3522
    }
3523
3524
    // This test checks that a wrapping subtraction with the maximum unsigned
3525
    // duration is as expected.
3526
    #[test]
3527
    fn wrapping_sub_unsigned_duration_max() {
3528
        let max =
3529
            -i128::try_from(std::time::Duration::MAX.as_nanos()).unwrap();
3530
        let got = i128::from(time(16, 59, 44, 1).to_nanosecond());
3531
        let expected = max.rem_euclid(i128::from(b::NANOS_PER_CIVIL_DAY));
3532
        assert_eq!(got, expected);
3533
    }
3534
3535
    /// # `serde` deserializer compatibility test
3536
    ///
3537
    /// Serde YAML used to be unable to deserialize `jiff` types,
3538
    /// as deserializing from bytes is not supported by the deserializer.
3539
    ///
3540
    /// - <https://github.com/BurntSushi/jiff/issues/138>
3541
    /// - <https://github.com/BurntSushi/jiff/discussions/148>
3542
    #[test]
3543
    fn civil_time_deserialize_yaml() {
3544
        let expected = time(16, 35, 4, 987654321);
3545
3546
        let deserialized: Time =
3547
            serde_yaml::from_str("16:35:04.987654321").unwrap();
3548
3549
        assert_eq!(deserialized, expected);
3550
3551
        let deserialized: Time =
3552
            serde_yaml::from_slice("16:35:04.987654321".as_bytes()).unwrap();
3553
3554
        assert_eq!(deserialized, expected);
3555
3556
        let cursor = Cursor::new(b"16:35:04.987654321");
3557
        let deserialized: Time = serde_yaml::from_reader(cursor).unwrap();
3558
3559
        assert_eq!(deserialized, expected);
3560
    }
3561
}