Skip to main content

chrono/
time_delta.rs

1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! Temporal quantification
12
13#[cfg(all(not(feature = "std"), feature = "core-error"))]
14use core::error::Error;
15use core::fmt;
16use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
17use core::time::Duration;
18#[cfg(feature = "std")]
19use std::error::Error;
20
21use crate::{expect, try_opt};
22
23#[cfg(any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"))]
24use rkyv::{Archive, Deserialize, Serialize};
25
26/// The number of nanoseconds in a microsecond.
27const NANOS_PER_MICRO: i32 = 1000;
28/// The number of nanoseconds in a millisecond.
29const NANOS_PER_MILLI: i32 = 1_000_000;
30/// The number of nanoseconds in seconds.
31pub(crate) const NANOS_PER_SEC: i32 = 1_000_000_000;
32/// The number of microseconds per second.
33const MICROS_PER_SEC: i64 = 1_000_000;
34/// The number of milliseconds per second.
35const MILLIS_PER_SEC: i64 = 1000;
36/// The number of seconds in a minute.
37const SECS_PER_MINUTE: i64 = 60;
38/// The number of seconds in an hour.
39const SECS_PER_HOUR: i64 = 3600;
40/// The number of (non-leap) seconds in days.
41const SECS_PER_DAY: i64 = 86_400;
42/// The number of (non-leap) seconds in a week.
43const SECS_PER_WEEK: i64 = 604_800;
44
45/// Time duration with nanosecond precision.
46///
47/// This also allows for negative durations; see individual methods for details.
48///
49/// A `TimeDelta` is represented internally as a complement of seconds and
50/// nanoseconds. The range is restricted to that of `i64` milliseconds, with the
51/// minimum value notably being set to `-i64::MAX` rather than allowing the full
52/// range of `i64::MIN`. This is to allow easy flipping of sign, so that for
53/// instance `abs()` can be called without any checks.
54#[derive(#[automatically_derived]
impl ::core::clone::Clone for TimeDelta {
    #[inline]
    fn clone(&self) -> TimeDelta {
        let _: ::core::clone::AssertParamIsClone<i64>;
        let _: ::core::clone::AssertParamIsClone<i32>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TimeDelta { }Copy, #[automatically_derived]
impl ::core::default::Default for TimeDelta {
    #[inline]
    fn default() -> TimeDelta {
        TimeDelta {
            secs: ::core::default::Default::default(),
            nanos: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::cmp::PartialEq for TimeDelta {
    #[inline]
    fn eq(&self, other: &TimeDelta) -> bool {
        self.secs == other.secs && self.nanos == other.nanos
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TimeDelta {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<i64>;
        let _: ::core::cmp::AssertParamIsEq<i32>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for TimeDelta {
    #[inline]
    fn partial_cmp(&self, other: &TimeDelta)
        -> ::core::option::Option<::core::cmp::Ordering> {
        match ::core::cmp::PartialOrd::partial_cmp(&self.secs, &other.secs) {
            ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
                ::core::cmp::PartialOrd::partial_cmp(&self.nanos,
                    &other.nanos),
            cmp => cmp,
        }
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for TimeDelta {
    #[inline]
    fn cmp(&self, other: &TimeDelta) -> ::core::cmp::Ordering {
        match ::core::cmp::Ord::cmp(&self.secs, &other.secs) {
            ::core::cmp::Ordering::Equal =>
                ::core::cmp::Ord::cmp(&self.nanos, &other.nanos),
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]
impl ::core::fmt::Debug for TimeDelta {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "TimeDelta",
            "secs", &self.secs, "nanos", &&self.nanos)
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for TimeDelta {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.secs, state);
        ::core::hash::Hash::hash(&self.nanos, state)
    }
}Hash)]
55#[cfg_attr(
56    any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"),
57    derive(Archive, Deserialize, Serialize),
58    archive(compare(PartialEq, PartialOrd)),
59    archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
60)]
61#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63pub struct TimeDelta {
64    secs: i64,
65    nanos: i32, // Always 0 <= nanos < NANOS_PER_SEC
66}
67
68/// The minimum possible `TimeDelta`: `-i64::MAX` milliseconds.
69pub(crate) const MIN: TimeDelta = TimeDelta {
70    secs: -i64::MAX / MILLIS_PER_SEC - 1,
71    nanos: NANOS_PER_SEC + (-i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI,
72};
73
74/// The maximum possible `TimeDelta`: `i64::MAX` milliseconds.
75pub(crate) const MAX: TimeDelta = TimeDelta {
76    secs: i64::MAX / MILLIS_PER_SEC,
77    nanos: (i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI,
78};
79
80impl TimeDelta {
81    /// Makes a new `TimeDelta` with given number of seconds and nanoseconds.
82    ///
83    /// # Errors
84    ///
85    /// Returns `None` when the duration is out of bounds, or if `nanos` ≥ 1,000,000,000.
86    pub const fn new(secs: i64, nanos: u32) -> Option<TimeDelta> {
87        if secs < MIN.secs
88            || secs > MAX.secs
89            || nanos >= 1_000_000_000
90            || (secs == MAX.secs && nanos > MAX.nanos as u32)
91            || (secs == MIN.secs && nanos < MIN.nanos as u32)
92        {
93            return None;
94        }
95        Some(TimeDelta { secs, nanos: nanos as i32 })
96    }
97
98    /// Makes a new `TimeDelta` with the given number of weeks.
99    ///
100    /// Equivalent to `TimeDelta::seconds(weeks * 7 * 24 * 60 * 60)` with
101    /// overflow checks.
102    ///
103    /// # Panics
104    ///
105    /// Panics when the duration is out of bounds.
106    #[inline]
107    #[must_use]
108    #[track_caller]
109    pub const fn weeks(weeks: i64) -> TimeDelta {
110        expect(TimeDelta::try_weeks(weeks), "TimeDelta::weeks out of bounds")
111    }
112
113    /// Makes a new `TimeDelta` with the given number of weeks.
114    ///
115    /// Equivalent to `TimeDelta::try_seconds(weeks * 7 * 24 * 60 * 60)` with
116    /// overflow checks.
117    ///
118    /// # Errors
119    ///
120    /// Returns `None` when the `TimeDelta` would be out of bounds.
121    #[inline]
122    pub const fn try_weeks(weeks: i64) -> Option<TimeDelta> {
123        TimeDelta::try_seconds(match weeks.checked_mul(SECS_PER_WEEK) { Some(v) => v, None => return None, }try_opt!(weeks.checked_mul(SECS_PER_WEEK)))
124    }
125
126    /// Makes a new `TimeDelta` with the given number of days.
127    ///
128    /// Equivalent to `TimeDelta::seconds(days * 24 * 60 * 60)` with overflow
129    /// checks.
130    ///
131    /// # Panics
132    ///
133    /// Panics when the `TimeDelta` would be out of bounds.
134    #[inline]
135    #[must_use]
136    #[track_caller]
137    pub const fn days(days: i64) -> TimeDelta {
138        expect(TimeDelta::try_days(days), "TimeDelta::days out of bounds")
139    }
140
141    /// Makes a new `TimeDelta` with the given number of days.
142    ///
143    /// Equivalent to `TimeDelta::try_seconds(days * 24 * 60 * 60)` with overflow
144    /// checks.
145    ///
146    /// # Errors
147    ///
148    /// Returns `None` when the `TimeDelta` would be out of bounds.
149    #[inline]
150    pub const fn try_days(days: i64) -> Option<TimeDelta> {
151        TimeDelta::try_seconds(match days.checked_mul(SECS_PER_DAY) { Some(v) => v, None => return None, }try_opt!(days.checked_mul(SECS_PER_DAY)))
152    }
153
154    /// Makes a new `TimeDelta` with the given number of hours.
155    ///
156    /// Equivalent to `TimeDelta::seconds(hours * 60 * 60)` with overflow checks.
157    ///
158    /// # Panics
159    ///
160    /// Panics when the `TimeDelta` would be out of bounds.
161    #[inline]
162    #[must_use]
163    #[track_caller]
164    pub const fn hours(hours: i64) -> TimeDelta {
165        expect(TimeDelta::try_hours(hours), "TimeDelta::hours out of bounds")
166    }
167
168    /// Makes a new `TimeDelta` with the given number of hours.
169    ///
170    /// Equivalent to `TimeDelta::try_seconds(hours * 60 * 60)` with overflow checks.
171    ///
172    /// # Errors
173    ///
174    /// Returns `None` when the `TimeDelta` would be out of bounds.
175    #[inline]
176    pub const fn try_hours(hours: i64) -> Option<TimeDelta> {
177        TimeDelta::try_seconds(match hours.checked_mul(SECS_PER_HOUR) { Some(v) => v, None => return None, }try_opt!(hours.checked_mul(SECS_PER_HOUR)))
178    }
179
180    /// Makes a new `TimeDelta` with the given number of minutes.
181    ///
182    /// Equivalent to `TimeDelta::seconds(minutes * 60)` with overflow checks.
183    ///
184    /// # Panics
185    ///
186    /// Panics when the `TimeDelta` would be out of bounds.
187    #[inline]
188    #[must_use]
189    #[track_caller]
190    pub const fn minutes(minutes: i64) -> TimeDelta {
191        expect(TimeDelta::try_minutes(minutes), "TimeDelta::minutes out of bounds")
192    }
193
194    /// Makes a new `TimeDelta` with the given number of minutes.
195    ///
196    /// Equivalent to `TimeDelta::try_seconds(minutes * 60)` with overflow checks.
197    ///
198    /// # Errors
199    ///
200    /// Returns `None` when the `TimeDelta` would be out of bounds.
201    #[inline]
202    pub const fn try_minutes(minutes: i64) -> Option<TimeDelta> {
203        TimeDelta::try_seconds(match minutes.checked_mul(SECS_PER_MINUTE) {
    Some(v) => v,
    None => return None,
}try_opt!(minutes.checked_mul(SECS_PER_MINUTE)))
204    }
205
206    /// Makes a new `TimeDelta` with the given number of seconds.
207    ///
208    /// # Panics
209    ///
210    /// Panics when `seconds` is more than `i64::MAX / 1_000` or less than `-i64::MAX / 1_000`
211    /// (in this context, this is the same as `i64::MIN / 1_000` due to rounding).
212    #[inline]
213    #[must_use]
214    #[track_caller]
215    pub const fn seconds(seconds: i64) -> TimeDelta {
216        expect(TimeDelta::try_seconds(seconds), "TimeDelta::seconds out of bounds")
217    }
218
219    /// Makes a new `TimeDelta` with the given number of seconds.
220    ///
221    /// # Errors
222    ///
223    /// Returns `None` when `seconds` is more than `i64::MAX / 1_000` or less than
224    /// `-i64::MAX / 1_000` (in this context, this is the same as `i64::MIN / 1_000` due to
225    /// rounding).
226    #[inline]
227    pub const fn try_seconds(seconds: i64) -> Option<TimeDelta> {
228        TimeDelta::new(seconds, 0)
229    }
230
231    /// Makes a new `TimeDelta` with the given number of milliseconds.
232    ///
233    /// # Panics
234    ///
235    /// Panics when the `TimeDelta` would be out of bounds, i.e. when `milliseconds` is more than
236    /// `i64::MAX` or less than `-i64::MAX`. Notably, this is not the same as `i64::MIN`.
237    #[inline]
238    #[track_caller]
239    pub const fn milliseconds(milliseconds: i64) -> TimeDelta {
240        expect(TimeDelta::try_milliseconds(milliseconds), "TimeDelta::milliseconds out of bounds")
241    }
242
243    /// Makes a new `TimeDelta` with the given number of milliseconds.
244    ///
245    /// # Errors
246    ///
247    /// Returns `None` the `TimeDelta` would be out of bounds, i.e. when `milliseconds` is more
248    /// than `i64::MAX` or less than `-i64::MAX`. Notably, this is not the same as `i64::MIN`.
249    #[inline]
250    pub const fn try_milliseconds(milliseconds: i64) -> Option<TimeDelta> {
251        // We don't need to compare against MAX, as this function accepts an
252        // i64, and MAX is aligned to i64::MAX milliseconds.
253        if milliseconds < -i64::MAX {
254            return None;
255        }
256        let (secs, millis) = div_mod_floor_64(milliseconds, MILLIS_PER_SEC);
257        let d = TimeDelta { secs, nanos: millis as i32 * NANOS_PER_MILLI };
258        Some(d)
259    }
260
261    /// Makes a new `TimeDelta` with the given number of microseconds.
262    ///
263    /// The number of microseconds acceptable by this constructor is less than
264    /// the total number that can actually be stored in a `TimeDelta`, so it is
265    /// not possible to specify a value that would be out of bounds. This
266    /// function is therefore infallible.
267    #[inline]
268    pub const fn microseconds(microseconds: i64) -> TimeDelta {
269        let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
270        let nanos = micros as i32 * NANOS_PER_MICRO;
271        TimeDelta { secs, nanos }
272    }
273
274    /// Makes a new `TimeDelta` with the given number of nanoseconds.
275    ///
276    /// The number of nanoseconds acceptable by this constructor is less than
277    /// the total number that can actually be stored in a `TimeDelta`, so it is
278    /// not possible to specify a value that would be out of bounds. This
279    /// function is therefore infallible.
280    #[inline]
281    pub const fn nanoseconds(nanos: i64) -> TimeDelta {
282        let (secs, nanos) = div_mod_floor_64(nanos, NANOS_PER_SEC as i64);
283        TimeDelta { secs, nanos: nanos as i32 }
284    }
285
286    /// Returns the total number of whole weeks in the `TimeDelta`.
287    #[inline]
288    pub const fn num_weeks(&self) -> i64 {
289        self.num_days() / 7
290    }
291
292    /// Returns the total number of whole days in the `TimeDelta`.
293    #[inline]
294    pub const fn num_days(&self) -> i64 {
295        self.num_seconds() / SECS_PER_DAY
296    }
297
298    /// Returns the total number of whole hours in the `TimeDelta`.
299    #[inline]
300    pub const fn num_hours(&self) -> i64 {
301        self.num_seconds() / SECS_PER_HOUR
302    }
303
304    /// Returns the total number of whole minutes in the `TimeDelta`.
305    #[inline]
306    pub const fn num_minutes(&self) -> i64 {
307        self.num_seconds() / SECS_PER_MINUTE
308    }
309
310    /// Returns the total number of whole seconds in the `TimeDelta`.
311    pub const fn num_seconds(&self) -> i64 {
312        // If secs is negative, nanos should be subtracted from the duration.
313        if self.secs < 0 && self.nanos > 0 { self.secs + 1 } else { self.secs }
314    }
315
316    /// Returns the fractional number of seconds in the `TimeDelta`.
317    pub fn as_seconds_f64(self) -> f64 {
318        self.secs as f64 + self.nanos as f64 / NANOS_PER_SEC as f64
319    }
320
321    /// Returns the fractional number of seconds in the `TimeDelta`.
322    pub fn as_seconds_f32(self) -> f32 {
323        self.secs as f32 + self.nanos as f32 / NANOS_PER_SEC as f32
324    }
325
326    /// Returns the total number of whole milliseconds in the `TimeDelta`.
327    pub const fn num_milliseconds(&self) -> i64 {
328        // A proper TimeDelta will not overflow, because MIN and MAX are defined such
329        // that the range is within the bounds of an i64, from -i64::MAX through to
330        // +i64::MAX inclusive. Notably, i64::MIN is excluded from this range.
331        let secs_part = self.num_seconds() * MILLIS_PER_SEC;
332        let nanos_part = self.subsec_nanos() / NANOS_PER_MILLI;
333        secs_part + nanos_part as i64
334    }
335
336    /// Returns the number of milliseconds in the fractional part of the duration.
337    ///
338    /// This is the number of milliseconds such that
339    /// `subsec_millis() + num_seconds() * 1_000` is the truncated number of
340    /// milliseconds in the duration.
341    pub const fn subsec_millis(&self) -> i32 {
342        self.subsec_nanos() / NANOS_PER_MILLI
343    }
344
345    /// Returns the total number of whole microseconds in the `TimeDelta`,
346    /// or `None` on overflow (exceeding 2^63 microseconds in either direction).
347    pub const fn num_microseconds(&self) -> Option<i64> {
348        let secs_part = match self.num_seconds().checked_mul(MICROS_PER_SEC) {
    Some(v) => v,
    None => return None,
}try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
349        let nanos_part = self.subsec_nanos() / NANOS_PER_MICRO;
350        secs_part.checked_add(nanos_part as i64)
351    }
352
353    /// Returns the number of microseconds in the fractional part of the duration.
354    ///
355    /// This is the number of microseconds such that
356    /// `subsec_micros() + num_seconds() * 1_000_000` is the truncated number of
357    /// microseconds in the duration.
358    pub const fn subsec_micros(&self) -> i32 {
359        self.subsec_nanos() / NANOS_PER_MICRO
360    }
361
362    /// Returns the total number of whole nanoseconds in the `TimeDelta`,
363    /// or `None` on overflow (exceeding 2^63 nanoseconds in either direction).
364    pub const fn num_nanoseconds(&self) -> Option<i64> {
365        let secs_part = match self.num_seconds().checked_mul(NANOS_PER_SEC as i64) {
    Some(v) => v,
    None => return None,
}try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
366        let nanos_part = self.subsec_nanos();
367        secs_part.checked_add(nanos_part as i64)
368    }
369
370    /// Returns the number of nanoseconds in the fractional part of the duration.
371    ///
372    /// This is the number of nanoseconds such that
373    /// `subsec_nanos() + num_seconds() * 1_000_000_000` is the total number of
374    /// nanoseconds in the `TimeDelta`.
375    pub const fn subsec_nanos(&self) -> i32 {
376        if self.secs < 0 && self.nanos > 0 { self.nanos - NANOS_PER_SEC } else { self.nanos }
377    }
378
379    /// Add two `TimeDelta`s, returning `None` if overflow occurred.
380    #[must_use]
381    pub const fn checked_add(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
382        // No overflow checks here because we stay comfortably within the range of an `i64`.
383        // Range checks happen in `TimeDelta::new`.
384        let mut secs = self.secs + rhs.secs;
385        let mut nanos = self.nanos + rhs.nanos;
386        if nanos >= NANOS_PER_SEC {
387            nanos -= NANOS_PER_SEC;
388            secs += 1;
389        }
390        TimeDelta::new(secs, nanos as u32)
391    }
392
393    /// Subtract two `TimeDelta`s, returning `None` if overflow occurred.
394    #[must_use]
395    pub const fn checked_sub(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
396        // No overflow checks here because we stay comfortably within the range of an `i64`.
397        // Range checks happen in `TimeDelta::new`.
398        let mut secs = self.secs - rhs.secs;
399        let mut nanos = self.nanos - rhs.nanos;
400        if nanos < 0 {
401            nanos += NANOS_PER_SEC;
402            secs -= 1;
403        }
404        TimeDelta::new(secs, nanos as u32)
405    }
406
407    /// Multiply a `TimeDelta` with a i32, returning `None` if overflow occurred.
408    #[must_use]
409    pub const fn checked_mul(&self, rhs: i32) -> Option<TimeDelta> {
410        // Multiply nanoseconds as i64, because it cannot overflow that way.
411        let total_nanos = self.nanos as i64 * rhs as i64;
412        let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
413        // Multiply seconds as i128 to prevent overflow
414        let secs: i128 = self.secs as i128 * rhs as i128 + extra_secs as i128;
415        if secs <= i64::MIN as i128 || secs >= i64::MAX as i128 {
416            return None;
417        };
418        Some(TimeDelta { secs: secs as i64, nanos: nanos as i32 })
419    }
420
421    /// Divide a `TimeDelta` with a i32, returning `None` if dividing by 0.
422    #[must_use]
423    pub const fn checked_div(&self, rhs: i32) -> Option<TimeDelta> {
424        if rhs == 0 {
425            return None;
426        }
427        let secs = self.secs / rhs as i64;
428        let carry = self.secs % rhs as i64;
429        let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
430        let nanos = self.nanos / rhs + extra_nanos as i32;
431
432        let (secs, nanos) = match nanos {
433            i32::MIN..=-1 => (secs - 1, nanos + NANOS_PER_SEC),
434            NANOS_PER_SEC..=i32::MAX => (secs + 1, nanos - NANOS_PER_SEC),
435            _ => (secs, nanos),
436        };
437
438        Some(TimeDelta { secs, nanos })
439    }
440
441    /// Returns the `TimeDelta` as an absolute (non-negative) value.
442    #[inline]
443    pub const fn abs(&self) -> TimeDelta {
444        if self.secs < 0 && self.nanos != 0 {
445            TimeDelta { secs: (self.secs + 1).abs(), nanos: NANOS_PER_SEC - self.nanos }
446        } else {
447            TimeDelta { secs: self.secs.abs(), nanos: self.nanos }
448        }
449    }
450
451    /// The minimum possible `TimeDelta`: `-i64::MAX` milliseconds.
452    #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MIN` instead")]
453    #[inline]
454    pub const fn min_value() -> TimeDelta {
455        MIN
456    }
457
458    /// The maximum possible `TimeDelta`: `i64::MAX` milliseconds.
459    #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MAX` instead")]
460    #[inline]
461    pub const fn max_value() -> TimeDelta {
462        MAX
463    }
464
465    /// A `TimeDelta` where the stored seconds and nanoseconds are equal to zero.
466    #[inline]
467    pub const fn zero() -> TimeDelta {
468        TimeDelta { secs: 0, nanos: 0 }
469    }
470
471    /// Returns `true` if the `TimeDelta` equals `TimeDelta::zero()`.
472    #[inline]
473    pub const fn is_zero(&self) -> bool {
474        self.secs == 0 && self.nanos == 0
475    }
476
477    /// Creates a `TimeDelta` object from `std::time::Duration`
478    ///
479    /// This function errors when original duration is larger than the maximum
480    /// value supported for this type.
481    pub const fn from_std(duration: Duration) -> Result<TimeDelta, OutOfRangeError> {
482        // We need to check secs as u64 before coercing to i64
483        if duration.as_secs() > MAX.secs as u64 {
484            return Err(OutOfRangeError(()));
485        }
486        match TimeDelta::new(duration.as_secs() as i64, duration.subsec_nanos()) {
487            Some(d) => Ok(d),
488            None => Err(OutOfRangeError(())),
489        }
490    }
491
492    /// Creates a `std::time::Duration` object from a `TimeDelta`.
493    ///
494    /// This function errors when duration is less than zero. As standard
495    /// library implementation is limited to non-negative values.
496    pub const fn to_std(&self) -> Result<Duration, OutOfRangeError> {
497        if self.secs < 0 {
498            return Err(OutOfRangeError(()));
499        }
500        Ok(Duration::new(self.secs as u64, self.nanos as u32))
501    }
502
503    /// This duplicates `Neg::neg` because trait methods can't be const yet.
504    pub(crate) const fn neg(self) -> TimeDelta {
505        let (secs_diff, nanos) = match self.nanos {
506            0 => (0, 0),
507            nanos => (1, NANOS_PER_SEC - nanos),
508        };
509        TimeDelta { secs: -self.secs - secs_diff, nanos }
510    }
511
512    /// The minimum possible `TimeDelta`: `-i64::MAX` milliseconds.
513    pub const MIN: Self = MIN;
514
515    /// The maximum possible `TimeDelta`: `i64::MAX` milliseconds.
516    pub const MAX: Self = MAX;
517}
518
519impl Neg for TimeDelta {
520    type Output = TimeDelta;
521
522    #[inline]
523    #[track_caller]
524    fn neg(self) -> TimeDelta {
525        let (secs_diff, nanos) = match self.nanos {
526            0 => (0, 0),
527            nanos => (1, NANOS_PER_SEC - nanos),
528        };
529        TimeDelta { secs: -self.secs - secs_diff, nanos }
530    }
531}
532
533impl Add for TimeDelta {
534    type Output = TimeDelta;
535
536    #[track_caller]
537    fn add(self, rhs: TimeDelta) -> TimeDelta {
538        self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed")
539    }
540}
541
542impl Sub for TimeDelta {
543    type Output = TimeDelta;
544
545    #[track_caller]
546    fn sub(self, rhs: TimeDelta) -> TimeDelta {
547        self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed")
548    }
549}
550
551impl AddAssign for TimeDelta {
552    #[track_caller]
553    fn add_assign(&mut self, rhs: TimeDelta) {
554        let new = self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed");
555        *self = new;
556    }
557}
558
559impl SubAssign for TimeDelta {
560    #[track_caller]
561    fn sub_assign(&mut self, rhs: TimeDelta) {
562        let new = self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed");
563        *self = new;
564    }
565}
566
567impl Mul<i32> for TimeDelta {
568    type Output = TimeDelta;
569
570    #[track_caller]
571    fn mul(self, rhs: i32) -> TimeDelta {
572        self.checked_mul(rhs).expect("`TimeDelta * i32` overflowed")
573    }
574}
575
576impl Div<i32> for TimeDelta {
577    type Output = TimeDelta;
578
579    #[track_caller]
580    fn div(self, rhs: i32) -> TimeDelta {
581        self.checked_div(rhs).expect("`i32` is zero")
582    }
583}
584
585impl<'a> core::iter::Sum<&'a TimeDelta> for TimeDelta {
586    fn sum<I: Iterator<Item = &'a TimeDelta>>(iter: I) -> TimeDelta {
587        iter.fold(TimeDelta::zero(), |acc, x| acc + *x)
588    }
589}
590
591impl core::iter::Sum<TimeDelta> for TimeDelta {
592    fn sum<I: Iterator<Item = TimeDelta>>(iter: I) -> TimeDelta {
593        iter.fold(TimeDelta::zero(), |acc, x| acc + x)
594    }
595}
596
597impl fmt::Display for TimeDelta {
598    /// Format a `TimeDelta` using the [ISO 8601] format
599    ///
600    /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601#Durations
601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
602        // technically speaking, negative duration is not valid ISO 8601,
603        // but we need to print it anyway.
604        let (abs, sign) = if self.secs < 0 { (-*self, "-") } else { (*self, "") };
605
606        f.write_fmt(format_args!("{0}P", sign))write!(f, "{sign}P")?;
607        // Plenty of ways to encode an empty string. `P0D` is short and not too strange.
608        if abs.secs == 0 && abs.nanos == 0 {
609            return f.write_str("0D");
610        }
611
612        f.write_fmt(format_args!("T{0}", abs.secs)format_args!("T{}", abs.secs))?;
613
614        if abs.nanos > 0 {
615            // Count the number of significant digits, while removing all trailing zero's.
616            let mut figures = 9usize;
617            let mut fraction_digits = abs.nanos;
618            loop {
619                let div = fraction_digits / 10;
620                let last_digit = fraction_digits % 10;
621                if last_digit != 0 {
622                    break;
623                }
624                fraction_digits = div;
625                figures -= 1;
626            }
627            f.write_fmt(format_args!(".{0:01$}", fraction_digits, figures)format_args!(".{fraction_digits:0figures$}"))?;
628        }
629        f.write_str("S")?;
630        Ok(())
631    }
632}
633
634/// Represents error when converting `TimeDelta` to/from a standard library
635/// implementation
636///
637/// The `std::time::Duration` supports a range from zero to `u64::MAX`
638/// *seconds*, while this module supports signed range of up to
639/// `i64::MAX` of *milliseconds*.
640#[derive(#[automatically_derived]
impl ::core::fmt::Debug for OutOfRangeError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "OutOfRangeError", &&self.0)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for OutOfRangeError {
    #[inline]
    fn clone(&self) -> OutOfRangeError {
        let _: ::core::clone::AssertParamIsClone<()>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for OutOfRangeError { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for OutOfRangeError {
    #[inline]
    fn eq(&self, other: &OutOfRangeError) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OutOfRangeError {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<()>;
    }
}Eq)]
641#[cfg_attr(feature = "defmt", derive(defmt::Format))]
642pub struct OutOfRangeError(());
643
644impl fmt::Display for OutOfRangeError {
645    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
646        f.write_fmt(format_args!("Source duration value is out of range for the target type"))write!(f, "Source duration value is out of range for the target type")
647    }
648}
649
650#[cfg(any(feature = "std", feature = "core-error"))]
651impl Error for OutOfRangeError {
652    #[allow(deprecated)]
653    fn description(&self) -> &str {
654        "out of range error"
655    }
656}
657
658#[inline]
659const fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
660    (this.div_euclid(other), this.rem_euclid(other))
661}
662
663#[cfg(all(feature = "arbitrary", feature = "std"))]
664impl arbitrary::Arbitrary<'_> for TimeDelta {
665    fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<TimeDelta> {
666        const MIN_SECS: i64 = -i64::MAX / MILLIS_PER_SEC - 1;
667        const MAX_SECS: i64 = i64::MAX / MILLIS_PER_SEC;
668
669        let secs: i64 = u.int_in_range(MIN_SECS..=MAX_SECS)?;
670        let nanos: i32 = u.int_in_range(0..=(NANOS_PER_SEC - 1))?;
671        let duration = TimeDelta { secs, nanos };
672
673        if duration < MIN || duration > MAX {
674            Err(arbitrary::Error::IncorrectFormat)
675        } else {
676            Ok(duration)
677        }
678    }
679}
680
681#[cfg(feature = "serde")]
682mod serde {
683    use super::TimeDelta;
684    use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
685
686    impl Serialize for TimeDelta {
687        fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
688            <(i64, i32) as Serialize>::serialize(&(self.secs, self.nanos), serializer)
689        }
690    }
691
692    impl<'de> Deserialize<'de> for TimeDelta {
693        fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
694            let (secs, nanos) = <(i64, i32) as Deserialize>::deserialize(deserializer)?;
695            TimeDelta::new(secs, nanos as u32).ok_or(Error::custom("TimeDelta out of bounds"))
696        }
697    }
698
699    #[cfg(test)]
700    mod tests {
701        use super::{super::MAX, TimeDelta};
702
703        #[test]
704        fn test_serde() {
705            let duration = TimeDelta::new(123, 456).unwrap();
706            assert_eq!(
707                serde_json::from_value::<TimeDelta>(serde_json::to_value(duration).unwrap())
708                    .unwrap(),
709                duration
710            );
711        }
712
713        #[test]
714        #[should_panic(expected = "TimeDelta out of bounds")]
715        fn test_serde_oob_panic() {
716            let _ =
717                serde_json::from_value::<TimeDelta>(serde_json::json!([MAX.secs + 1, 0])).unwrap();
718        }
719    }
720}
721
722#[cfg(test)]
723mod tests {
724    use super::OutOfRangeError;
725    use super::{MAX, MIN, TimeDelta};
726    use crate::expect;
727    use core::time::Duration;
728
729    #[test]
730    fn test_duration() {
731        let days = |d| TimeDelta::try_days(d).unwrap();
732        let seconds = |s| TimeDelta::try_seconds(s).unwrap();
733
734        assert!(seconds(1) != TimeDelta::zero());
735        assert_eq!(seconds(1) + seconds(2), seconds(3));
736        assert_eq!(seconds(86_399) + seconds(4), days(1) + seconds(3));
737        assert_eq!(days(10) - seconds(1000), seconds(863_000));
738        assert_eq!(days(10) - seconds(1_000_000), seconds(-136_000));
739        assert_eq!(
740            days(2) + seconds(86_399) + TimeDelta::nanoseconds(1_234_567_890),
741            days(3) + TimeDelta::nanoseconds(234_567_890)
742        );
743        assert_eq!(-days(3), days(-3));
744        assert_eq!(-(days(3) + seconds(70)), days(-4) + seconds(86_400 - 70));
745
746        let mut d = TimeDelta::default();
747        d += TimeDelta::try_minutes(1).unwrap();
748        d -= seconds(30);
749        assert_eq!(d, seconds(30));
750    }
751
752    #[test]
753    fn test_duration_num_days() {
754        assert_eq!(TimeDelta::zero().num_days(), 0);
755        assert_eq!(TimeDelta::try_days(1).unwrap().num_days(), 1);
756        assert_eq!(TimeDelta::try_days(-1).unwrap().num_days(), -1);
757        assert_eq!(TimeDelta::try_seconds(86_399).unwrap().num_days(), 0);
758        assert_eq!(TimeDelta::try_seconds(86_401).unwrap().num_days(), 1);
759        assert_eq!(TimeDelta::try_seconds(-86_399).unwrap().num_days(), 0);
760        assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().num_days(), -1);
761        assert_eq!(TimeDelta::try_days(i32::MAX as i64).unwrap().num_days(), i32::MAX as i64);
762        assert_eq!(TimeDelta::try_days(i32::MIN as i64).unwrap().num_days(), i32::MIN as i64);
763    }
764
765    #[test]
766    fn test_duration_num_seconds() {
767        assert_eq!(TimeDelta::zero().num_seconds(), 0);
768        assert_eq!(TimeDelta::try_seconds(1).unwrap().num_seconds(), 1);
769        assert_eq!(TimeDelta::try_seconds(-1).unwrap().num_seconds(), -1);
770        assert_eq!(TimeDelta::try_milliseconds(999).unwrap().num_seconds(), 0);
771        assert_eq!(TimeDelta::try_milliseconds(1001).unwrap().num_seconds(), 1);
772        assert_eq!(TimeDelta::try_milliseconds(-999).unwrap().num_seconds(), 0);
773        assert_eq!(TimeDelta::try_milliseconds(-1001).unwrap().num_seconds(), -1);
774    }
775
776    #[test]
777    fn test_duration_seconds_max_allowed() {
778        let duration = TimeDelta::try_seconds(i64::MAX / 1_000).unwrap();
779        assert_eq!(duration.num_seconds(), i64::MAX / 1_000);
780        assert_eq!(
781            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
782            i64::MAX as i128 / 1_000 * 1_000_000_000
783        );
784    }
785
786    #[test]
787    fn test_duration_seconds_max_overflow() {
788        assert!(TimeDelta::try_seconds(i64::MAX / 1_000 + 1).is_none());
789    }
790
791    #[test]
792    #[should_panic(expected = "TimeDelta::seconds out of bounds")]
793    fn test_duration_seconds_max_overflow_panic() {
794        let _ = TimeDelta::seconds(i64::MAX / 1_000 + 1);
795    }
796
797    #[test]
798    fn test_duration_seconds_min_allowed() {
799        let duration = TimeDelta::try_seconds(i64::MIN / 1_000).unwrap(); // Same as -i64::MAX / 1_000 due to rounding
800        assert_eq!(duration.num_seconds(), i64::MIN / 1_000); // Same as -i64::MAX / 1_000 due to rounding
801        assert_eq!(
802            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
803            -i64::MAX as i128 / 1_000 * 1_000_000_000
804        );
805    }
806
807    #[test]
808    fn test_duration_seconds_min_underflow() {
809        assert!(TimeDelta::try_seconds(-i64::MAX / 1_000 - 1).is_none());
810    }
811
812    #[test]
813    #[should_panic(expected = "TimeDelta::seconds out of bounds")]
814    fn test_duration_seconds_min_underflow_panic() {
815        let _ = TimeDelta::seconds(-i64::MAX / 1_000 - 1);
816    }
817
818    #[test]
819    fn test_duration_as_seconds_f64() {
820        assert_eq!(TimeDelta::seconds(1).as_seconds_f64(), 1.0);
821        assert_eq!(TimeDelta::seconds(-1).as_seconds_f64(), -1.0);
822        assert_eq!(TimeDelta::seconds(100).as_seconds_f64(), 100.0);
823        assert_eq!(TimeDelta::seconds(-100).as_seconds_f64(), -100.0);
824
825        assert_eq!(TimeDelta::milliseconds(500).as_seconds_f64(), 0.5);
826        assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f64(), -0.5);
827        assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f64(), 1.5);
828        assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f64(), -1.5);
829    }
830
831    #[test]
832    fn test_duration_as_seconds_f32() {
833        assert_eq!(TimeDelta::seconds(1).as_seconds_f32(), 1.0);
834        assert_eq!(TimeDelta::seconds(-1).as_seconds_f32(), -1.0);
835        assert_eq!(TimeDelta::seconds(100).as_seconds_f32(), 100.0);
836        assert_eq!(TimeDelta::seconds(-100).as_seconds_f32(), -100.0);
837
838        assert_eq!(TimeDelta::milliseconds(500).as_seconds_f32(), 0.5);
839        assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f32(), -0.5);
840        assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f32(), 1.5);
841        assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f32(), -1.5);
842    }
843
844    #[test]
845    fn test_duration_subsec_nanos() {
846        assert_eq!(TimeDelta::zero().subsec_nanos(), 0);
847        assert_eq!(TimeDelta::nanoseconds(1).subsec_nanos(), 1);
848        assert_eq!(TimeDelta::nanoseconds(-1).subsec_nanos(), -1);
849        assert_eq!(TimeDelta::seconds(1).subsec_nanos(), 0);
850        assert_eq!(TimeDelta::nanoseconds(1_000_000_001).subsec_nanos(), 1);
851    }
852
853    #[test]
854    fn test_duration_subsec_micros() {
855        assert_eq!(TimeDelta::zero().subsec_micros(), 0);
856        assert_eq!(TimeDelta::microseconds(1).subsec_micros(), 1);
857        assert_eq!(TimeDelta::microseconds(-1).subsec_micros(), -1);
858        assert_eq!(TimeDelta::seconds(1).subsec_micros(), 0);
859        assert_eq!(TimeDelta::microseconds(1_000_001).subsec_micros(), 1);
860        assert_eq!(TimeDelta::nanoseconds(1_000_001_999).subsec_micros(), 1);
861    }
862
863    #[test]
864    fn test_duration_subsec_millis() {
865        assert_eq!(TimeDelta::zero().subsec_millis(), 0);
866        assert_eq!(TimeDelta::milliseconds(1).subsec_millis(), 1);
867        assert_eq!(TimeDelta::milliseconds(-1).subsec_millis(), -1);
868        assert_eq!(TimeDelta::seconds(1).subsec_millis(), 0);
869        assert_eq!(TimeDelta::milliseconds(1_001).subsec_millis(), 1);
870        assert_eq!(TimeDelta::microseconds(1_001_999).subsec_millis(), 1);
871    }
872
873    #[test]
874    fn test_duration_num_milliseconds() {
875        assert_eq!(TimeDelta::zero().num_milliseconds(), 0);
876        assert_eq!(TimeDelta::try_milliseconds(1).unwrap().num_milliseconds(), 1);
877        assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().num_milliseconds(), -1);
878        assert_eq!(TimeDelta::microseconds(999).num_milliseconds(), 0);
879        assert_eq!(TimeDelta::microseconds(1001).num_milliseconds(), 1);
880        assert_eq!(TimeDelta::microseconds(-999).num_milliseconds(), 0);
881        assert_eq!(TimeDelta::microseconds(-1001).num_milliseconds(), -1);
882    }
883
884    #[test]
885    fn test_duration_milliseconds_max_allowed() {
886        // The maximum number of milliseconds acceptable through the constructor is
887        // equal to the number that can be stored in a TimeDelta.
888        let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
889        assert_eq!(duration.num_milliseconds(), i64::MAX);
890        assert_eq!(
891            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
892            i64::MAX as i128 * 1_000_000
893        );
894    }
895
896    #[test]
897    fn test_duration_milliseconds_max_overflow() {
898        // Here we ensure that trying to add one millisecond to the maximum storable
899        // value will fail.
900        assert!(
901            TimeDelta::try_milliseconds(i64::MAX)
902                .unwrap()
903                .checked_add(&TimeDelta::try_milliseconds(1).unwrap())
904                .is_none()
905        );
906    }
907
908    #[test]
909    fn test_duration_milliseconds_min_allowed() {
910        // The minimum number of milliseconds acceptable through the constructor is
911        // not equal to the number that can be stored in a TimeDelta - there is a
912        // difference of one (i64::MIN vs -i64::MAX).
913        let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
914        assert_eq!(duration.num_milliseconds(), -i64::MAX);
915        assert_eq!(
916            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
917            -i64::MAX as i128 * 1_000_000
918        );
919    }
920
921    #[test]
922    fn test_duration_milliseconds_min_underflow() {
923        // Here we ensure that trying to subtract one millisecond from the minimum
924        // storable value will fail.
925        assert!(
926            TimeDelta::try_milliseconds(-i64::MAX)
927                .unwrap()
928                .checked_sub(&TimeDelta::try_milliseconds(1).unwrap())
929                .is_none()
930        );
931    }
932
933    #[test]
934    #[should_panic(expected = "TimeDelta::milliseconds out of bounds")]
935    fn test_duration_milliseconds_min_underflow_panic() {
936        // Here we ensure that trying to create a value one millisecond below the
937        // minimum storable value will fail. This test is necessary because the
938        // storable range is -i64::MAX, but the constructor type of i64 will allow
939        // i64::MIN, which is one value below.
940        let _ = TimeDelta::milliseconds(i64::MIN); // Same as -i64::MAX - 1
941    }
942
943    #[test]
944    fn test_duration_num_microseconds() {
945        assert_eq!(TimeDelta::zero().num_microseconds(), Some(0));
946        assert_eq!(TimeDelta::microseconds(1).num_microseconds(), Some(1));
947        assert_eq!(TimeDelta::microseconds(-1).num_microseconds(), Some(-1));
948        assert_eq!(TimeDelta::nanoseconds(999).num_microseconds(), Some(0));
949        assert_eq!(TimeDelta::nanoseconds(1001).num_microseconds(), Some(1));
950        assert_eq!(TimeDelta::nanoseconds(-999).num_microseconds(), Some(0));
951        assert_eq!(TimeDelta::nanoseconds(-1001).num_microseconds(), Some(-1));
952
953        // overflow checks
954        const MICROS_PER_DAY: i64 = 86_400_000_000;
955        assert_eq!(
956            TimeDelta::try_days(i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
957            Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
958        );
959        assert_eq!(
960            TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
961            Some(-i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
962        );
963        assert_eq!(
964            TimeDelta::try_days(i64::MAX / MICROS_PER_DAY + 1).unwrap().num_microseconds(),
965            None
966        );
967        assert_eq!(
968            TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY - 1).unwrap().num_microseconds(),
969            None
970        );
971    }
972    #[test]
973    fn test_duration_microseconds_max_allowed() {
974        // The number of microseconds acceptable through the constructor is far
975        // fewer than the number that can actually be stored in a TimeDelta, so this
976        // is not a particular insightful test.
977        let duration = TimeDelta::microseconds(i64::MAX);
978        assert_eq!(duration.num_microseconds(), Some(i64::MAX));
979        assert_eq!(
980            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
981            i64::MAX as i128 * 1_000
982        );
983        // Here we create a TimeDelta with the maximum possible number of
984        // microseconds by creating a TimeDelta with the maximum number of
985        // milliseconds and then checking that the number of microseconds matches
986        // the storage limit.
987        let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
988        assert!(duration.num_microseconds().is_none());
989        assert_eq!(
990            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
991            i64::MAX as i128 * 1_000_000
992        );
993    }
994    #[test]
995    fn test_duration_microseconds_max_overflow() {
996        // This test establishes that a TimeDelta can store more microseconds than
997        // are representable through the return of duration.num_microseconds().
998        let duration = TimeDelta::microseconds(i64::MAX) + TimeDelta::microseconds(1);
999        assert!(duration.num_microseconds().is_none());
1000        assert_eq!(
1001            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1002            (i64::MAX as i128 + 1) * 1_000
1003        );
1004        // Here we ensure that trying to add one microsecond to the maximum storable
1005        // value will fail.
1006        assert!(
1007            TimeDelta::try_milliseconds(i64::MAX)
1008                .unwrap()
1009                .checked_add(&TimeDelta::microseconds(1))
1010                .is_none()
1011        );
1012    }
1013    #[test]
1014    fn test_duration_microseconds_min_allowed() {
1015        // The number of microseconds acceptable through the constructor is far
1016        // fewer than the number that can actually be stored in a TimeDelta, so this
1017        // is not a particular insightful test.
1018        let duration = TimeDelta::microseconds(i64::MIN);
1019        assert_eq!(duration.num_microseconds(), Some(i64::MIN));
1020        assert_eq!(
1021            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1022            i64::MIN as i128 * 1_000
1023        );
1024        // Here we create a TimeDelta with the minimum possible number of
1025        // microseconds by creating a TimeDelta with the minimum number of
1026        // milliseconds and then checking that the number of microseconds matches
1027        // the storage limit.
1028        let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1029        assert!(duration.num_microseconds().is_none());
1030        assert_eq!(
1031            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1032            -i64::MAX as i128 * 1_000_000
1033        );
1034    }
1035    #[test]
1036    fn test_duration_microseconds_min_underflow() {
1037        // This test establishes that a TimeDelta can store more microseconds than
1038        // are representable through the return of duration.num_microseconds().
1039        let duration = TimeDelta::microseconds(i64::MIN) - TimeDelta::microseconds(1);
1040        assert!(duration.num_microseconds().is_none());
1041        assert_eq!(
1042            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1043            (i64::MIN as i128 - 1) * 1_000
1044        );
1045        // Here we ensure that trying to subtract one microsecond from the minimum
1046        // storable value will fail.
1047        assert!(
1048            TimeDelta::try_milliseconds(-i64::MAX)
1049                .unwrap()
1050                .checked_sub(&TimeDelta::microseconds(1))
1051                .is_none()
1052        );
1053    }
1054
1055    #[test]
1056    fn test_duration_num_nanoseconds() {
1057        assert_eq!(TimeDelta::zero().num_nanoseconds(), Some(0));
1058        assert_eq!(TimeDelta::nanoseconds(1).num_nanoseconds(), Some(1));
1059        assert_eq!(TimeDelta::nanoseconds(-1).num_nanoseconds(), Some(-1));
1060
1061        // overflow checks
1062        const NANOS_PER_DAY: i64 = 86_400_000_000_000;
1063        assert_eq!(
1064            TimeDelta::try_days(i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1065            Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1066        );
1067        assert_eq!(
1068            TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1069            Some(-i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1070        );
1071        assert_eq!(
1072            TimeDelta::try_days(i64::MAX / NANOS_PER_DAY + 1).unwrap().num_nanoseconds(),
1073            None
1074        );
1075        assert_eq!(
1076            TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY - 1).unwrap().num_nanoseconds(),
1077            None
1078        );
1079    }
1080    #[test]
1081    fn test_duration_nanoseconds_max_allowed() {
1082        // The number of nanoseconds acceptable through the constructor is far fewer
1083        // than the number that can actually be stored in a TimeDelta, so this is not
1084        // a particular insightful test.
1085        let duration = TimeDelta::nanoseconds(i64::MAX);
1086        assert_eq!(duration.num_nanoseconds(), Some(i64::MAX));
1087        assert_eq!(
1088            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1089            i64::MAX as i128
1090        );
1091        // Here we create a TimeDelta with the maximum possible number of nanoseconds
1092        // by creating a TimeDelta with the maximum number of milliseconds and then
1093        // checking that the number of nanoseconds matches the storage limit.
1094        let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
1095        assert!(duration.num_nanoseconds().is_none());
1096        assert_eq!(
1097            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1098            i64::MAX as i128 * 1_000_000
1099        );
1100    }
1101
1102    #[test]
1103    fn test_duration_nanoseconds_max_overflow() {
1104        // This test establishes that a TimeDelta can store more nanoseconds than are
1105        // representable through the return of duration.num_nanoseconds().
1106        let duration = TimeDelta::nanoseconds(i64::MAX) + TimeDelta::nanoseconds(1);
1107        assert!(duration.num_nanoseconds().is_none());
1108        assert_eq!(
1109            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1110            i64::MAX as i128 + 1
1111        );
1112        // Here we ensure that trying to add one nanosecond to the maximum storable
1113        // value will fail.
1114        assert!(
1115            TimeDelta::try_milliseconds(i64::MAX)
1116                .unwrap()
1117                .checked_add(&TimeDelta::nanoseconds(1))
1118                .is_none()
1119        );
1120    }
1121
1122    #[test]
1123    fn test_duration_nanoseconds_min_allowed() {
1124        // The number of nanoseconds acceptable through the constructor is far fewer
1125        // than the number that can actually be stored in a TimeDelta, so this is not
1126        // a particular insightful test.
1127        let duration = TimeDelta::nanoseconds(i64::MIN);
1128        assert_eq!(duration.num_nanoseconds(), Some(i64::MIN));
1129        assert_eq!(
1130            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1131            i64::MIN as i128
1132        );
1133        // Here we create a TimeDelta with the minimum possible number of nanoseconds
1134        // by creating a TimeDelta with the minimum number of milliseconds and then
1135        // checking that the number of nanoseconds matches the storage limit.
1136        let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1137        assert!(duration.num_nanoseconds().is_none());
1138        assert_eq!(
1139            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1140            -i64::MAX as i128 * 1_000_000
1141        );
1142    }
1143
1144    #[test]
1145    fn test_duration_nanoseconds_min_underflow() {
1146        // This test establishes that a TimeDelta can store more nanoseconds than are
1147        // representable through the return of duration.num_nanoseconds().
1148        let duration = TimeDelta::nanoseconds(i64::MIN) - TimeDelta::nanoseconds(1);
1149        assert!(duration.num_nanoseconds().is_none());
1150        assert_eq!(
1151            duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1152            i64::MIN as i128 - 1
1153        );
1154        // Here we ensure that trying to subtract one nanosecond from the minimum
1155        // storable value will fail.
1156        assert!(
1157            TimeDelta::try_milliseconds(-i64::MAX)
1158                .unwrap()
1159                .checked_sub(&TimeDelta::nanoseconds(1))
1160                .is_none()
1161        );
1162    }
1163
1164    #[test]
1165    fn test_max() {
1166        assert_eq!(
1167            MAX.secs as i128 * 1_000_000_000 + MAX.nanos as i128,
1168            i64::MAX as i128 * 1_000_000
1169        );
1170        assert_eq!(MAX, TimeDelta::try_milliseconds(i64::MAX).unwrap());
1171        assert_eq!(MAX.num_milliseconds(), i64::MAX);
1172        assert_eq!(MAX.num_microseconds(), None);
1173        assert_eq!(MAX.num_nanoseconds(), None);
1174    }
1175
1176    #[test]
1177    fn test_min() {
1178        assert_eq!(
1179            MIN.secs as i128 * 1_000_000_000 + MIN.nanos as i128,
1180            -i64::MAX as i128 * 1_000_000
1181        );
1182        assert_eq!(MIN, TimeDelta::try_milliseconds(-i64::MAX).unwrap());
1183        assert_eq!(MIN.num_milliseconds(), -i64::MAX);
1184        assert_eq!(MIN.num_microseconds(), None);
1185        assert_eq!(MIN.num_nanoseconds(), None);
1186    }
1187
1188    #[test]
1189    fn test_duration_ord() {
1190        let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1191
1192        assert!(milliseconds(1) < milliseconds(2));
1193        assert!(milliseconds(2) > milliseconds(1));
1194        assert!(milliseconds(-1) > milliseconds(-2));
1195        assert!(milliseconds(-2) < milliseconds(-1));
1196        assert!(milliseconds(-1) < milliseconds(1));
1197        assert!(milliseconds(1) > milliseconds(-1));
1198        assert!(milliseconds(0) < milliseconds(1));
1199        assert!(milliseconds(0) > milliseconds(-1));
1200        assert!(milliseconds(1_001) < milliseconds(1_002));
1201        assert!(milliseconds(-1_001) > milliseconds(-1_002));
1202        assert!(TimeDelta::nanoseconds(1_234_567_890) < TimeDelta::nanoseconds(1_234_567_891));
1203        assert!(TimeDelta::nanoseconds(-1_234_567_890) > TimeDelta::nanoseconds(-1_234_567_891));
1204        assert!(milliseconds(i64::MAX) > milliseconds(i64::MAX - 1));
1205        assert!(milliseconds(-i64::MAX) < milliseconds(-i64::MAX + 1));
1206    }
1207
1208    #[test]
1209    fn test_duration_checked_ops() {
1210        let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1211        let seconds = |s| TimeDelta::try_seconds(s).unwrap();
1212
1213        assert_eq!(
1214            milliseconds(i64::MAX).checked_add(&milliseconds(0)),
1215            Some(milliseconds(i64::MAX))
1216        );
1217        assert_eq!(
1218            milliseconds(i64::MAX - 1).checked_add(&TimeDelta::microseconds(999)),
1219            Some(milliseconds(i64::MAX - 2) + TimeDelta::microseconds(1999))
1220        );
1221        assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::microseconds(1000)).is_none());
1222        assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::nanoseconds(1)).is_none());
1223
1224        assert_eq!(
1225            milliseconds(-i64::MAX).checked_sub(&milliseconds(0)),
1226            Some(milliseconds(-i64::MAX))
1227        );
1228        assert_eq!(
1229            milliseconds(-i64::MAX + 1).checked_sub(&TimeDelta::microseconds(999)),
1230            Some(milliseconds(-i64::MAX + 2) - TimeDelta::microseconds(1999))
1231        );
1232        assert!(milliseconds(-i64::MAX).checked_sub(&milliseconds(1)).is_none());
1233        assert!(milliseconds(-i64::MAX).checked_sub(&TimeDelta::nanoseconds(1)).is_none());
1234
1235        assert!(seconds(i64::MAX / 1000).checked_mul(2000).is_none());
1236        assert!(seconds(i64::MIN / 1000).checked_mul(2000).is_none());
1237        assert!(seconds(1).checked_div(0).is_none());
1238    }
1239
1240    #[test]
1241    fn test_duration_abs() {
1242        let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1243
1244        assert_eq!(milliseconds(1300).abs(), milliseconds(1300));
1245        assert_eq!(milliseconds(1000).abs(), milliseconds(1000));
1246        assert_eq!(milliseconds(300).abs(), milliseconds(300));
1247        assert_eq!(milliseconds(0).abs(), milliseconds(0));
1248        assert_eq!(milliseconds(-300).abs(), milliseconds(300));
1249        assert_eq!(milliseconds(-700).abs(), milliseconds(700));
1250        assert_eq!(milliseconds(-1000).abs(), milliseconds(1000));
1251        assert_eq!(milliseconds(-1300).abs(), milliseconds(1300));
1252        assert_eq!(milliseconds(-1700).abs(), milliseconds(1700));
1253        assert_eq!(milliseconds(-i64::MAX).abs(), milliseconds(i64::MAX));
1254    }
1255
1256    #[test]
1257    #[allow(clippy::erasing_op)]
1258    fn test_duration_mul() {
1259        assert_eq!(TimeDelta::zero() * i32::MAX, TimeDelta::zero());
1260        assert_eq!(TimeDelta::zero() * i32::MIN, TimeDelta::zero());
1261        assert_eq!(TimeDelta::nanoseconds(1) * 0, TimeDelta::zero());
1262        assert_eq!(TimeDelta::nanoseconds(1) * 1, TimeDelta::nanoseconds(1));
1263        assert_eq!(TimeDelta::nanoseconds(1) * 1_000_000_000, TimeDelta::try_seconds(1).unwrap());
1264        assert_eq!(TimeDelta::nanoseconds(1) * -1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1265        assert_eq!(-TimeDelta::nanoseconds(1) * 1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1266        assert_eq!(
1267            TimeDelta::nanoseconds(30) * 333_333_333,
1268            TimeDelta::try_seconds(10).unwrap() - TimeDelta::nanoseconds(10)
1269        );
1270        assert_eq!(
1271            (TimeDelta::nanoseconds(1)
1272                + TimeDelta::try_seconds(1).unwrap()
1273                + TimeDelta::try_days(1).unwrap())
1274                * 3,
1275            TimeDelta::nanoseconds(3)
1276                + TimeDelta::try_seconds(3).unwrap()
1277                + TimeDelta::try_days(3).unwrap()
1278        );
1279        assert_eq!(
1280            TimeDelta::try_milliseconds(1500).unwrap() * -2,
1281            TimeDelta::try_seconds(-3).unwrap()
1282        );
1283        assert_eq!(
1284            TimeDelta::try_milliseconds(-1500).unwrap() * 2,
1285            TimeDelta::try_seconds(-3).unwrap()
1286        );
1287    }
1288
1289    #[test]
1290    fn test_duration_div() {
1291        assert_eq!(TimeDelta::zero() / i32::MAX, TimeDelta::zero());
1292        assert_eq!(TimeDelta::zero() / i32::MIN, TimeDelta::zero());
1293        assert_eq!(TimeDelta::nanoseconds(123_456_789) / 1, TimeDelta::nanoseconds(123_456_789));
1294        assert_eq!(TimeDelta::nanoseconds(123_456_789) / -1, -TimeDelta::nanoseconds(123_456_789));
1295        assert_eq!(-TimeDelta::nanoseconds(123_456_789) / -1, TimeDelta::nanoseconds(123_456_789));
1296        assert_eq!(-TimeDelta::nanoseconds(123_456_789) / 1, -TimeDelta::nanoseconds(123_456_789));
1297        assert_eq!(TimeDelta::try_seconds(1).unwrap() / 3, TimeDelta::nanoseconds(333_333_333));
1298        assert_eq!(TimeDelta::try_seconds(4).unwrap() / 3, TimeDelta::nanoseconds(1_333_333_333));
1299        assert_eq!(
1300            TimeDelta::try_seconds(-1).unwrap() / 2,
1301            TimeDelta::try_milliseconds(-500).unwrap()
1302        );
1303        assert_eq!(
1304            TimeDelta::try_seconds(1).unwrap() / -2,
1305            TimeDelta::try_milliseconds(-500).unwrap()
1306        );
1307        assert_eq!(
1308            TimeDelta::try_seconds(-1).unwrap() / -2,
1309            TimeDelta::try_milliseconds(500).unwrap()
1310        );
1311        assert_eq!(TimeDelta::try_seconds(-4).unwrap() / 3, TimeDelta::nanoseconds(-1_333_333_333));
1312        assert_eq!(TimeDelta::try_seconds(-4).unwrap() / -3, TimeDelta::nanoseconds(1_333_333_333));
1313    }
1314
1315    #[test]
1316    fn test_duration_sum() {
1317        let duration_list_1 = [TimeDelta::zero(), TimeDelta::try_seconds(1).unwrap()];
1318        let sum_1: TimeDelta = duration_list_1.iter().sum();
1319        assert_eq!(sum_1, TimeDelta::try_seconds(1).unwrap());
1320
1321        let duration_list_2 = [
1322            TimeDelta::zero(),
1323            TimeDelta::try_seconds(1).unwrap(),
1324            TimeDelta::try_seconds(6).unwrap(),
1325            TimeDelta::try_seconds(10).unwrap(),
1326        ];
1327        let sum_2: TimeDelta = duration_list_2.iter().sum();
1328        assert_eq!(sum_2, TimeDelta::try_seconds(17).unwrap());
1329
1330        let duration_arr = [
1331            TimeDelta::zero(),
1332            TimeDelta::try_seconds(1).unwrap(),
1333            TimeDelta::try_seconds(6).unwrap(),
1334            TimeDelta::try_seconds(10).unwrap(),
1335        ];
1336        let sum_3: TimeDelta = duration_arr.into_iter().sum();
1337        assert_eq!(sum_3, TimeDelta::try_seconds(17).unwrap());
1338    }
1339
1340    #[test]
1341    fn test_duration_fmt() {
1342        assert_eq!(TimeDelta::zero().to_string(), "P0D");
1343        assert_eq!(TimeDelta::try_days(42).unwrap().to_string(), "PT3628800S");
1344        assert_eq!(TimeDelta::try_days(-42).unwrap().to_string(), "-PT3628800S");
1345        assert_eq!(TimeDelta::try_seconds(42).unwrap().to_string(), "PT42S");
1346        assert_eq!(TimeDelta::try_milliseconds(42).unwrap().to_string(), "PT0.042S");
1347        assert_eq!(TimeDelta::microseconds(42).to_string(), "PT0.000042S");
1348        assert_eq!(TimeDelta::nanoseconds(42).to_string(), "PT0.000000042S");
1349        assert_eq!(
1350            (TimeDelta::try_days(7).unwrap() + TimeDelta::try_milliseconds(6543).unwrap())
1351                .to_string(),
1352            "PT604806.543S"
1353        );
1354        assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().to_string(), "-PT86401S");
1355        assert_eq!(TimeDelta::nanoseconds(-1).to_string(), "-PT0.000000001S");
1356
1357        // the format specifier should have no effect on `TimeDelta`
1358        assert_eq!(
1359            format!(
1360                "{:30}",
1361                TimeDelta::try_days(1).unwrap() + TimeDelta::try_milliseconds(2345).unwrap()
1362            ),
1363            "PT86402.345S"
1364        );
1365    }
1366
1367    #[test]
1368    fn test_to_std() {
1369        assert_eq!(TimeDelta::try_seconds(1).unwrap().to_std(), Ok(Duration::new(1, 0)));
1370        assert_eq!(TimeDelta::try_seconds(86_401).unwrap().to_std(), Ok(Duration::new(86_401, 0)));
1371        assert_eq!(
1372            TimeDelta::try_milliseconds(123).unwrap().to_std(),
1373            Ok(Duration::new(0, 123_000_000))
1374        );
1375        assert_eq!(
1376            TimeDelta::try_milliseconds(123_765).unwrap().to_std(),
1377            Ok(Duration::new(123, 765_000_000))
1378        );
1379        assert_eq!(TimeDelta::nanoseconds(777).to_std(), Ok(Duration::new(0, 777)));
1380        assert_eq!(MAX.to_std(), Ok(Duration::new(9_223_372_036_854_775, 807_000_000)));
1381        assert_eq!(TimeDelta::try_seconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1382        assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1383    }
1384
1385    #[test]
1386    fn test_from_std() {
1387        assert_eq!(
1388            Ok(TimeDelta::try_seconds(1).unwrap()),
1389            TimeDelta::from_std(Duration::new(1, 0))
1390        );
1391        assert_eq!(
1392            Ok(TimeDelta::try_seconds(86_401).unwrap()),
1393            TimeDelta::from_std(Duration::new(86_401, 0))
1394        );
1395        assert_eq!(
1396            Ok(TimeDelta::try_milliseconds(123).unwrap()),
1397            TimeDelta::from_std(Duration::new(0, 123_000_000))
1398        );
1399        assert_eq!(
1400            Ok(TimeDelta::try_milliseconds(123_765).unwrap()),
1401            TimeDelta::from_std(Duration::new(123, 765_000_000))
1402        );
1403        assert_eq!(Ok(TimeDelta::nanoseconds(777)), TimeDelta::from_std(Duration::new(0, 777)));
1404        assert_eq!(Ok(MAX), TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_000)));
1405        assert_eq!(
1406            TimeDelta::from_std(Duration::new(9_223_372_036_854_776, 0)),
1407            Err(OutOfRangeError(()))
1408        );
1409        assert_eq!(
1410            TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_001)),
1411            Err(OutOfRangeError(()))
1412        );
1413    }
1414
1415    #[test]
1416    fn test_duration_const() {
1417        const ONE_WEEK: TimeDelta = expect(TimeDelta::try_weeks(1), "");
1418        const ONE_DAY: TimeDelta = expect(TimeDelta::try_days(1), "");
1419        const ONE_HOUR: TimeDelta = expect(TimeDelta::try_hours(1), "");
1420        const ONE_MINUTE: TimeDelta = expect(TimeDelta::try_minutes(1), "");
1421        const ONE_SECOND: TimeDelta = expect(TimeDelta::try_seconds(1), "");
1422        const ONE_MILLI: TimeDelta = expect(TimeDelta::try_milliseconds(1), "");
1423        const ONE_MICRO: TimeDelta = TimeDelta::microseconds(1);
1424        const ONE_NANO: TimeDelta = TimeDelta::nanoseconds(1);
1425        let combo: TimeDelta = ONE_WEEK
1426            + ONE_DAY
1427            + ONE_HOUR
1428            + ONE_MINUTE
1429            + ONE_SECOND
1430            + ONE_MILLI
1431            + ONE_MICRO
1432            + ONE_NANO;
1433
1434        assert!(ONE_WEEK != TimeDelta::zero());
1435        assert!(ONE_DAY != TimeDelta::zero());
1436        assert!(ONE_HOUR != TimeDelta::zero());
1437        assert!(ONE_MINUTE != TimeDelta::zero());
1438        assert!(ONE_SECOND != TimeDelta::zero());
1439        assert!(ONE_MILLI != TimeDelta::zero());
1440        assert!(ONE_MICRO != TimeDelta::zero());
1441        assert!(ONE_NANO != TimeDelta::zero());
1442        assert_eq!(
1443            combo,
1444            TimeDelta::try_seconds(86400 * 7 + 86400 + 3600 + 60 + 1).unwrap()
1445                + TimeDelta::nanoseconds(1 + 1_000 + 1_000_000)
1446        );
1447    }
1448
1449    #[test]
1450    #[cfg(feature = "rkyv-validation")]
1451    fn test_rkyv_validation() {
1452        let duration = TimeDelta::try_seconds(1).unwrap();
1453        let bytes = rkyv::to_bytes::<_, 16>(&duration).unwrap();
1454        assert_eq!(rkyv::from_bytes::<TimeDelta>(&bytes).unwrap(), duration);
1455    }
1456}