Skip to main content

jiff/civil/
time.rs

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