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