jiff/civil/
time.rs

1use core::time::Duration as UnsignedDuration;
2
3use 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)]
222pub struct Time {
223    hour: Hour,
224    minute: Minute,
225    second: Second,
226    subsec_nanosecond: SubsecNanosecond,
227}
228
229impl 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    pub fn new(
282        hour: i8,
283        minute: i8,
284        second: i8,
285        subsec_nanosecond: i32,
286    ) -> Result<Time, Error> {
287        let hour = Hour::try_new("hour", hour)?;
288        let minute = Minute::try_new("minute", minute)?;
289        let second = Second::try_new("second", second)?;
290        let subsec_nanosecond =
291            SubsecNanosecond::try_new("subsec_nanosecond", subsec_nanosecond)?;
292        Ok(Time::new_ranged(hour, minute, second, subsec_nanosecond))
293    }
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    pub const fn constant(
328        hour: i8,
329        minute: i8,
330        second: i8,
331        subsec_nanosecond: i32,
332    ) -> Time {
333        if !Hour::contains(hour) {
334            panic!("invalid hour");
335        }
336        if !Minute::contains(minute) {
337            panic!("invalid minute");
338        }
339        if !Second::contains(second) {
340            panic!("invalid second");
341        }
342        if !SubsecNanosecond::contains(subsec_nanosecond) {
343            panic!("invalid nanosecond");
344        }
345        let hour = Hour::new_unchecked(hour);
346        let minute = Minute::new_unchecked(minute);
347        let second = Second::new_unchecked(second);
348        let subsec_nanosecond =
349            SubsecNanosecond::new_unchecked(subsec_nanosecond);
350        Time { hour, minute, second, subsec_nanosecond }
351    }
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    pub const fn midnight() -> Time {
373        Time::constant(0, 0, 0, 0)
374    }
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    pub fn with(self) -> TimeWith {
404        TimeWith::new(self)
405    }
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    pub fn hour(self) -> i8 {
421        self.hour_ranged().get()
422    }
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    pub fn minute(self) -> i8 {
438        self.minute_ranged().get()
439    }
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    pub fn second(self) -> i8 {
455        self.second_ranged().get()
456    }
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    pub fn millisecond(self) -> i16 {
472        self.millisecond_ranged().get()
473    }
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    pub fn microsecond(self) -> i16 {
489        self.microsecond_ranged().get()
490    }
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    pub fn nanosecond(self) -> i16 {
506        self.nanosecond_ranged().get()
507    }
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    pub fn subsec_nanosecond(self) -> i32 {
558        self.subsec_nanosecond_ranged().get()
559    }
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    pub const fn to_datetime(self, date: Date) -> DateTime {
577        DateTime::from_parts(date, self)
578    }
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    pub const fn on(self, year: i16, month: i8, day: i8) -> DateTime {
606        DateTime::from_parts(Date::constant(year, month, day), self)
607    }
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    pub fn wrapping_add<A: Into<TimeArithmetic>>(self, duration: A) -> Time {
704        let duration: TimeArithmetic = duration.into();
705        duration.wrapping_add(self)
706    }
707
708    #[inline]
709    fn wrapping_add_span(self, span: Span) -> Time {
710        let mut sum = self.to_nanosecond().without_bounds();
711        sum = sum.wrapping_add(
712            span.get_hours_ranged()
713                .without_bounds()
714                .wrapping_mul(t::NANOS_PER_HOUR),
715        );
716        sum = sum.wrapping_add(
717            span.get_minutes_ranged()
718                .without_bounds()
719                .wrapping_mul(t::NANOS_PER_MINUTE),
720        );
721        sum = sum.wrapping_add(
722            span.get_seconds_ranged()
723                .without_bounds()
724                .wrapping_mul(t::NANOS_PER_SECOND),
725        );
726        sum = sum.wrapping_add(
727            span.get_milliseconds_ranged()
728                .without_bounds()
729                .wrapping_mul(t::NANOS_PER_MILLI),
730        );
731        sum = sum.wrapping_add(
732            span.get_microseconds_ranged()
733                .without_bounds()
734                .wrapping_mul(t::NANOS_PER_MICRO),
735        );
736        sum = sum.wrapping_add(span.get_nanoseconds_ranged().without_bounds());
737        let civil_day_nanosecond = sum % t::NANOS_PER_CIVIL_DAY;
738        Time::from_nanosecond(civil_day_nanosecond.rinto())
739    }
740
741    #[inline]
742    fn wrapping_add_signed_duration(self, duration: SignedDuration) -> Time {
743        let start = t::NoUnits128::rfrom(self.to_nanosecond());
744        let duration = t::NoUnits128::new_unchecked(duration.as_nanos());
745        let end = start.wrapping_add(duration) % t::NANOS_PER_CIVIL_DAY;
746        Time::from_nanosecond(end.rinto())
747    }
748
749    #[inline]
750    fn wrapping_add_unsigned_duration(
751        self,
752        duration: UnsignedDuration,
753    ) -> Time {
754        let start = t::NoUnits128::rfrom(self.to_nanosecond());
755        // OK because 96-bit unsigned integer can't overflow i128.
756        let duration = i128::try_from(duration.as_nanos()).unwrap();
757        let duration = t::NoUnits128::new_unchecked(duration);
758        let duration = duration % t::NANOS_PER_CIVIL_DAY;
759        let end = start.wrapping_add(duration) % t::NANOS_PER_CIVIL_DAY;
760        Time::from_nanosecond(end.rinto())
761    }
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    pub fn wrapping_sub<A: Into<TimeArithmetic>>(self, duration: A) -> Time {
800        let duration: TimeArithmetic = duration.into();
801        duration.wrapping_sub(self)
802    }
803
804    #[inline]
805    fn wrapping_sub_unsigned_duration(
806        self,
807        duration: UnsignedDuration,
808    ) -> Time {
809        let start = t::NoUnits128::rfrom(self.to_nanosecond());
810        // OK because 96-bit unsigned integer can't overflow i128.
811        let duration = i128::try_from(duration.as_nanos()).unwrap();
812        let duration = t::NoUnits128::new_unchecked(duration);
813        let end = start.wrapping_sub(duration) % t::NANOS_PER_CIVIL_DAY;
814        Time::from_nanosecond(end.rinto())
815    }
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    pub fn checked_add<A: Into<TimeArithmetic>>(
932        self,
933        duration: A,
934    ) -> Result<Time, Error> {
935        let duration: TimeArithmetic = duration.into();
936        duration.checked_add(self)
937    }
938
939    #[inline]
940    fn checked_add_span(self, span: Span) -> Result<Time, Error> {
941        let (time, span) = self.overflowing_add(span)?;
942        if let Some(err) = span.smallest_non_time_non_zero_unit_error() {
943            return Err(err);
944        }
945        Ok(time)
946    }
947
948    #[inline]
949    fn checked_add_duration(
950        self,
951        duration: SignedDuration,
952    ) -> Result<Time, Error> {
953        let original = duration;
954        let start = t::NoUnits128::rfrom(self.to_nanosecond());
955        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        let end = start.try_checked_add("nanoseconds", duration).unwrap();
960        let end = CivilDayNanosecond::try_rfrom("nanoseconds", end)
961            .with_context(|| {
962                err!(
963                    "adding signed duration {duration:?}, equal to
964                     {nanos} nanoseconds, to {time} overflowed",
965                    duration = original,
966                    nanos = original.as_nanos(),
967                    time = self,
968                )
969            })?;
970        Ok(Time::from_nanosecond(end))
971    }
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    pub fn checked_sub<A: Into<TimeArithmetic>>(
1004        self,
1005        duration: A,
1006    ) -> Result<Time, Error> {
1007        let duration: TimeArithmetic = duration.into();
1008        duration.checked_neg().and_then(|ta| ta.checked_add(self))
1009    }
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    pub fn saturating_add<A: Into<TimeArithmetic>>(self, duration: A) -> Time {
1049        let duration: TimeArithmetic = duration.into();
1050        self.checked_add(duration).unwrap_or_else(|_| {
1051            if duration.is_negative() {
1052                Time::MIN
1053            } else {
1054                Time::MAX
1055            }
1056        })
1057    }
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    pub fn saturating_sub<A: Into<TimeArithmetic>>(self, duration: A) -> Time {
1085        let duration: TimeArithmetic = duration.into();
1086        let Ok(duration) = duration.checked_neg() else { return Time::MIN };
1087        self.saturating_add(duration)
1088    }
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    pub(crate) fn overflowing_add(
1102        self,
1103        span: Span,
1104    ) -> Result<(Time, Span), Error> {
1105        if let Some(err) = span.smallest_non_time_non_zero_unit_error() {
1106            return Err(err);
1107        }
1108        let span_nanos = span.to_invariant_nanoseconds();
1109        let time_nanos = self.to_nanosecond();
1110        let sum = span_nanos + time_nanos;
1111        let days = t::SpanDays::try_new(
1112            "overflowing-days",
1113            sum.div_floor(t::NANOS_PER_CIVIL_DAY),
1114        )?;
1115        let time_nanos = sum.rem_floor(t::NANOS_PER_CIVIL_DAY);
1116        let time = Time::from_nanosecond(time_nanos.rinto());
1117        Ok((time, Span::new().days_ranged(days)))
1118    }
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    pub(crate) fn overflowing_add_duration(
1126        self,
1127        duration: SignedDuration,
1128    ) -> Result<(Time, SignedDuration), Error> {
1129        if self.subsec_nanosecond() != 0 || duration.subsec_nanos() != 0 {
1130            return self.overflowing_add_duration_general(duration);
1131        }
1132        let start = t::NoUnits::rfrom(self.to_second());
1133        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        let Some(sum) = start.checked_add(duration_secs) else {
1138            return self.overflowing_add_duration_general(duration);
1139        };
1140        let days = t::SpanDays::try_new(
1141            "overflowing-days",
1142            sum.div_floor(t::SECONDS_PER_CIVIL_DAY),
1143        )?;
1144        let time_secs = sum.rem_floor(t::SECONDS_PER_CIVIL_DAY);
1145        let time = Time::from_second(time_secs.rinto());
1146        // OK because of the constraint imposed by t::SpanDays.
1147        let hours = i64::from(days).checked_mul(24).unwrap();
1148        Ok((time, SignedDuration::from_hours(hours)))
1149    }
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    fn overflowing_add_duration_general(
1158        self,
1159        duration: SignedDuration,
1160    ) -> Result<(Time, SignedDuration), Error> {
1161        let start = t::NoUnits128::rfrom(self.to_nanosecond());
1162        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        let sum = start.try_checked_add("nanoseconds", duration).unwrap();
1167        let days = t::SpanDays::try_new(
1168            "overflowing-days",
1169            sum.div_floor(t::NANOS_PER_CIVIL_DAY),
1170        )?;
1171        let time_nanos = sum.rem_floor(t::NANOS_PER_CIVIL_DAY);
1172        let time = Time::from_nanosecond(time_nanos.rinto());
1173        // OK because of the constraint imposed by t::SpanDays.
1174        let hours = i64::from(days).checked_mul(24).unwrap();
1175        Ok((time, SignedDuration::from_hours(hours)))
1176    }
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    pub fn until<A: Into<TimeDifference>>(
1248        self,
1249        other: A,
1250    ) -> Result<Span, Error> {
1251        let args: TimeDifference = other.into();
1252        let span = args.until_with_largest_unit(self)?;
1253        if args.rounding_may_change_span() {
1254            span.round(args.round)
1255        } else {
1256            Ok(span)
1257        }
1258    }
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    pub fn since<A: Into<TimeDifference>>(
1282        self,
1283        other: A,
1284    ) -> Result<Span, Error> {
1285        let args: TimeDifference = other.into();
1286        let span = -args.until_with_largest_unit(self)?;
1287        if args.rounding_may_change_span() {
1288            span.round(args.round)
1289        } else {
1290            Ok(span)
1291        }
1292    }
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    pub fn duration_until(self, other: Time) -> SignedDuration {
1394        SignedDuration::time_until(self, other)
1395    }
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    pub fn duration_since(self, other: Time) -> SignedDuration {
1414        SignedDuration::time_until(other, self)
1415    }
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    pub fn round<R: Into<TimeRound>>(self, options: R) -> Result<Time, Error> {
1532        let options: TimeRound = options.into();
1533        options.round(self)
1534    }
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    pub fn series(self, period: Span) -> TimeSeries {
1583        TimeSeries { start: self, period, step: 0 }
1584    }
1585}
1586
1587/// Parsing and formatting using a "printf"-style API.
1588impl 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    pub fn strptime(
1620        format: impl AsRef<[u8]>,
1621        input: impl AsRef<[u8]>,
1622    ) -> Result<Time, Error> {
1623        fmt::strtime::parse(format, input).and_then(|tm| tm.to_time())
1624    }
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    pub fn strftime<'f, F: 'f + ?Sized + AsRef<[u8]>>(
1669        &self,
1670        format: &'f F,
1671    ) -> fmt::strtime::Display<'f> {
1672        fmt::strtime::Display { fmt: format.as_ref(), tm: (*self).into() }
1673    }
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.
1682impl Time {
1683    #[inline]
1684    pub(crate) fn new_ranged(
1685        hour: impl RInto<Hour>,
1686        minute: impl RInto<Minute>,
1687        second: impl RInto<Second>,
1688        subsec_nanosecond: impl RInto<SubsecNanosecond>,
1689    ) -> Time {
1690        Time {
1691            hour: hour.rinto(),
1692            minute: minute.rinto(),
1693            second: second.rinto(),
1694            subsec_nanosecond: subsec_nanosecond.rinto(),
1695        }
1696    }
1697
1698    /// Set the fractional parts of this time to the given units via ranged
1699    /// types.
1700    #[inline]
1701    fn with_subsec_parts_ranged(
1702        self,
1703        millisecond: impl RInto<Millisecond>,
1704        microsecond: impl RInto<Microsecond>,
1705        nanosecond: impl RInto<Nanosecond>,
1706    ) -> Time {
1707        let millisecond = SubsecNanosecond::rfrom(millisecond.rinto());
1708        let microsecond = SubsecNanosecond::rfrom(microsecond.rinto());
1709        let nanosecond = SubsecNanosecond::rfrom(nanosecond.rinto());
1710        let mut subsec_nanosecond =
1711            millisecond * t::MICROS_PER_MILLI * t::NANOS_PER_MICRO;
1712        subsec_nanosecond += microsecond * t::NANOS_PER_MICRO;
1713        subsec_nanosecond += nanosecond;
1714        Time { subsec_nanosecond: subsec_nanosecond.rinto(), ..self }
1715    }
1716
1717    #[inline]
1718    pub(crate) fn hour_ranged(self) -> Hour {
1719        self.hour
1720    }
1721
1722    #[inline]
1723    pub(crate) fn minute_ranged(self) -> Minute {
1724        self.minute
1725    }
1726
1727    #[inline]
1728    pub(crate) fn second_ranged(self) -> Second {
1729        self.second
1730    }
1731
1732    #[inline]
1733    pub(crate) fn millisecond_ranged(self) -> Millisecond {
1734        let micros = self.subsec_nanosecond_ranged() / t::NANOS_PER_MICRO;
1735        let millis = micros / t::MICROS_PER_MILLI;
1736        millis.rinto()
1737    }
1738
1739    #[inline]
1740    pub(crate) fn microsecond_ranged(self) -> Microsecond {
1741        let micros = self.subsec_nanosecond_ranged() / t::NANOS_PER_MICRO;
1742        let only_micros = micros % t::MICROS_PER_MILLI;
1743        only_micros.rinto()
1744    }
1745
1746    #[inline]
1747    pub(crate) fn nanosecond_ranged(self) -> Nanosecond {
1748        let only_nanos = self.subsec_nanosecond_ranged() % t::NANOS_PER_MICRO;
1749        only_nanos.rinto()
1750    }
1751
1752    #[inline]
1753    pub(crate) fn subsec_nanosecond_ranged(self) -> SubsecNanosecond {
1754        self.subsec_nanosecond
1755    }
1756
1757    #[inline]
1758    pub(crate) fn until_nanoseconds(self, other: Time) -> t::SpanNanoseconds {
1759        let t1 = t::SpanNanoseconds::rfrom(self.to_nanosecond());
1760        let t2 = t::SpanNanoseconds::rfrom(other.to_nanosecond());
1761        t2 - t1
1762    }
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    pub(crate) fn to_second(&self) -> CivilDaySecond {
1772        self.to_itime().map(|x| x.to_second().second).to_rint()
1773    }
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    pub(crate) fn from_second(second: CivilDaySecond) -> Time {
1780        let second = rangeint::composite!((second) => {
1781            ITimeSecond { second }
1782        });
1783        Time::from_itime(second.map(|x| x.to_time()))
1784    }
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    pub(crate) fn to_nanosecond(&self) -> CivilDayNanosecond {
1793        self.to_itime().map(|x| x.to_nanosecond().nanosecond).to_rint()
1794    }
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    pub(crate) fn from_nanosecond(nanosecond: CivilDayNanosecond) -> Time {
1801        let nano = rangeint::composite!((nanosecond) => {
1802            ITimeNanosecond { nanosecond }
1803        });
1804        Time::from_itime(nano.map(|x| x.to_time()))
1805    }
1806
1807    #[inline]
1808    pub(crate) fn to_itime(&self) -> Composite<ITime> {
1809        rangeint::composite! {
1810            (
1811                hour = self.hour,
1812                minute = self.minute,
1813                second = self.second,
1814                subsec_nanosecond = self.subsec_nanosecond,
1815            ) => {
1816                ITime { hour, minute, second, subsec_nanosecond }
1817            }
1818        }
1819    }
1820
1821    #[inline]
1822    pub(crate) fn from_itime(itime: Composite<ITime>) -> Time {
1823        let (hour, minute, second, subsec_nanosecond) = rangeint::uncomposite!(
1824            itime,
1825            c => (c.hour, c.minute, c.second, c.subsec_nanosecond),
1826        );
1827        Time {
1828            hour: hour.to_rint(),
1829            minute: minute.to_rint(),
1830            second: second.to_rint(),
1831            subsec_nanosecond: subsec_nanosecond.to_rint(),
1832        }
1833    }
1834
1835    #[inline]
1836    pub(crate) const fn to_itime_const(&self) -> ITime {
1837        ITime {
1838            hour: self.hour.get_unchecked(),
1839            minute: self.minute.get_unchecked(),
1840            second: self.second.get_unchecked(),
1841            subsec_nanosecond: self.subsec_nanosecond.get_unchecked(),
1842        }
1843    }
1844}
1845
1846impl Default for Time {
1847    #[inline]
1848    fn default() -> Time {
1849        Time::midnight()
1850    }
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/// ```
1878impl core::fmt::Debug for Time {
1879    #[inline]
1880    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1881        core::fmt::Display::fmt(self, f)
1882    }
1883}
1884
1885/// Converts a `Time` into an ISO 8601 compliant string.
1886///
1887/// Options currently supported:
1888///
1889/// * [`std::fmt::Formatter::precision`] can be set to control the precision
1890/// of the fractional second component.
1891///
1892/// # Example
1893///
1894/// ```
1895/// use jiff::civil::time;
1896///
1897/// let t = time(7, 0, 0, 123_000_000);
1898/// assert_eq!(format!("{t:.6}"), "07:00:00.123000");
1899/// // Precision values greater than 9 are clamped to 9.
1900/// assert_eq!(format!("{t:.300}"), "07:00:00.123000000");
1901/// // A precision of 0 implies the entire fractional
1902/// // component is always truncated.
1903/// assert_eq!(format!("{t:.0}"), "07:00:00");
1904///
1905/// # Ok::<(), Box<dyn std::error::Error>>(())
1906/// ```
1907impl core::fmt::Display for Time {
1908    #[inline]
1909    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1910        use crate::fmt::StdFmtWrite;
1911
1912        let precision =
1913            f.precision().map(|p| u8::try_from(p).unwrap_or(u8::MAX));
1914        temporal::DateTimePrinter::new()
1915            .precision(precision)
1916            .print_time(self, StdFmtWrite(f))
1917            .map_err(|_| core::fmt::Error)
1918    }
1919}
1920
1921impl core::str::FromStr for Time {
1922    type Err = Error;
1923
1924    #[inline]
1925    fn from_str(string: &str) -> Result<Time, Error> {
1926        DEFAULT_DATETIME_PARSER.parse_time(string)
1927    }
1928}
1929
1930/// Adds a span of time. This uses wrapping arithmetic.
1931///
1932/// For checked arithmetic, see [`Time::checked_add`].
1933impl core::ops::Add<Span> for Time {
1934    type Output = Time;
1935
1936    #[inline]
1937    fn add(self, rhs: Span) -> Time {
1938        self.wrapping_add(rhs)
1939    }
1940}
1941
1942/// Adds a span of time in place. This uses wrapping arithmetic.
1943///
1944/// For checked arithmetic, see [`Time::checked_add`].
1945impl core::ops::AddAssign<Span> for Time {
1946    #[inline]
1947    fn add_assign(&mut self, rhs: Span) {
1948        *self = *self + rhs;
1949    }
1950}
1951
1952/// Subtracts a span of time. This uses wrapping arithmetic.
1953///
1954/// For checked arithmetic, see [`Time::checked_sub`].
1955impl core::ops::Sub<Span> for Time {
1956    type Output = Time;
1957
1958    #[inline]
1959    fn sub(self, rhs: Span) -> Time {
1960        self.wrapping_sub(rhs)
1961    }
1962}
1963
1964/// Subtracts a span of time in place. This uses wrapping arithmetic.
1965///
1966/// For checked arithmetic, see [`Time::checked_sub`].
1967impl core::ops::SubAssign<Span> for Time {
1968    #[inline]
1969    fn sub_assign(&mut self, rhs: Span) {
1970        *self = *self - rhs;
1971    }
1972}
1973
1974/// Computes the span of time between two times.
1975///
1976/// This will return a negative span when the time being subtracted is greater.
1977///
1978/// Since this uses the default configuration for calculating a span between
1979/// two times (no rounding and largest units is hours), this will never panic
1980/// or fail in any way.
1981///
1982/// To configure the largest unit or enable rounding, use [`Time::since`].
1983impl core::ops::Sub for Time {
1984    type Output = Span;
1985
1986    #[inline]
1987    fn sub(self, rhs: Time) -> Span {
1988        self.since(rhs).expect("since never fails when given Time")
1989    }
1990}
1991
1992/// Adds a signed duration of time. This uses wrapping arithmetic.
1993///
1994/// For checked arithmetic, see [`Time::checked_add`].
1995impl core::ops::Add<SignedDuration> for Time {
1996    type Output = Time;
1997
1998    #[inline]
1999    fn add(self, rhs: SignedDuration) -> Time {
2000        self.wrapping_add(rhs)
2001    }
2002}
2003
2004/// Adds a signed duration of time in place. This uses wrapping arithmetic.
2005///
2006/// For checked arithmetic, see [`Time::checked_add`].
2007impl core::ops::AddAssign<SignedDuration> for Time {
2008    #[inline]
2009    fn add_assign(&mut self, rhs: SignedDuration) {
2010        *self = *self + rhs;
2011    }
2012}
2013
2014/// Subtracts a signed duration of time. This uses wrapping arithmetic.
2015///
2016/// For checked arithmetic, see [`Time::checked_sub`].
2017impl core::ops::Sub<SignedDuration> for Time {
2018    type Output = Time;
2019
2020    #[inline]
2021    fn sub(self, rhs: SignedDuration) -> Time {
2022        self.wrapping_sub(rhs)
2023    }
2024}
2025
2026/// Subtracts a signed duration of time in place. This uses wrapping arithmetic.
2027///
2028/// For checked arithmetic, see [`Time::checked_sub`].
2029impl core::ops::SubAssign<SignedDuration> for Time {
2030    #[inline]
2031    fn sub_assign(&mut self, rhs: SignedDuration) {
2032        *self = *self - rhs;
2033    }
2034}
2035
2036/// Adds an unsigned duration of time. This uses wrapping arithmetic.
2037///
2038/// For checked arithmetic, see [`Time::checked_add`].
2039impl core::ops::Add<UnsignedDuration> for Time {
2040    type Output = Time;
2041
2042    #[inline]
2043    fn add(self, rhs: UnsignedDuration) -> Time {
2044        self.wrapping_add(rhs)
2045    }
2046}
2047
2048/// Adds an unsigned duration of time in place. This uses wrapping arithmetic.
2049///
2050/// For checked arithmetic, see [`Time::checked_add`].
2051impl core::ops::AddAssign<UnsignedDuration> for Time {
2052    #[inline]
2053    fn add_assign(&mut self, rhs: UnsignedDuration) {
2054        *self = *self + rhs;
2055    }
2056}
2057
2058/// Subtracts an unsigned duration of time. This uses wrapping arithmetic.
2059///
2060/// For checked arithmetic, see [`Time::checked_sub`].
2061impl core::ops::Sub<UnsignedDuration> for Time {
2062    type Output = Time;
2063
2064    #[inline]
2065    fn sub(self, rhs: UnsignedDuration) -> Time {
2066        self.wrapping_sub(rhs)
2067    }
2068}
2069
2070/// Subtracts an unsigned duration of time in place. This uses wrapping
2071/// arithmetic.
2072///
2073/// For checked arithmetic, see [`Time::checked_sub`].
2074impl core::ops::SubAssign<UnsignedDuration> for Time {
2075    #[inline]
2076    fn sub_assign(&mut self, rhs: UnsignedDuration) {
2077        *self = *self - rhs;
2078    }
2079}
2080
2081impl From<DateTime> for Time {
2082    #[inline]
2083    fn from(dt: DateTime) -> Time {
2084        dt.time()
2085    }
2086}
2087
2088impl From<Zoned> for Time {
2089    #[inline]
2090    fn from(zdt: Zoned) -> Time {
2091        zdt.datetime().time()
2092    }
2093}
2094
2095impl<'a> From<&'a Zoned> for Time {
2096    #[inline]
2097    fn from(zdt: &'a Zoned) -> Time {
2098        zdt.datetime().time()
2099    }
2100}
2101
2102#[cfg(feature = "serde")]
2103impl serde::Serialize for Time {
2104    #[inline]
2105    fn serialize<S: serde::Serializer>(
2106        &self,
2107        serializer: S,
2108    ) -> Result<S::Ok, S::Error> {
2109        serializer.collect_str(self)
2110    }
2111}
2112
2113#[cfg(feature = "serde")]
2114impl<'de> serde::Deserialize<'de> for Time {
2115    #[inline]
2116    fn deserialize<D: serde::Deserializer<'de>>(
2117        deserializer: D,
2118    ) -> Result<Time, D::Error> {
2119        use serde::de;
2120
2121        struct TimeVisitor;
2122
2123        impl<'de> de::Visitor<'de> for TimeVisitor {
2124            type Value = Time;
2125
2126            fn expecting(
2127                &self,
2128                f: &mut core::fmt::Formatter,
2129            ) -> core::fmt::Result {
2130                f.write_str("a time string")
2131            }
2132
2133            #[inline]
2134            fn visit_bytes<E: de::Error>(
2135                self,
2136                value: &[u8],
2137            ) -> Result<Time, E> {
2138                DEFAULT_DATETIME_PARSER
2139                    .parse_time(value)
2140                    .map_err(de::Error::custom)
2141            }
2142
2143            #[inline]
2144            fn visit_str<E: de::Error>(self, value: &str) -> Result<Time, E> {
2145                self.visit_bytes(value.as_bytes())
2146            }
2147        }
2148
2149        deserializer.deserialize_str(TimeVisitor)
2150    }
2151}
2152
2153#[cfg(test)]
2154impl quickcheck::Arbitrary for Time {
2155    fn arbitrary(g: &mut quickcheck::Gen) -> Time {
2156        let hour = Hour::arbitrary(g);
2157        let minute = Minute::arbitrary(g);
2158        let second = Second::arbitrary(g);
2159        let subsec_nanosecond = SubsecNanosecond::arbitrary(g);
2160        Time::new_ranged(hour, minute, second, subsec_nanosecond)
2161    }
2162
2163    fn shrink(&self) -> alloc::boxed::Box<dyn Iterator<Item = Time>> {
2164        alloc::boxed::Box::new(
2165            (
2166                self.hour_ranged(),
2167                self.minute_ranged(),
2168                self.second_ranged(),
2169                self.subsec_nanosecond_ranged(),
2170            )
2171                .shrink()
2172                .map(
2173                    |(hour, minute, second, subsec_nanosecond)| {
2174                        Time::new_ranged(
2175                            hour,
2176                            minute,
2177                            second,
2178                            subsec_nanosecond,
2179                        )
2180                    },
2181                ),
2182        )
2183    }
2184}
2185
2186/// An iterator over periodic times, created by [`Time::series`].
2187///
2188/// It is exhausted when the next value would exceed a [`Span`] or [`Time`]
2189/// value.
2190#[derive(Clone, Debug)]
2191pub struct TimeSeries {
2192    start: Time,
2193    period: Span,
2194    step: i64,
2195}
2196
2197impl Iterator for TimeSeries {
2198    type Item = Time;
2199
2200    #[inline]
2201    fn next(&mut self) -> Option<Time> {
2202        let span = self.period.checked_mul(self.step).ok()?;
2203        self.step = self.step.checked_add(1)?;
2204        let time = self.start.checked_add(span).ok()?;
2205        Some(time)
2206    }
2207}
2208
2209/// Options for [`Time::checked_add`] and [`Time::checked_sub`].
2210///
2211/// This type provides a way to ergonomically add one of a few different
2212/// duration types to a [`Time`].
2213///
2214/// The main way to construct values of this type is with its `From` trait
2215/// implementations:
2216///
2217/// * `From<Span> for TimeArithmetic` adds (or subtracts) the given span to the
2218/// receiver time.
2219/// * `From<SignedDuration> for TimeArithmetic` adds (or subtracts)
2220/// the given signed duration to the receiver time.
2221/// * `From<std::time::Duration> for TimeArithmetic` adds (or subtracts)
2222/// the given unsigned duration to the receiver time.
2223///
2224/// # Example
2225///
2226/// ```
2227/// use std::time::Duration;
2228///
2229/// use jiff::{civil::time, SignedDuration, ToSpan};
2230///
2231/// let t = time(0, 0, 0, 0);
2232/// assert_eq!(t.checked_add(2.hours())?, time(2, 0, 0, 0));
2233/// assert_eq!(t.checked_add(SignedDuration::from_hours(2))?, time(2, 0, 0, 0));
2234/// assert_eq!(t.checked_add(Duration::from_secs(2 * 60 * 60))?, time(2, 0, 0, 0));
2235///
2236/// # Ok::<(), Box<dyn std::error::Error>>(())
2237/// ```
2238#[derive(Clone, Copy, Debug)]
2239pub struct TimeArithmetic {
2240    duration: Duration,
2241}
2242
2243impl TimeArithmetic {
2244    #[inline]
2245    fn wrapping_add(self, time: Time) -> Time {
2246        match self.duration {
2247            Duration::Span(span) => time.wrapping_add_span(span),
2248            Duration::Signed(sdur) => time.wrapping_add_signed_duration(sdur),
2249            Duration::Unsigned(udur) => {
2250                time.wrapping_add_unsigned_duration(udur)
2251            }
2252        }
2253    }
2254
2255    #[inline]
2256    fn wrapping_sub(self, time: Time) -> Time {
2257        match self.duration {
2258            Duration::Span(span) => time.wrapping_add_span(span.negate()),
2259            Duration::Signed(sdur) => {
2260                if let Some(sdur) = sdur.checked_neg() {
2261                    time.wrapping_add_signed_duration(sdur)
2262                } else {
2263                    let udur = UnsignedDuration::new(
2264                        i64::MIN.unsigned_abs(),
2265                        sdur.subsec_nanos().unsigned_abs(),
2266                    );
2267                    time.wrapping_add_unsigned_duration(udur)
2268                }
2269            }
2270            Duration::Unsigned(udur) => {
2271                time.wrapping_sub_unsigned_duration(udur)
2272            }
2273        }
2274    }
2275
2276    #[inline]
2277    fn checked_add(self, time: Time) -> Result<Time, Error> {
2278        match self.duration.to_signed()? {
2279            SDuration::Span(span) => time.checked_add_span(span),
2280            SDuration::Absolute(sdur) => time.checked_add_duration(sdur),
2281        }
2282    }
2283
2284    #[inline]
2285    fn checked_neg(self) -> Result<TimeArithmetic, Error> {
2286        let duration = self.duration.checked_neg()?;
2287        Ok(TimeArithmetic { duration })
2288    }
2289
2290    #[inline]
2291    fn is_negative(&self) -> bool {
2292        self.duration.is_negative()
2293    }
2294}
2295
2296impl From<Span> for TimeArithmetic {
2297    fn from(span: Span) -> TimeArithmetic {
2298        let duration = Duration::from(span);
2299        TimeArithmetic { duration }
2300    }
2301}
2302
2303impl From<SignedDuration> for TimeArithmetic {
2304    fn from(sdur: SignedDuration) -> TimeArithmetic {
2305        let duration = Duration::from(sdur);
2306        TimeArithmetic { duration }
2307    }
2308}
2309
2310impl From<UnsignedDuration> for TimeArithmetic {
2311    fn from(udur: UnsignedDuration) -> TimeArithmetic {
2312        let duration = Duration::from(udur);
2313        TimeArithmetic { duration }
2314    }
2315}
2316
2317impl<'a> From<&'a Span> for TimeArithmetic {
2318    fn from(span: &'a Span) -> TimeArithmetic {
2319        TimeArithmetic::from(*span)
2320    }
2321}
2322
2323impl<'a> From<&'a SignedDuration> for TimeArithmetic {
2324    fn from(sdur: &'a SignedDuration) -> TimeArithmetic {
2325        TimeArithmetic::from(*sdur)
2326    }
2327}
2328
2329impl<'a> From<&'a UnsignedDuration> for TimeArithmetic {
2330    fn from(udur: &'a UnsignedDuration) -> TimeArithmetic {
2331        TimeArithmetic::from(*udur)
2332    }
2333}
2334
2335/// Options for [`Time::since`] and [`Time::until`].
2336///
2337/// This type provides a way to configure the calculation of spans between two
2338/// [`Time`] values. In particular, both `Time::since` and `Time::until` accept
2339/// anything that implements `Into<TimeDifference>`. There are a few key trait
2340/// implementations that make this convenient:
2341///
2342/// * `From<Time> for TimeDifference` will construct a configuration consisting
2343/// of just the time. So for example, `time1.until(time2)` will return the span
2344/// from `time1` to `time2`.
2345/// * `From<DateTime> for TimeDifference` will construct a configuration
2346/// consisting of just the time from the given datetime. So for example,
2347/// `time.since(datetime)` returns the span from `datetime.time()` to `time`.
2348/// * `From<(Unit, Time)>` is a convenient way to specify the largest units
2349/// that should be present on the span returned. By default, the largest units
2350/// are hours. Using this trait implementation is equivalent to
2351/// `TimeDifference::new(time).largest(unit)`.
2352/// * `From<(Unit, DateTime)>` is like the one above, but with the time from
2353/// the given datetime.
2354///
2355/// One can also provide a `TimeDifference` value directly. Doing so
2356/// is necessary to use the rounding features of calculating a span. For
2357/// example, setting the smallest unit (defaults to [`Unit::Nanosecond`]), the
2358/// rounding mode (defaults to [`RoundMode::Trunc`]) and the rounding increment
2359/// (defaults to `1`). The defaults are selected such that no rounding occurs.
2360///
2361/// Rounding a span as part of calculating it is provided as a convenience.
2362/// Callers may choose to round the span as a distinct step via
2363/// [`Span::round`].
2364///
2365/// # Example
2366///
2367/// This example shows how to round a span between two datetimes to the nearest
2368/// half-hour, with ties breaking away from zero.
2369///
2370/// ```
2371/// use jiff::{civil::{Time, TimeDifference}, RoundMode, ToSpan, Unit};
2372///
2373/// let t1 = "08:14:00.123456789".parse::<Time>()?;
2374/// let t2 = "15:00".parse::<Time>()?;
2375/// let span = t1.until(
2376///     TimeDifference::new(t2)
2377///         .smallest(Unit::Minute)
2378///         .mode(RoundMode::HalfExpand)
2379///         .increment(30),
2380/// )?;
2381/// assert_eq!(span, 7.hours().fieldwise());
2382///
2383/// // One less minute, and because of the HalfExpand mode, the span would
2384/// // get rounded down.
2385/// let t2 = "14:59".parse::<Time>()?;
2386/// let span = t1.until(
2387///     TimeDifference::new(t2)
2388///         .smallest(Unit::Minute)
2389///         .mode(RoundMode::HalfExpand)
2390///         .increment(30),
2391/// )?;
2392/// assert_eq!(span, 6.hours().minutes(30).fieldwise());
2393///
2394/// # Ok::<(), Box<dyn std::error::Error>>(())
2395/// ```
2396#[derive(Clone, Copy, Debug)]
2397pub struct TimeDifference {
2398    time: Time,
2399    round: SpanRound<'static>,
2400}
2401
2402impl TimeDifference {
2403    /// Create a new default configuration for computing the span between
2404    /// the given time and some other time (specified as the receiver in
2405    /// [`Time::since`] or [`Time::until`]).
2406    #[inline]
2407    pub fn new(time: Time) -> TimeDifference {
2408        // We use truncation rounding by default since it seems that's
2409        // what is generally expected when computing the difference between
2410        // datetimes.
2411        //
2412        // See: https://github.com/tc39/proposal-temporal/issues/1122
2413        let round = SpanRound::new().mode(RoundMode::Trunc);
2414        TimeDifference { time, round }
2415    }
2416
2417    /// Set the smallest units allowed in the span returned.
2418    ///
2419    /// # Errors
2420    ///
2421    /// The smallest units must be no greater than the largest units. If this
2422    /// is violated, then computing a span with this configuration will result
2423    /// in an error.
2424    ///
2425    /// # Example
2426    ///
2427    /// This shows how to round a span between two times to units no less than
2428    /// seconds.
2429    ///
2430    /// ```
2431    /// use jiff::{civil::{Time, TimeDifference}, RoundMode, ToSpan, Unit};
2432    ///
2433    /// let t1 = "08:14:02.5001".parse::<Time>()?;
2434    /// let t2 = "08:30:03.0001".parse::<Time>()?;
2435    /// let span = t1.until(
2436    ///     TimeDifference::new(t2)
2437    ///         .smallest(Unit::Second)
2438    ///         .mode(RoundMode::HalfExpand),
2439    /// )?;
2440    /// assert_eq!(span, 16.minutes().seconds(1).fieldwise());
2441    ///
2442    /// # Ok::<(), Box<dyn std::error::Error>>(())
2443    /// ```
2444    #[inline]
2445    pub fn smallest(self, unit: Unit) -> TimeDifference {
2446        TimeDifference { round: self.round.smallest(unit), ..self }
2447    }
2448
2449    /// Set the largest units allowed in the span returned.
2450    ///
2451    /// When a largest unit is not specified, computing a span between times
2452    /// behaves as if it were set to [`Unit::Hour`].
2453    ///
2454    /// # Errors
2455    ///
2456    /// The largest units, when set, must be at least as big as the smallest
2457    /// units (which defaults to [`Unit::Nanosecond`]). If this is violated,
2458    /// then computing a span with this configuration will result in an error.
2459    ///
2460    /// # Example
2461    ///
2462    /// This shows how to round a span between two times to units no
2463    /// bigger than seconds.
2464    ///
2465    /// ```
2466    /// use jiff::{civil::{Time, TimeDifference}, ToSpan, Unit};
2467    ///
2468    /// let t1 = "08:14".parse::<Time>()?;
2469    /// let t2 = "08:30".parse::<Time>()?;
2470    /// let span = t1.until(TimeDifference::new(t2).largest(Unit::Second))?;
2471    /// assert_eq!(span, 960.seconds().fieldwise());
2472    ///
2473    /// # Ok::<(), Box<dyn std::error::Error>>(())
2474    /// ```
2475    #[inline]
2476    pub fn largest(self, unit: Unit) -> TimeDifference {
2477        TimeDifference { round: self.round.largest(unit), ..self }
2478    }
2479
2480    /// Set the rounding mode.
2481    ///
2482    /// This defaults to [`RoundMode::Trunc`] since it's plausible that
2483    /// rounding "up" in the context of computing the span between two times
2484    /// could be surprising in a number of cases. The [`RoundMode::HalfExpand`]
2485    /// mode corresponds to typical rounding you might have learned about in
2486    /// school. But a variety of other rounding modes exist.
2487    ///
2488    /// # Example
2489    ///
2490    /// This shows how to always round "up" towards positive infinity.
2491    ///
2492    /// ```
2493    /// use jiff::{civil::{Time, TimeDifference}, RoundMode, ToSpan, Unit};
2494    ///
2495    /// let t1 = "08:10".parse::<Time>()?;
2496    /// let t2 = "08:11".parse::<Time>()?;
2497    /// let span = t1.until(
2498    ///     TimeDifference::new(t2)
2499    ///         .smallest(Unit::Hour)
2500    ///         .mode(RoundMode::Ceil),
2501    /// )?;
2502    /// // Only one minute elapsed, but we asked to always round up!
2503    /// assert_eq!(span, 1.hour().fieldwise());
2504    ///
2505    /// // Since `Ceil` always rounds toward positive infinity, the behavior
2506    /// // flips for a negative span.
2507    /// let span = t1.since(
2508    ///     TimeDifference::new(t2)
2509    ///         .smallest(Unit::Hour)
2510    ///         .mode(RoundMode::Ceil),
2511    /// )?;
2512    /// assert_eq!(span, 0.hour().fieldwise());
2513    ///
2514    /// # Ok::<(), Box<dyn std::error::Error>>(())
2515    /// ```
2516    #[inline]
2517    pub fn mode(self, mode: RoundMode) -> TimeDifference {
2518        TimeDifference { round: self.round.mode(mode), ..self }
2519    }
2520
2521    /// Set the rounding increment for the smallest unit.
2522    ///
2523    /// The default value is `1`. Other values permit rounding the smallest
2524    /// unit to the nearest integer increment specified. For example, if the
2525    /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
2526    /// `30` would result in rounding in increments of a half hour. That is,
2527    /// the only minute value that could result would be `0` or `30`.
2528    ///
2529    /// # Errors
2530    ///
2531    /// The rounding increment must divide evenly into the next highest unit
2532    /// after the smallest unit configured (and must not be equivalent to it).
2533    /// For example, if the smallest unit is [`Unit::Nanosecond`], then *some*
2534    /// of the valid values for the rounding increment are `1`, `2`, `4`, `5`,
2535    /// `100` and `500`. Namely, any integer that divides evenly into `1,000`
2536    /// nanoseconds since there are `1,000` nanoseconds in the next highest
2537    /// unit (microseconds).
2538    ///
2539    /// The error will occur when computing the span, and not when setting
2540    /// the increment here.
2541    ///
2542    /// # Example
2543    ///
2544    /// This shows how to round the span between two times to the nearest 5
2545    /// minute increment.
2546    ///
2547    /// ```
2548    /// use jiff::{civil::{Time, TimeDifference}, RoundMode, ToSpan, Unit};
2549    ///
2550    /// let t1 = "08:19".parse::<Time>()?;
2551    /// let t2 = "12:52".parse::<Time>()?;
2552    /// let span = t1.until(
2553    ///     TimeDifference::new(t2)
2554    ///         .smallest(Unit::Minute)
2555    ///         .increment(5)
2556    ///         .mode(RoundMode::HalfExpand),
2557    /// )?;
2558    /// assert_eq!(span, 4.hour().minutes(35).fieldwise());
2559    ///
2560    /// # Ok::<(), Box<dyn std::error::Error>>(())
2561    /// ```
2562    #[inline]
2563    pub fn increment(self, increment: i64) -> TimeDifference {
2564        TimeDifference { round: self.round.increment(increment), ..self }
2565    }
2566
2567    /// Returns true if and only if this configuration could change the span
2568    /// via rounding.
2569    #[inline]
2570    fn rounding_may_change_span(&self) -> bool {
2571        self.round.rounding_may_change_span_ignore_largest()
2572    }
2573
2574    /// Returns the span of time from `t1` to the time in this configuration.
2575    /// The biggest units allowed are determined by the `smallest` and
2576    /// `largest` settings, but defaults to `Unit::Hour`.
2577    #[inline]
2578    fn until_with_largest_unit(&self, t1: Time) -> Result<Span, Error> {
2579        let t2 = self.time;
2580        if t1 == t2 {
2581            return Ok(Span::new());
2582        }
2583        let largest = self.round.get_largest().unwrap_or(Unit::Hour);
2584        if largest > Unit::Hour {
2585            return Err(err!(
2586                "rounding the span between two times must use hours \
2587                 or smaller for its units, but found {units}",
2588                units = largest.plural(),
2589            ));
2590        }
2591        let start = t1.to_nanosecond();
2592        let end = t2.to_nanosecond();
2593        let span =
2594            Span::from_invariant_nanoseconds(largest, (end - start).rinto())
2595                .expect("difference in civil times is always in bounds");
2596        Ok(span)
2597    }
2598}
2599
2600impl From<Time> for TimeDifference {
2601    #[inline]
2602    fn from(time: Time) -> TimeDifference {
2603        TimeDifference::new(time)
2604    }
2605}
2606
2607impl From<DateTime> for TimeDifference {
2608    #[inline]
2609    fn from(dt: DateTime) -> TimeDifference {
2610        TimeDifference::from(Time::from(dt))
2611    }
2612}
2613
2614impl From<Zoned> for TimeDifference {
2615    #[inline]
2616    fn from(zdt: Zoned) -> TimeDifference {
2617        TimeDifference::from(Time::from(zdt))
2618    }
2619}
2620
2621impl<'a> From<&'a Zoned> for TimeDifference {
2622    #[inline]
2623    fn from(zdt: &'a Zoned) -> TimeDifference {
2624        TimeDifference::from(zdt.datetime())
2625    }
2626}
2627
2628impl From<(Unit, Time)> for TimeDifference {
2629    #[inline]
2630    fn from((largest, time): (Unit, Time)) -> TimeDifference {
2631        TimeDifference::from(time).largest(largest)
2632    }
2633}
2634
2635impl From<(Unit, DateTime)> for TimeDifference {
2636    #[inline]
2637    fn from((largest, dt): (Unit, DateTime)) -> TimeDifference {
2638        TimeDifference::from((largest, Time::from(dt)))
2639    }
2640}
2641
2642impl From<(Unit, Zoned)> for TimeDifference {
2643    #[inline]
2644    fn from((largest, zdt): (Unit, Zoned)) -> TimeDifference {
2645        TimeDifference::from((largest, Time::from(zdt)))
2646    }
2647}
2648
2649impl<'a> From<(Unit, &'a Zoned)> for TimeDifference {
2650    #[inline]
2651    fn from((largest, zdt): (Unit, &'a Zoned)) -> TimeDifference {
2652        TimeDifference::from((largest, zdt.datetime()))
2653    }
2654}
2655
2656/// Options for [`Time::round`].
2657///
2658/// This type provides a way to configure the rounding of a civil time.
2659/// In particular, `Time::round` accepts anything that implements the
2660/// `Into<TimeRound>` trait. There are some trait implementations that
2661/// therefore make calling `Time::round` in some common cases more ergonomic:
2662///
2663/// * `From<Unit> for TimeRound` will construct a rounding configuration that
2664/// rounds to the unit given. Specifically, `TimeRound::new().smallest(unit)`.
2665/// * `From<(Unit, i64)> for TimeRound` is like the one above, but also
2666/// specifies the rounding increment for [`TimeRound::increment`].
2667///
2668/// Note that in the default configuration, no rounding occurs.
2669///
2670/// # Example
2671///
2672/// This example shows how to round a time to the nearest second:
2673///
2674/// ```
2675/// use jiff::{civil::{Time, time}, Unit};
2676///
2677/// let t: Time = "16:24:59.5".parse()?;
2678/// assert_eq!(
2679///     t.round(Unit::Second)?,
2680///     // The second rounds up and causes minutes to increase.
2681///     time(16, 25, 0, 0),
2682/// );
2683///
2684/// # Ok::<(), Box<dyn std::error::Error>>(())
2685/// ```
2686///
2687/// The above makes use of the fact that `Unit` implements
2688/// `Into<TimeRound>`. If you want to change the rounding mode to, say,
2689/// truncation, then you'll need to construct a `TimeRound` explicitly
2690/// since there are no convenience `Into` trait implementations for
2691/// [`RoundMode`].
2692///
2693/// ```
2694/// use jiff::{civil::{Time, TimeRound, time}, RoundMode, Unit};
2695///
2696/// let t: Time = "2024-06-20 16:24:59.5".parse()?;
2697/// assert_eq!(
2698///     t.round(
2699///         TimeRound::new().smallest(Unit::Second).mode(RoundMode::Trunc),
2700///     )?,
2701///     // The second just gets truncated as if it wasn't there.
2702///     time(16, 24, 59, 0),
2703/// );
2704///
2705/// # Ok::<(), Box<dyn std::error::Error>>(())
2706/// ```
2707#[derive(Clone, Copy, Debug)]
2708pub struct TimeRound {
2709    smallest: Unit,
2710    mode: RoundMode,
2711    increment: i64,
2712}
2713
2714impl TimeRound {
2715    /// Create a new default configuration for rounding a [`Time`].
2716    #[inline]
2717    pub fn new() -> TimeRound {
2718        TimeRound {
2719            smallest: Unit::Nanosecond,
2720            mode: RoundMode::HalfExpand,
2721            increment: 1,
2722        }
2723    }
2724
2725    /// Set the smallest units allowed in the time returned after rounding.
2726    ///
2727    /// Any units below the smallest configured unit will be used, along with
2728    /// the rounding increment and rounding mode, to determine the value of the
2729    /// smallest unit. For example, when rounding `03:25:30` to the
2730    /// nearest minute, the `30` second unit will result in rounding the minute
2731    /// unit of `25` up to `26` and zeroing out everything below minutes.
2732    ///
2733    /// This defaults to [`Unit::Nanosecond`].
2734    ///
2735    /// # Errors
2736    ///
2737    /// The smallest units must be no greater than [`Unit::Hour`].
2738    ///
2739    /// # Example
2740    ///
2741    /// ```
2742    /// use jiff::{civil::{TimeRound, time}, Unit};
2743    ///
2744    /// let t = time(3, 25, 30, 0);
2745    /// assert_eq!(
2746    ///     t.round(TimeRound::new().smallest(Unit::Minute))?,
2747    ///     time(3, 26, 0, 0),
2748    /// );
2749    /// // Or, utilize the `From<Unit> for TimeRound` impl:
2750    /// assert_eq!(t.round(Unit::Minute)?, time(3, 26, 0, 0));
2751    ///
2752    /// # Ok::<(), Box<dyn std::error::Error>>(())
2753    /// ```
2754    #[inline]
2755    pub fn smallest(self, unit: Unit) -> TimeRound {
2756        TimeRound { smallest: unit, ..self }
2757    }
2758
2759    /// Set the rounding mode.
2760    ///
2761    /// This defaults to [`RoundMode::HalfExpand`], which rounds away from
2762    /// zero. It matches the kind of rounding you might have been taught in
2763    /// school.
2764    ///
2765    /// # Example
2766    ///
2767    /// This shows how to always round times up towards positive infinity.
2768    ///
2769    /// ```
2770    /// use jiff::{civil::{Time, TimeRound, time}, RoundMode, Unit};
2771    ///
2772    /// let t: Time = "03:25:01".parse()?;
2773    /// assert_eq!(
2774    ///     t.round(
2775    ///         TimeRound::new()
2776    ///             .smallest(Unit::Minute)
2777    ///             .mode(RoundMode::Ceil),
2778    ///     )?,
2779    ///     time(3, 26, 0, 0),
2780    /// );
2781    ///
2782    /// # Ok::<(), Box<dyn std::error::Error>>(())
2783    /// ```
2784    #[inline]
2785    pub fn mode(self, mode: RoundMode) -> TimeRound {
2786        TimeRound { mode, ..self }
2787    }
2788
2789    /// Set the rounding increment for the smallest unit.
2790    ///
2791    /// The default value is `1`. Other values permit rounding the smallest
2792    /// unit to the nearest integer increment specified. For example, if the
2793    /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
2794    /// `30` would result in rounding in increments of a half hour. That is,
2795    /// the only minute value that could result would be `0` or `30`.
2796    ///
2797    /// # Errors
2798    ///
2799    /// The rounding increment must divide evenly into the
2800    /// next highest unit above the smallest unit set. The rounding increment
2801    /// must also not be equal to the next highest unit. For example, if the
2802    /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
2803    /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
2804    /// Namely, any integer that divides evenly into `1,000` nanoseconds since
2805    /// there are `1,000` nanoseconds in the next highest unit (microseconds).
2806    ///
2807    /// # Example
2808    ///
2809    /// This example shows how to round a time to the nearest 10 minute
2810    /// increment.
2811    ///
2812    /// ```
2813    /// use jiff::{civil::{Time, TimeRound, time}, RoundMode, Unit};
2814    ///
2815    /// let t: Time = "03:24:59".parse()?;
2816    /// assert_eq!(t.round((Unit::Minute, 10))?, time(3, 20, 0, 0));
2817    ///
2818    /// # Ok::<(), Box<dyn std::error::Error>>(())
2819    /// ```
2820    #[inline]
2821    pub fn increment(self, increment: i64) -> TimeRound {
2822        TimeRound { increment, ..self }
2823    }
2824
2825    /// Does the actual rounding.
2826    pub(crate) fn round(&self, t: Time) -> Result<Time, Error> {
2827        let increment = increment::for_time(self.smallest, self.increment)?;
2828        let nanos = t.to_nanosecond();
2829        let rounded = self.mode.round_by_unit_in_nanoseconds(
2830            nanos,
2831            self.smallest,
2832            increment,
2833        );
2834        let limit =
2835            t::NoUnits128::rfrom(t::CivilDayNanosecond::MAX_SELF) + C(1);
2836        Ok(Time::from_nanosecond((rounded % limit).rinto()))
2837    }
2838}
2839
2840impl Default for TimeRound {
2841    #[inline]
2842    fn default() -> TimeRound {
2843        TimeRound::new()
2844    }
2845}
2846
2847impl From<Unit> for TimeRound {
2848    #[inline]
2849    fn from(unit: Unit) -> TimeRound {
2850        TimeRound::default().smallest(unit)
2851    }
2852}
2853
2854impl From<(Unit, i64)> for TimeRound {
2855    #[inline]
2856    fn from((unit, increment): (Unit, i64)) -> TimeRound {
2857        TimeRound::from(unit).increment(increment)
2858    }
2859}
2860
2861/// A builder for setting the fields on a [`Time`].
2862///
2863/// This builder is constructed via [`Time::with`].
2864///
2865/// # Example
2866///
2867/// Unlike [`Date`], a [`Time`] is valid for all possible valid values of its
2868/// fields. That is, there is no way for two valid field values to combine
2869/// into an invalid `Time`. So, for `Time`, this builder does have as much of
2870/// a benefit versus an API design with methods like `Time::with_hour` and
2871/// `Time::with_minute`. Nevertheless, this builder permits settings multiple
2872/// fields at the same time and performing only one validity check. Moreover,
2873/// this provides a consistent API with other date and time types in this
2874/// crate.
2875///
2876/// ```
2877/// use jiff::civil::time;
2878///
2879/// let t1 = time(0, 0, 24, 0);
2880/// let t2 = t1.with().hour(15).minute(30).millisecond(10).build()?;
2881/// assert_eq!(t2, time(15, 30, 24, 10_000_000));
2882///
2883/// # Ok::<(), Box<dyn std::error::Error>>(())
2884/// ```
2885#[derive(Clone, Copy, Debug)]
2886pub struct TimeWith {
2887    original: Time,
2888    hour: Option<i8>,
2889    minute: Option<i8>,
2890    second: Option<i8>,
2891    millisecond: Option<i16>,
2892    microsecond: Option<i16>,
2893    nanosecond: Option<i16>,
2894    subsec_nanosecond: Option<i32>,
2895}
2896
2897impl TimeWith {
2898    #[inline]
2899    fn new(original: Time) -> TimeWith {
2900        TimeWith {
2901            original,
2902            hour: None,
2903            minute: None,
2904            second: None,
2905            millisecond: None,
2906            microsecond: None,
2907            nanosecond: None,
2908            subsec_nanosecond: None,
2909        }
2910    }
2911
2912    /// Create a new `Time` from the fields set on this configuration.
2913    ///
2914    /// An error occurs when the fields combine to an invalid time. This only
2915    /// occurs when at least one field has an invalid value, or if at least
2916    /// one of `millisecond`, `microsecond` or `nanosecond` is set _and_
2917    /// `subsec_nanosecond` is set. Otherwise, if all fields are valid, then
2918    /// the entire `Time` is guaranteed to be valid.
2919    ///
2920    /// For any fields not set on this configuration, the values are taken from
2921    /// the [`Time`] that originally created this configuration. When no values
2922    /// are set, this routine is guaranteed to succeed and will always return
2923    /// the original time without modification.
2924    ///
2925    /// # Example
2926    ///
2927    /// This creates a time but with its fractional nanosecond component
2928    /// stripped:
2929    ///
2930    /// ```
2931    /// use jiff::civil::time;
2932    ///
2933    /// let t = time(14, 27, 30, 123_456_789);
2934    /// assert_eq!(t.with().subsec_nanosecond(0).build()?, time(14, 27, 30, 0));
2935    ///
2936    /// # Ok::<(), Box<dyn std::error::Error>>(())
2937    /// ```
2938    ///
2939    /// # Example: error for invalid time
2940    ///
2941    /// ```
2942    /// use jiff::civil::time;
2943    ///
2944    /// let t = time(14, 27, 30, 0);
2945    /// assert!(t.with().hour(24).build().is_err());
2946    /// ```
2947    ///
2948    /// # Example: error for ambiguous sub-second value
2949    ///
2950    /// ```
2951    /// use jiff::civil::time;
2952    ///
2953    /// let t = time(14, 27, 30, 123_456_789);
2954    /// // Setting both the individual sub-second fields and the entire
2955    /// // fractional component could lead to a misleading configuration. So
2956    /// // if it's done, it results in an error in all cases. Callers must
2957    /// // choose one or the other.
2958    /// assert!(t.with().microsecond(1).subsec_nanosecond(0).build().is_err());
2959    /// ```
2960    #[inline]
2961    pub fn build(self) -> Result<Time, Error> {
2962        let hour = match self.hour {
2963            None => self.original.hour_ranged(),
2964            Some(hour) => Hour::try_new("hour", hour)?,
2965        };
2966        let minute = match self.minute {
2967            None => self.original.minute_ranged(),
2968            Some(minute) => Minute::try_new("minute", minute)?,
2969        };
2970        let second = match self.second {
2971            None => self.original.second_ranged(),
2972            Some(second) => Second::try_new("second", second)?,
2973        };
2974        let millisecond = match self.millisecond {
2975            None => self.original.millisecond_ranged(),
2976            Some(millisecond) => {
2977                Millisecond::try_new("millisecond", millisecond)?
2978            }
2979        };
2980        let microsecond = match self.microsecond {
2981            None => self.original.microsecond_ranged(),
2982            Some(microsecond) => {
2983                Microsecond::try_new("microsecond", microsecond)?
2984            }
2985        };
2986        let nanosecond = match self.nanosecond {
2987            None => self.original.nanosecond_ranged(),
2988            Some(nanosecond) => Nanosecond::try_new("nanosecond", nanosecond)?,
2989        };
2990        let subsec_nanosecond = match self.subsec_nanosecond {
2991            None => self.original.subsec_nanosecond_ranged(),
2992            Some(subsec_nanosecond) => {
2993                if self.millisecond.is_some() {
2994                    return Err(err!(
2995                        "cannot set both TimeWith::millisecond \
2996                         and TimeWith::subsec_nanosecond",
2997                    ));
2998                }
2999                if self.microsecond.is_some() {
3000                    return Err(err!(
3001                        "cannot set both TimeWith::microsecond \
3002                         and TimeWith::subsec_nanosecond",
3003                    ));
3004                }
3005                if self.nanosecond.is_some() {
3006                    return Err(err!(
3007                        "cannot set both TimeWith::nanosecond \
3008                         and TimeWith::subsec_nanosecond",
3009                    ));
3010                }
3011                SubsecNanosecond::try_new(
3012                    "subsec_nanosecond",
3013                    subsec_nanosecond,
3014                )?
3015            }
3016        };
3017        if self.subsec_nanosecond.is_some() {
3018            Ok(Time::new_ranged(hour, minute, second, subsec_nanosecond))
3019        } else {
3020            Ok(Time::new_ranged(hour, minute, second, C(0))
3021                .with_subsec_parts_ranged(
3022                    millisecond,
3023                    microsecond,
3024                    nanosecond,
3025                ))
3026        }
3027    }
3028
3029    /// Set the hour field on a [`Time`].
3030    ///
3031    /// One can access this value via [`Time::hour`].
3032    ///
3033    /// This overrides any previous hour settings.
3034    ///
3035    /// # Errors
3036    ///
3037    /// This returns an error when [`TimeWith::build`] is called if the given
3038    /// hour is outside the range `0..=23`.
3039    ///
3040    /// # Example
3041    ///
3042    /// ```
3043    /// use jiff::civil::time;
3044    ///
3045    /// let t1 = time(15, 21, 59, 0);
3046    /// assert_eq!(t1.hour(), 15);
3047    /// let t2 = t1.with().hour(3).build()?;
3048    /// assert_eq!(t2.hour(), 3);
3049    ///
3050    /// # Ok::<(), Box<dyn std::error::Error>>(())
3051    /// ```
3052    #[inline]
3053    pub fn hour(self, hour: i8) -> TimeWith {
3054        TimeWith { hour: Some(hour), ..self }
3055    }
3056
3057    /// Set the minute field on a [`Time`].
3058    ///
3059    /// One can access this value via [`Time::minute`].
3060    ///
3061    /// This overrides any previous minute settings.
3062    ///
3063    /// # Errors
3064    ///
3065    /// This returns an error when [`TimeWith::build`] is called if the given
3066    /// minute is outside the range `0..=59`.
3067    ///
3068    /// # Example
3069    ///
3070    /// ```
3071    /// use jiff::civil::time;
3072    ///
3073    /// let t1 = time(15, 21, 59, 0);
3074    /// assert_eq!(t1.minute(), 21);
3075    /// let t2 = t1.with().minute(3).build()?;
3076    /// assert_eq!(t2.minute(), 3);
3077    ///
3078    /// # Ok::<(), Box<dyn std::error::Error>>(())
3079    /// ```
3080    #[inline]
3081    pub fn minute(self, minute: i8) -> TimeWith {
3082        TimeWith { minute: Some(minute), ..self }
3083    }
3084
3085    /// Set the second field on a [`Time`].
3086    ///
3087    /// One can access this value via [`Time::second`].
3088    ///
3089    /// This overrides any previous second settings.
3090    ///
3091    /// # Errors
3092    ///
3093    /// This returns an error when [`TimeWith::build`] is called if the given
3094    /// second is outside the range `0..=59`.
3095    ///
3096    /// # Example
3097    ///
3098    /// ```
3099    /// use jiff::civil::time;
3100    ///
3101    /// let t1 = time(15, 21, 59, 0);
3102    /// assert_eq!(t1.second(), 59);
3103    /// let t2 = t1.with().second(3).build()?;
3104    /// assert_eq!(t2.second(), 3);
3105    ///
3106    /// # Ok::<(), Box<dyn std::error::Error>>(())
3107    /// ```
3108    #[inline]
3109    pub fn second(self, second: i8) -> TimeWith {
3110        TimeWith { second: Some(second), ..self }
3111    }
3112
3113    /// Set the millisecond field on a [`Time`].
3114    ///
3115    /// One can access this value via [`Time::millisecond`].
3116    ///
3117    /// This overrides any previous millisecond settings.
3118    ///
3119    /// Note that this only sets the millisecond component. It does
3120    /// not change the microsecond or nanosecond components. To set
3121    /// the fractional second component to nanosecond precision, use
3122    /// [`TimeWith::subsec_nanosecond`].
3123    ///
3124    /// # Errors
3125    ///
3126    /// This returns an error when [`TimeWith::build`] is called if the given
3127    /// millisecond is outside the range `0..=999`, or if both this and
3128    /// [`TimeWith::subsec_nanosecond`] are set.
3129    ///
3130    /// # Example
3131    ///
3132    /// This shows the relationship between [`Time::millisecond`] and
3133    /// [`Time::subsec_nanosecond`]:
3134    ///
3135    /// ```
3136    /// use jiff::civil::time;
3137    ///
3138    /// let t = time(15, 21, 35, 0).with().millisecond(123).build()?;
3139    /// assert_eq!(t.subsec_nanosecond(), 123_000_000);
3140    ///
3141    /// # Ok::<(), Box<dyn std::error::Error>>(())
3142    /// ```
3143    #[inline]
3144    pub fn millisecond(self, millisecond: i16) -> TimeWith {
3145        TimeWith { millisecond: Some(millisecond), ..self }
3146    }
3147
3148    /// Set the microsecond field on a [`Time`].
3149    ///
3150    /// One can access this value via [`Time::microsecond`].
3151    ///
3152    /// This overrides any previous microsecond settings.
3153    ///
3154    /// Note that this only sets the microsecond component. It does
3155    /// not change the millisecond or nanosecond components. To set
3156    /// the fractional second component to nanosecond precision, use
3157    /// [`TimeWith::subsec_nanosecond`].
3158    ///
3159    /// # Errors
3160    ///
3161    /// This returns an error when [`TimeWith::build`] is called if the given
3162    /// microsecond is outside the range `0..=999`, or if both this and
3163    /// [`TimeWith::subsec_nanosecond`] are set.
3164    ///
3165    /// # Example
3166    ///
3167    /// This shows the relationship between [`Time::microsecond`] and
3168    /// [`Time::subsec_nanosecond`]:
3169    ///
3170    /// ```
3171    /// use jiff::civil::time;
3172    ///
3173    /// let t = time(15, 21, 35, 0).with().microsecond(123).build()?;
3174    /// assert_eq!(t.subsec_nanosecond(), 123_000);
3175    ///
3176    /// # Ok::<(), Box<dyn std::error::Error>>(())
3177    /// ```
3178    #[inline]
3179    pub fn microsecond(self, microsecond: i16) -> TimeWith {
3180        TimeWith { microsecond: Some(microsecond), ..self }
3181    }
3182
3183    /// Set the nanosecond field on a [`Time`].
3184    ///
3185    /// One can access this value via [`Time::nanosecond`].
3186    ///
3187    /// This overrides any previous nanosecond settings.
3188    ///
3189    /// Note that this only sets the nanosecond component. It does
3190    /// not change the millisecond or microsecond components. To set
3191    /// the fractional second component to nanosecond precision, use
3192    /// [`TimeWith::subsec_nanosecond`].
3193    ///
3194    /// # Errors
3195    ///
3196    /// This returns an error when [`TimeWith::build`] is called if the given
3197    /// nanosecond is outside the range `0..=999`, or if both this and
3198    /// [`TimeWith::subsec_nanosecond`] are set.
3199    ///
3200    /// # Example
3201    ///
3202    /// This shows the relationship between [`Time::nanosecond`] and
3203    /// [`Time::subsec_nanosecond`]:
3204    ///
3205    /// ```
3206    /// use jiff::civil::time;
3207    ///
3208    /// let t = time(15, 21, 35, 0).with().nanosecond(123).build()?;
3209    /// assert_eq!(t.subsec_nanosecond(), 123);
3210    ///
3211    /// # Ok::<(), Box<dyn std::error::Error>>(())
3212    /// ```
3213    #[inline]
3214    pub fn nanosecond(self, nanosecond: i16) -> TimeWith {
3215        TimeWith { nanosecond: Some(nanosecond), ..self }
3216    }
3217
3218    /// Set the subsecond nanosecond field on a [`Time`].
3219    ///
3220    /// If you want to access this value on `Time`, then use
3221    /// [`Time::subsec_nanosecond`].
3222    ///
3223    /// This overrides any previous subsecond nanosecond settings.
3224    ///
3225    /// Note that this sets the entire fractional second component to
3226    /// nanosecond precision, and overrides any individual millisecond,
3227    /// microsecond or nanosecond settings. To set individual components,
3228    /// use [`TimeWith::millisecond`], [`TimeWith::microsecond`] or
3229    /// [`TimeWith::nanosecond`].
3230    ///
3231    /// # Errors
3232    ///
3233    /// This returns an error when [`TimeWith::build`] is called if the given
3234    /// subsecond nanosecond is outside the range `0..=999,999,999`, or if both
3235    /// this and one of [`TimeWith::millisecond`], [`TimeWith::microsecond`] or
3236    /// [`TimeWith::nanosecond`] are set.
3237    ///
3238    /// # Example
3239    ///
3240    /// This shows the relationship between constructing a `Time` value with
3241    /// subsecond nanoseconds and its individual subsecond fields:
3242    ///
3243    /// ```
3244    /// use jiff::civil::time;
3245    ///
3246    /// let t1 = time(15, 21, 35, 0);
3247    /// let t2 = t1.with().subsec_nanosecond(123_456_789).build()?;
3248    /// assert_eq!(t2.millisecond(), 123);
3249    /// assert_eq!(t2.microsecond(), 456);
3250    /// assert_eq!(t2.nanosecond(), 789);
3251    ///
3252    /// # Ok::<(), Box<dyn std::error::Error>>(())
3253    /// ```
3254    #[inline]
3255    pub fn subsec_nanosecond(self, subsec_nanosecond: i32) -> TimeWith {
3256        TimeWith { subsec_nanosecond: Some(subsec_nanosecond), ..self }
3257    }
3258}
3259
3260#[cfg(test)]
3261mod tests {
3262    use std::io::Cursor;
3263
3264    use crate::{civil::time, span::span_eq, ToSpan};
3265
3266    use super::*;
3267
3268    #[test]
3269    fn min() {
3270        let t = Time::MIN;
3271        assert_eq!(t.hour(), 0);
3272        assert_eq!(t.minute(), 0);
3273        assert_eq!(t.second(), 0);
3274        assert_eq!(t.subsec_nanosecond(), 0);
3275    }
3276
3277    #[test]
3278    fn max() {
3279        let t = Time::MAX;
3280        assert_eq!(t.hour(), 23);
3281        assert_eq!(t.minute(), 59);
3282        assert_eq!(t.second(), 59);
3283        assert_eq!(t.subsec_nanosecond(), 999_999_999);
3284    }
3285
3286    #[test]
3287    fn invalid() {
3288        assert!(Time::new(24, 0, 0, 0).is_err());
3289        assert!(Time::new(23, 60, 0, 0).is_err());
3290        assert!(Time::new(23, 59, 60, 0).is_err());
3291        assert!(Time::new(23, 59, 61, 0).is_err());
3292        assert!(Time::new(-1, 0, 0, 0).is_err());
3293        assert!(Time::new(0, -1, 0, 0).is_err());
3294        assert!(Time::new(0, 0, -1, 0).is_err());
3295
3296        assert!(Time::new(0, 0, 0, 1_000_000_000).is_err());
3297        assert!(Time::new(0, 0, 0, -1).is_err());
3298        assert!(Time::new(23, 59, 59, 1_000_000_000).is_err());
3299        assert!(Time::new(23, 59, 59, -1).is_err());
3300    }
3301
3302    #[test]
3303    fn rounding_cross_midnight() {
3304        let t1 = time(23, 59, 59, 999_999_999);
3305
3306        let t2 = t1.round(Unit::Nanosecond).unwrap();
3307        assert_eq!(t2, t1);
3308
3309        let t2 = t1.round(Unit::Millisecond).unwrap();
3310        assert_eq!(t2, time(0, 0, 0, 0));
3311
3312        let t2 = t1.round(Unit::Microsecond).unwrap();
3313        assert_eq!(t2, time(0, 0, 0, 0));
3314
3315        let t2 = t1.round(Unit::Millisecond).unwrap();
3316        assert_eq!(t2, time(0, 0, 0, 0));
3317
3318        let t2 = t1.round(Unit::Second).unwrap();
3319        assert_eq!(t2, time(0, 0, 0, 0));
3320
3321        let t2 = t1.round(Unit::Minute).unwrap();
3322        assert_eq!(t2, time(0, 0, 0, 0));
3323
3324        let t2 = t1.round(Unit::Hour).unwrap();
3325        assert_eq!(t2, time(0, 0, 0, 0));
3326
3327        let t1 = time(22, 15, 0, 0);
3328        assert_eq!(
3329            time(22, 30, 0, 0),
3330            t1.round(TimeRound::new().smallest(Unit::Minute).increment(30))
3331                .unwrap()
3332        );
3333    }
3334
3335    #[cfg(not(miri))]
3336    quickcheck::quickcheck! {
3337        fn prop_ordering_same_as_civil_nanosecond(
3338            civil_nanosecond1: CivilDayNanosecond,
3339            civil_nanosecond2: CivilDayNanosecond
3340        ) -> bool {
3341            let t1 = Time::from_nanosecond(civil_nanosecond1);
3342            let t2 = Time::from_nanosecond(civil_nanosecond2);
3343            t1.cmp(&t2) == civil_nanosecond1.cmp(&civil_nanosecond2)
3344        }
3345
3346        fn prop_checked_add_then_sub(
3347            time: Time,
3348            nano_span: CivilDayNanosecond
3349        ) -> quickcheck::TestResult {
3350            let span = Span::new().nanoseconds(nano_span.get());
3351            let Ok(sum) = time.checked_add(span) else {
3352                return quickcheck::TestResult::discard()
3353            };
3354            let diff = sum.checked_sub(span).unwrap();
3355            quickcheck::TestResult::from_bool(time == diff)
3356        }
3357
3358        fn prop_wrapping_add_then_sub(
3359            time: Time,
3360            nano_span: CivilDayNanosecond
3361        ) -> bool {
3362            let span = Span::new().nanoseconds(nano_span.get());
3363            let sum = time.wrapping_add(span);
3364            let diff = sum.wrapping_sub(span);
3365            time == diff
3366        }
3367
3368        fn prop_checked_add_equals_wrapping_add(
3369            time: Time,
3370            nano_span: CivilDayNanosecond
3371        ) -> quickcheck::TestResult {
3372            let span = Span::new().nanoseconds(nano_span.get());
3373            let Ok(sum_checked) = time.checked_add(span) else {
3374                return quickcheck::TestResult::discard()
3375            };
3376            let sum_wrapped = time.wrapping_add(span);
3377            quickcheck::TestResult::from_bool(sum_checked == sum_wrapped)
3378        }
3379
3380        fn prop_checked_sub_equals_wrapping_sub(
3381            time: Time,
3382            nano_span: CivilDayNanosecond
3383        ) -> quickcheck::TestResult {
3384            let span = Span::new().nanoseconds(nano_span.get());
3385            let Ok(diff_checked) = time.checked_sub(span) else {
3386                return quickcheck::TestResult::discard()
3387            };
3388            let diff_wrapped = time.wrapping_sub(span);
3389            quickcheck::TestResult::from_bool(diff_checked == diff_wrapped)
3390        }
3391
3392        fn prop_until_then_add(t1: Time, t2: Time) -> bool {
3393            let span = t1.until(t2).unwrap();
3394            t1.checked_add(span).unwrap() == t2
3395        }
3396
3397        fn prop_until_then_sub(t1: Time, t2: Time) -> bool {
3398            let span = t1.until(t2).unwrap();
3399            t2.checked_sub(span).unwrap() == t1
3400        }
3401
3402        fn prop_since_then_add(t1: Time, t2: Time) -> bool {
3403            let span = t1.since(t2).unwrap();
3404            t2.checked_add(span).unwrap() == t1
3405        }
3406
3407        fn prop_since_then_sub(t1: Time, t2: Time) -> bool {
3408            let span = t1.since(t2).unwrap();
3409            t1.checked_sub(span).unwrap() == t2
3410        }
3411
3412        fn prop_until_is_since_negated(t1: Time, t2: Time) -> bool {
3413            t1.until(t2).unwrap().get_nanoseconds()
3414                == t1.since(t2).unwrap().negate().get_nanoseconds()
3415        }
3416    }
3417
3418    #[test]
3419    fn overflowing_add() {
3420        let t1 = time(23, 30, 0, 0);
3421        let (t2, span) = t1.overflowing_add(5.hours()).unwrap();
3422        assert_eq!(t2, time(4, 30, 0, 0));
3423        span_eq!(span, 1.days());
3424    }
3425
3426    #[test]
3427    fn overflowing_add_overflows() {
3428        let t1 = time(23, 30, 0, 0);
3429        let span = Span::new()
3430            .hours(t::SpanHours::MAX_REPR)
3431            .minutes(t::SpanMinutes::MAX_REPR)
3432            .seconds(t::SpanSeconds::MAX_REPR)
3433            .milliseconds(t::SpanMilliseconds::MAX_REPR)
3434            .microseconds(t::SpanMicroseconds::MAX_REPR)
3435            .nanoseconds(t::SpanNanoseconds::MAX_REPR);
3436        assert!(t1.overflowing_add(span).is_err());
3437    }
3438
3439    #[test]
3440    fn time_size() {
3441        #[cfg(debug_assertions)]
3442        {
3443            assert_eq!(24, core::mem::size_of::<Time>());
3444        }
3445        #[cfg(not(debug_assertions))]
3446        {
3447            assert_eq!(8, core::mem::size_of::<Time>());
3448        }
3449    }
3450
3451    // This test checks that a wrapping subtraction with the minimum signed
3452    // duration is as expected.
3453    #[test]
3454    fn wrapping_sub_signed_duration_min() {
3455        let max = -SignedDuration::MIN.as_nanos();
3456        let got = time(15, 30, 8, 999_999_999).to_nanosecond();
3457        let expected = max.rem_euclid(t::NANOS_PER_CIVIL_DAY.bound());
3458        assert_eq!(i128::from(got.get()), expected);
3459    }
3460
3461    // This test checks that a wrapping subtraction with the maximum signed
3462    // duration is as expected.
3463    #[test]
3464    fn wrapping_sub_signed_duration_max() {
3465        let max = -SignedDuration::MAX.as_nanos();
3466        let got = time(8, 29, 52, 1).to_nanosecond();
3467        let expected = max.rem_euclid(t::NANOS_PER_CIVIL_DAY.bound());
3468        assert_eq!(i128::from(got.get()), expected);
3469    }
3470
3471    // This test checks that a wrapping subtraction with the maximum unsigned
3472    // duration is as expected.
3473    #[test]
3474    fn wrapping_sub_unsigned_duration_max() {
3475        let max =
3476            -i128::try_from(std::time::Duration::MAX.as_nanos()).unwrap();
3477        let got = time(16, 59, 44, 1).to_nanosecond();
3478        let expected = max.rem_euclid(t::NANOS_PER_CIVIL_DAY.bound());
3479        assert_eq!(i128::from(got.get()), expected);
3480    }
3481
3482    /// # `serde` deserializer compatibility test
3483    ///
3484    /// Serde YAML used to be unable to deserialize `jiff` types,
3485    /// as deserializing from bytes is not supported by the deserializer.
3486    ///
3487    /// - <https://github.com/BurntSushi/jiff/issues/138>
3488    /// - <https://github.com/BurntSushi/jiff/discussions/148>
3489    #[test]
3490    fn civil_time_deserialize_yaml() {
3491        let expected = time(16, 35, 4, 987654321);
3492
3493        let deserialized: Time =
3494            serde_yaml::from_str("16:35:04.987654321").unwrap();
3495
3496        assert_eq!(deserialized, expected);
3497
3498        let deserialized: Time =
3499            serde_yaml::from_slice("16:35:04.987654321".as_bytes()).unwrap();
3500
3501        assert_eq!(deserialized, expected);
3502
3503        let cursor = Cursor::new(b"16:35:04.987654321");
3504        let deserialized: Time = serde_yaml::from_reader(cursor).unwrap();
3505
3506        assert_eq!(deserialized, expected);
3507    }
3508}