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