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.
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.
11 use ops
::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}
;
13 const NANOS_PER_SEC
: u32 = 1_000_000_000;
14 const NANOS_PER_MILLI
: u32 = 1_000_000;
15 const MILLIS_PER_SEC
: u64 = 1_000;
17 /// A duration type to represent a span of time, typically used for system
20 /// Each duration is composed of a number of seconds and nanosecond precision.
21 /// APIs binding a system timeout will typically round up the nanosecond
22 /// precision if the underlying system does not support that level of precision.
24 /// Durations implement many common traits, including `Add`, `Sub`, and other
25 /// ops traits. Currently a duration may only be inspected for its number of
26 /// seconds and its nanosecond precision.
31 /// use std::time::Duration;
33 /// let five_seconds = Duration::new(5, 0);
34 /// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
36 /// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
37 /// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
39 /// let ten_millis = Duration::from_millis(10);
41 #[stable(feature = "duration", since = "1.3.0")]
42 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
45 nanos
: u32, // Always 0 <= nanos < NANOS_PER_SEC
49 /// Creates a new `Duration` from the specified number of seconds and
50 /// additional nanosecond precision.
52 /// If the nanoseconds is greater than 1 billion (the number of nanoseconds
53 /// in a second), then it will carry over into the seconds provided.
57 /// This constructor will panic if the carry from the nanoseconds overflows
58 /// the seconds counter.
59 #[stable(feature = "duration", since = "1.3.0")]
61 pub fn new(secs
: u64, nanos
: u32) -> Duration
{
62 let secs
= secs
.checked_add((nanos
/ NANOS_PER_SEC
) as u64)
63 .expect("overflow in Duration::new");
64 let nanos
= nanos
% NANOS_PER_SEC
;
65 Duration { secs: secs, nanos: nanos }
68 /// Creates a new `Duration` from the specified number of seconds.
69 #[stable(feature = "duration", since = "1.3.0")]
71 pub fn from_secs(secs
: u64) -> Duration
{
72 Duration { secs: secs, nanos: 0 }
75 /// Creates a new `Duration` from the specified number of milliseconds.
76 #[stable(feature = "duration", since = "1.3.0")]
78 pub fn from_millis(millis
: u64) -> Duration
{
79 let secs
= millis
/ MILLIS_PER_SEC
;
80 let nanos
= ((millis
% MILLIS_PER_SEC
) as u32) * NANOS_PER_MILLI
;
81 Duration { secs: secs, nanos: nanos }
84 /// Returns the number of whole seconds represented by this duration.
86 /// The extra precision represented by this duration is ignored (i.e. extra
87 /// nanoseconds are not represented in the returned value).
88 #[stable(feature = "duration", since = "1.3.0")]
90 pub fn as_secs(&self) -> u64 { self.secs }
92 /// Returns the nanosecond precision represented by this duration.
94 /// This method does **not** return the length of the duration when
95 /// represented by nanoseconds. The returned number always represents a
96 /// fractional portion of a second (i.e. it is less than one billion).
97 #[stable(feature = "duration", since = "1.3.0")]
99 pub fn subsec_nanos(&self) -> u32 { self.nanos }
101 /// Checked duration addition. Computes `self + other`, returning `None`
102 /// if overflow occurred.
109 /// #![feature(duration_checked_ops)]
111 /// use std::time::Duration;
113 /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
114 /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
116 #[unstable(feature = "duration_checked_ops", issue = "35774")]
118 pub fn checked_add(self, rhs
: Duration
) -> Option
<Duration
> {
119 if let Some(mut secs
) = self.secs
.checked_add(rhs
.secs
) {
120 let mut nanos
= self.nanos
+ rhs
.nanos
;
121 if nanos
>= NANOS_PER_SEC
{
122 nanos
-= NANOS_PER_SEC
;
123 if let Some(new_secs
) = secs
.checked_add(1) {
129 debug_assert
!(nanos
< NANOS_PER_SEC
);
139 /// Checked duration subtraction. Computes `self + other`, returning `None`
140 /// if the result would be negative or if underflow occurred.
147 /// #![feature(duration_checked_ops)]
149 /// use std::time::Duration;
151 /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
152 /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
154 #[unstable(feature = "duration_checked_ops", issue = "35774")]
156 pub fn checked_sub(self, rhs
: Duration
) -> Option
<Duration
> {
157 if let Some(mut secs
) = self.secs
.checked_sub(rhs
.secs
) {
158 let nanos
= if self.nanos
>= rhs
.nanos
{
159 self.nanos
- rhs
.nanos
161 if let Some(sub_secs
) = secs
.checked_sub(1) {
163 self.nanos
+ NANOS_PER_SEC
- rhs
.nanos
168 debug_assert
!(nanos
< NANOS_PER_SEC
);
169 Some(Duration { secs: secs, nanos: nanos }
)
175 /// Checked duration multiplication. Computes `self * other`, returning
176 /// `None` if underflow or overflow occurred.
183 /// #![feature(duration_checked_ops)]
185 /// use std::time::Duration;
187 /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
188 /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
190 #[unstable(feature = "duration_checked_ops", issue = "35774")]
192 pub fn checked_mul(self, rhs
: u32) -> Option
<Duration
> {
193 // Multiply nanoseconds as u64, because it cannot overflow that way.
194 let total_nanos
= self.nanos
as u64 * rhs
as u64;
195 let extra_secs
= total_nanos
/ (NANOS_PER_SEC
as u64);
196 let nanos
= (total_nanos
% (NANOS_PER_SEC
as u64)) as u32;
197 if let Some(secs
) = self.secs
198 .checked_mul(rhs
as u64)
199 .and_then(|s
| s
.checked_add(extra_secs
)) {
200 debug_assert
!(nanos
< NANOS_PER_SEC
);
210 /// Checked duration division. Computes `self / other`, returning `None`
211 /// if `other == 0` or the operation results in underflow or overflow.
218 /// #![feature(duration_checked_ops)]
220 /// use std::time::Duration;
222 /// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
223 /// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
224 /// assert_eq!(Duration::new(2, 0).checked_div(0), None);
226 #[unstable(feature = "duration_checked_ops", issue = "35774")]
228 pub fn checked_div(self, rhs
: u32) -> Option
<Duration
> {
230 let secs
= self.secs
/ (rhs
as u64);
231 let carry
= self.secs
- secs
* (rhs
as u64);
232 let extra_nanos
= carry
* (NANOS_PER_SEC
as u64) / (rhs
as u64);
233 let nanos
= self.nanos
/ rhs
+ (extra_nanos
as u32);
234 debug_assert
!(nanos
< NANOS_PER_SEC
);
235 Some(Duration { secs: secs, nanos: nanos }
)
242 #[stable(feature = "duration", since = "1.3.0")]
243 impl Add
for Duration
{
244 type Output
= Duration
;
246 fn add(self, rhs
: Duration
) -> Duration
{
247 self.checked_add(rhs
).expect("overflow when adding durations")
251 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
252 impl AddAssign
for Duration
{
253 fn add_assign(&mut self, rhs
: Duration
) {
258 #[stable(feature = "duration", since = "1.3.0")]
259 impl Sub
for Duration
{
260 type Output
= Duration
;
262 fn sub(self, rhs
: Duration
) -> Duration
{
263 self.checked_sub(rhs
).expect("overflow when subtracting durations")
267 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
268 impl SubAssign
for Duration
{
269 fn sub_assign(&mut self, rhs
: Duration
) {
274 #[stable(feature = "duration", since = "1.3.0")]
275 impl Mul
<u32> for Duration
{
276 type Output
= Duration
;
278 fn mul(self, rhs
: u32) -> Duration
{
279 self.checked_mul(rhs
).expect("overflow when multiplying duration by scalar")
283 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
284 impl MulAssign
<u32> for Duration
{
285 fn mul_assign(&mut self, rhs
: u32) {
290 #[stable(feature = "duration", since = "1.3.0")]
291 impl Div
<u32> for Duration
{
292 type Output
= Duration
;
294 fn div(self, rhs
: u32) -> Duration
{
295 self.checked_div(rhs
).expect("divide by zero error when dividing duration by scalar")
299 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
300 impl DivAssign
<u32> for Duration
{
301 fn div_assign(&mut self, rhs
: u32) {
312 assert
!(Duration
::from_secs(1) != Duration
::from_secs(0));
313 assert_eq
!(Duration
::from_secs(1) + Duration
::from_secs(2),
314 Duration
::from_secs(3));
315 assert_eq
!(Duration
::from_millis(10) + Duration
::from_secs(4),
316 Duration
::new(4, 10 * 1_000_000));
317 assert_eq
!(Duration
::from_millis(4000), Duration
::new(4, 0));
322 assert_eq
!(Duration
::new(0, 0).as_secs(), 0);
323 assert_eq
!(Duration
::from_secs(1).as_secs(), 1);
324 assert_eq
!(Duration
::from_millis(999).as_secs(), 0);
325 assert_eq
!(Duration
::from_millis(1001).as_secs(), 1);
330 assert_eq
!(Duration
::new(0, 0).subsec_nanos(), 0);
331 assert_eq
!(Duration
::new(0, 5).subsec_nanos(), 5);
332 assert_eq
!(Duration
::new(0, 1_000_000_001).subsec_nanos(), 1);
333 assert_eq
!(Duration
::from_secs(1).subsec_nanos(), 0);
334 assert_eq
!(Duration
::from_millis(999).subsec_nanos(), 999 * 1_000_000);
335 assert_eq
!(Duration
::from_millis(1001).subsec_nanos(), 1 * 1_000_000);
340 assert_eq
!(Duration
::new(0, 0) + Duration
::new(0, 1),
341 Duration
::new(0, 1));
342 assert_eq
!(Duration
::new(0, 500_000_000) + Duration
::new(0, 500_000_001),
343 Duration
::new(1, 1));
348 assert_eq
!(Duration
::new(0, 0).checked_add(Duration
::new(0, 1)),
349 Some(Duration
::new(0, 1)));
350 assert_eq
!(Duration
::new(0, 500_000_000).checked_add(Duration
::new(0, 500_000_001)),
351 Some(Duration
::new(1, 1)));
352 assert_eq
!(Duration
::new(1, 0).checked_add(Duration
::new(::u64::MAX
, 0)), None
);
357 assert_eq
!(Duration
::new(0, 1) - Duration
::new(0, 0),
358 Duration
::new(0, 1));
359 assert_eq
!(Duration
::new(0, 500_000_001) - Duration
::new(0, 500_000_000),
360 Duration
::new(0, 1));
361 assert_eq
!(Duration
::new(1, 0) - Duration
::new(0, 1),
362 Duration
::new(0, 999_999_999));
367 let zero
= Duration
::new(0, 0);
368 let one_nano
= Duration
::new(0, 1);
369 let one_sec
= Duration
::new(1, 0);
370 assert_eq
!(one_nano
.checked_sub(zero
), Some(Duration
::new(0, 1)));
371 assert_eq
!(one_sec
.checked_sub(one_nano
),
372 Some(Duration
::new(0, 999_999_999)));
373 assert_eq
!(zero
.checked_sub(one_nano
), None
);
374 assert_eq
!(zero
.checked_sub(one_sec
), None
);
377 #[test] #[should_panic]
379 Duration
::new(0, 0) - Duration
::new(0, 1);
382 #[test] #[should_panic]
384 Duration
::new(0, 0) - Duration
::new(1, 0);
389 assert_eq
!(Duration
::new(0, 1) * 2, Duration
::new(0, 2));
390 assert_eq
!(Duration
::new(1, 1) * 3, Duration
::new(3, 3));
391 assert_eq
!(Duration
::new(0, 500_000_001) * 4, Duration
::new(2, 4));
392 assert_eq
!(Duration
::new(0, 500_000_001) * 4000,
393 Duration
::new(2000, 4000));
398 assert_eq
!(Duration
::new(0, 1).checked_mul(2), Some(Duration
::new(0, 2)));
399 assert_eq
!(Duration
::new(1, 1).checked_mul(3), Some(Duration
::new(3, 3)));
400 assert_eq
!(Duration
::new(0, 500_000_001).checked_mul(4), Some(Duration
::new(2, 4)));
401 assert_eq
!(Duration
::new(0, 500_000_001).checked_mul(4000),
402 Some(Duration
::new(2000, 4000)));
403 assert_eq
!(Duration
::new(::u64::MAX
- 1, 0).checked_mul(2), None
);
408 assert_eq
!(Duration
::new(0, 1) / 2, Duration
::new(0, 0));
409 assert_eq
!(Duration
::new(1, 1) / 3, Duration
::new(0, 333_333_333));
410 assert_eq
!(Duration
::new(99, 999_999_000) / 100,
411 Duration
::new(0, 999_999_990));
416 assert_eq
!(Duration
::new(2, 0).checked_div(2), Some(Duration
::new(1, 0)));
417 assert_eq
!(Duration
::new(1, 0).checked_div(2), Some(Duration
::new(0, 500_000_000)));
418 assert_eq
!(Duration
::new(2, 0).checked_div(0), None
);