Skip to main content

jiff/civil/
time.rs

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