Coverage Report

Created: 2025-11-16 06:22

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