@@ -2,6 +2,7 @@ use std::{
22 io:: { Read , Write } ,
33 mem:: MaybeUninit ,
44 ops:: { Add , Sub } ,
5+ time:: Duration ,
56} ;
67
78/// A timestamp relative to `CLOCK_BOOTTIME`.
@@ -51,85 +52,47 @@ impl SystemTime {
5152 i64:: from_ne_bytes ( nsec_bytes) ,
5253 ) )
5354 }
54- }
55-
56- impl Sub < SystemTime > for SystemTime {
57- type Output = Duration ;
58-
59- fn sub ( self , rhs : SystemTime ) -> Self :: Output {
60- Duration :: new ( self . secs - rhs. secs , self . nsecs - rhs. nsecs )
61- }
62- }
63-
64- impl Add < Duration > for SystemTime {
65- type Output = SystemTime ;
66-
67- fn add ( self , rhs : Duration ) -> Self :: Output {
68- SystemTime :: new ( self . secs + rhs. secs , self . nsecs + rhs. nsecs )
69- }
70- }
71-
72- impl Sub < Duration > for SystemTime {
73- type Output = SystemTime ;
7455
75- fn sub ( self , rhs : Duration ) -> Self :: Output {
76- SystemTime :: new ( self . secs - rhs. secs , self . nsecs - rhs . nsecs )
77- }
78- }
56+ # [ inline ]
57+ pub fn checked_add ( self , rhs : Duration ) -> Option < SystemTime > {
58+ let rhs_secs = rhs . as_nanos ( ) . div_euclid ( 1_000_000_000 ) . try_into ( ) . ok ( ) ? ;
59+ let rhs_nsecs = rhs . as_nanos ( ) . rem_euclid ( 1_000_000_000 ) . try_into ( ) . ok ( ) ? ;
7960
80- #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Clone , Copy ) ]
81- pub struct Duration {
82- secs : i64 ,
83- nsecs : i64 ,
84- }
61+ let secs = self . secs . checked_add ( rhs_secs) ?;
62+ let nsecs = self . nsecs . checked_add ( rhs_nsecs) ?;
8563
86- impl Duration {
87- pub fn new ( secs : i64 , nsecs : i64 ) -> Duration {
88- Duration {
89- secs : secs + nsecs. div_euclid ( 1_000_000_000 ) ,
90- nsecs : nsecs. rem_euclid ( 1_000_000_000 ) ,
91- }
64+ Some ( SystemTime :: new ( secs, nsecs) )
9265 }
9366
94- pub fn seconds ( secs : i64 ) -> Duration {
95- Duration :: new ( secs, 0 )
96- }
67+ #[ inline]
68+ pub fn checked_sub ( self , rhs : Duration ) -> Option < SystemTime > {
69+ let rhs_secs = rhs. as_nanos ( ) . div_euclid ( 1_000_000_000 ) . try_into ( ) . ok ( ) ?;
70+ let rhs_nsecs = rhs. as_nanos ( ) . rem_euclid ( 1_000_000_000 ) . try_into ( ) . ok ( ) ?;
9771
98- #[ cfg( test) ]
99- pub fn minutes ( minutes : i64 ) -> Duration {
100- Duration :: seconds ( minutes * 60 )
101- }
72+ let secs = self . secs . checked_sub ( rhs_secs) ?;
73+ let nsecs = self . nsecs . checked_sub ( rhs_nsecs) ?;
10274
103- #[ cfg( test) ]
104- pub fn milliseconds ( ms : i64 ) -> Duration {
105- let secs = ms / 1000 ;
106- let ms = ms % 1000 ;
107- Duration :: new ( secs, ms * 1_000_000 )
75+ Some ( SystemTime :: new ( secs, nsecs) )
10876 }
10977}
11078
111- impl Add < Duration > for Duration {
112- type Output = Duration ;
79+ impl Add < Duration > for SystemTime {
80+ type Output = SystemTime ;
11381
82+ #[ inline]
11483 fn add ( self , rhs : Duration ) -> Self :: Output {
115- Duration :: new ( self . secs + rhs. secs , self . nsecs + rhs. nsecs )
84+ self . checked_add ( rhs)
85+ . expect ( "overflow when adding duration" )
11686 }
11787}
11888
119- impl Sub < Duration > for Duration {
120- type Output = Duration ;
89+ impl Sub < Duration > for SystemTime {
90+ type Output = SystemTime ;
12191
92+ #[ inline]
12293 fn sub ( self , rhs : Duration ) -> Self :: Output {
123- Duration :: new ( self . secs - rhs. secs , self . nsecs - rhs. nsecs )
124- }
125- }
126-
127- impl From < Duration > for std:: time:: Duration {
128- fn from ( dur : Duration ) -> std:: time:: Duration {
129- std:: time:: Duration :: new (
130- dur. secs . try_into ( ) . unwrap_or ( 0 ) ,
131- dur. nsecs . try_into ( ) . unwrap_or ( 0 ) ,
132- )
94+ self . checked_sub ( rhs)
95+ . expect ( "overflow when subtracting duration" )
13396 }
13497}
13598
@@ -213,13 +176,7 @@ mod tests {
213176 use super :: * ;
214177
215178 #[ test]
216- fn test_new_durations_and_times ( ) {
217- assert_eq ! ( Duration :: new( 1 , 1_000_000_000 ) , Duration :: seconds( 2 ) ) ;
218- assert_eq ! (
219- Duration :: new( -2 , 500_000_000 ) ,
220- Duration :: seconds( -1 ) + Duration :: milliseconds( -500 )
221- ) ;
222-
179+ fn test_new_system_time ( ) {
223180 assert_eq ! ( SystemTime :: new( -1 , 2_000_000_000 ) , SystemTime :: new( 1 , 0 ) ) ;
224181 assert_eq ! (
225182 SystemTime :: new( 2 , -500_000_000 ) ,
@@ -230,37 +187,20 @@ mod tests {
230187 #[ test]
231188 fn test_time_ops ( ) {
232189 assert_eq ! (
233- Duration :: seconds( 2 ) + Duration :: seconds( 3 ) ,
234- Duration :: seconds( 5 )
235- ) ;
236- assert_eq ! (
237- Duration :: seconds( 3 ) - Duration :: seconds( 1 ) ,
238- Duration :: seconds( 2 )
239- ) ;
240- assert_eq ! (
241- Duration :: seconds( -10 ) + Duration :: seconds( -5 ) ,
242- Duration :: seconds( -15 )
243- ) ;
244- assert_eq ! (
245- Duration :: milliseconds( 5555 ) + Duration :: milliseconds( 5555 ) ,
246- Duration :: seconds( 11 ) + Duration :: milliseconds( 110 )
247- ) ;
248- assert_eq ! (
249- Duration :: milliseconds( -5555 ) + Duration :: milliseconds( -1111 ) ,
250- Duration :: milliseconds( -6666 )
251- ) ;
252- assert_eq ! (
253- Duration :: seconds( 10 ) - Duration :: seconds( -5 ) ,
254- Duration :: seconds( 15 )
190+ SystemTime :: new( 0 , 0 ) + Duration :: from_secs( 3 ) ,
191+ SystemTime :: new( 3 , 0 )
255192 ) ;
256-
257193 assert_eq ! (
258- SystemTime :: new( 0 , 0 ) + Duration :: seconds ( 3 ) ,
194+ SystemTime :: new( 0 , 500_000_000 ) + Duration :: from_nanos ( 2_500_000_000 ) ,
259195 SystemTime :: new( 3 , 0 )
260196 ) ;
261197 assert_eq ! (
262- SystemTime :: new( 10 , 0 ) - Duration :: seconds ( 4 ) ,
198+ SystemTime :: new( 10 , 0 ) - Duration :: from_secs ( 4 ) ,
263199 SystemTime :: new( 6 , 0 )
264200 ) ;
201+ assert_eq ! (
202+ SystemTime :: new( 10 , 0 ) - Duration :: from_nanos( 3_500_000_000 ) ,
203+ SystemTime :: new( 6 , 500_000_000 )
204+ ) ;
265205 }
266206}
0 commit comments