Skip to main content

jiff/civil/
time.rs

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