2
2
//!
3
3
//! Requires the `time_trigger` feature.
4
4
5
- #[ cfg( test) ]
6
- use chrono:: NaiveDateTime ;
7
5
use chrono:: { DateTime , Datelike , Duration , Local , TimeZone , Timelike } ;
8
6
#[ cfg( test) ]
9
7
use mock_instant:: { SystemTime , UNIX_EPOCH } ;
@@ -13,11 +11,18 @@ use serde::de;
13
11
#[ cfg( feature = "config_parsing" ) ]
14
12
use std:: fmt;
15
13
use std:: sync:: RwLock ;
14
+ use thiserror:: Error ;
16
15
17
16
use crate :: append:: rolling_file:: { policy:: compound:: trigger:: Trigger , LogFile } ;
18
17
#[ cfg( feature = "config_parsing" ) ]
19
18
use crate :: config:: { Deserialize , Deserializers } ;
20
19
20
+ macro_rules! try_from {
21
+ ( $func: ident, $para: expr, $interval: expr) => {
22
+ Duration :: $func( $para) . ok_or( TimeTrigerError :: TooLargeInterval ( $interval) ) ?
23
+ } ;
24
+ }
25
+
21
26
#[ cfg( feature = "config_parsing" ) ]
22
27
/// Configuration for the time trigger.
23
28
#[ derive( Copy , Clone , Eq , PartialEq , Hash , Debug , Default , serde:: Deserialize ) ]
@@ -73,6 +78,12 @@ impl Default for TimeTriggerInterval {
73
78
}
74
79
}
75
80
81
+ #[ derive( Debug , Error ) ]
82
+ enum TimeTrigerError {
83
+ #[ error( "The integer value {0:?} for the specified time trigger interval is too large, it must be less than 9,223,372,036,854,775,807 seconds." ) ]
84
+ TooLargeInterval ( TimeTriggerInterval ) ,
85
+ }
86
+
76
87
#[ cfg( feature = "config_parsing" ) ]
77
88
impl < ' de > serde:: Deserialize < ' de > for TimeTriggerInterval {
78
89
fn deserialize < D > ( d : D ) -> Result < Self , D :: Error >
@@ -181,18 +192,22 @@ impl TimeTrigger {
181
192
let now: std:: time:: Duration = SystemTime :: now ( )
182
193
. duration_since ( UNIX_EPOCH )
183
194
. expect ( "system time before Unix epoch" ) ;
184
- NaiveDateTime :: from_timestamp_opt ( now. as_secs ( ) as i64 , now. subsec_nanos ( ) )
195
+ DateTime :: from_timestamp ( now. as_secs ( ) as i64 , now. subsec_nanos ( ) )
185
196
. unwrap ( )
197
+ . naive_local ( )
186
198
. and_local_timezone ( Local )
187
199
. unwrap ( )
188
200
} ;
189
201
190
202
#[ cfg( not( test) ) ]
191
203
let current = Local :: now ( ) ;
192
- let next_time = TimeTrigger :: get_next_time ( current, config. interval , config. modulate ) ;
204
+ let next_time =
205
+ TimeTrigger :: get_next_time ( current, config. interval , config. modulate ) . unwrap ( ) ;
193
206
let next_roll_time = if config. max_random_delay > 0 {
194
207
let random_delay = rand:: thread_rng ( ) . gen_range ( 0 ..config. max_random_delay ) ;
195
- next_time + Duration :: seconds ( random_delay as i64 )
208
+ next_time
209
+ + Duration :: try_seconds ( random_delay as i64 )
210
+ . unwrap_or ( Duration :: try_milliseconds ( i64:: MAX ) . unwrap ( ) )
196
211
} else {
197
212
next_time
198
213
} ;
@@ -207,13 +222,13 @@ impl TimeTrigger {
207
222
current : DateTime < Local > ,
208
223
interval : TimeTriggerInterval ,
209
224
modulate : bool ,
210
- ) -> DateTime < Local > {
225
+ ) -> Result < DateTime < Local > , TimeTrigerError > {
211
226
let year = current. year ( ) ;
212
227
if let TimeTriggerInterval :: Year ( n) = interval {
213
228
let n = n as i32 ;
214
229
let increment = if modulate { n - year % n } else { n } ;
215
230
let year_new = year + increment;
216
- return Local . with_ymd_and_hms ( year_new, 1 , 1 , 0 , 0 , 0 ) . unwrap ( ) ;
231
+ return Ok ( Local . with_ymd_and_hms ( year_new, 1 , 1 , 0 , 0 , 0 ) . unwrap ( ) ) ;
217
232
}
218
233
219
234
if let TimeTriggerInterval :: Month ( n) = interval {
@@ -224,9 +239,9 @@ impl TimeTrigger {
224
239
let num_months_new = num_months + increment;
225
240
let year_new = ( num_months_new / 12 ) as i32 ;
226
241
let month_new = ( num_months_new) % 12 + 1 ;
227
- return Local
242
+ return Ok ( Local
228
243
. with_ymd_and_hms ( year_new, month_new, 1 , 0 , 0 , 0 )
229
- . unwrap ( ) ;
244
+ . unwrap ( ) ) ;
230
245
}
231
246
232
247
let month = current. month ( ) ;
@@ -236,14 +251,17 @@ impl TimeTrigger {
236
251
let weekday = current. weekday ( ) . num_days_from_monday ( ) as i64 ; // Monday is the first day of the week
237
252
let time = Local . with_ymd_and_hms ( year, month, day, 0 , 0 , 0 ) . unwrap ( ) ;
238
253
let increment = if modulate { n - week0 % n } else { n } ;
239
- return time + Duration :: weeks ( increment) - Duration :: days ( weekday) ;
254
+ let dur =
255
+ try_from ! ( try_weeks, increment, interval) - try_from ! ( try_days, weekday, interval) ;
256
+ return Ok ( time + dur) ;
240
257
}
241
258
242
259
if let TimeTriggerInterval :: Day ( n) = interval {
243
260
let ordinal0 = current. ordinal0 ( ) as i64 ;
244
261
let time = Local . with_ymd_and_hms ( year, month, day, 0 , 0 , 0 ) . unwrap ( ) ;
245
262
let increment = if modulate { n - ordinal0 % n } else { n } ;
246
- return time + Duration :: days ( increment) ;
263
+ let dur = try_from ! ( try_days, increment, interval) ;
264
+ return Ok ( time + dur) ;
247
265
}
248
266
249
267
let hour = current. hour ( ) ;
@@ -252,7 +270,8 @@ impl TimeTrigger {
252
270
. with_ymd_and_hms ( year, month, day, hour, 0 , 0 )
253
271
. unwrap ( ) ;
254
272
let increment = if modulate { n - ( hour as i64 ) % n } else { n } ;
255
- return time + Duration :: hours ( increment) ;
273
+ let dur = try_from ! ( try_hours, increment, interval) ;
274
+ return Ok ( time + dur) ;
256
275
}
257
276
258
277
let min = current. minute ( ) ;
@@ -261,7 +280,8 @@ impl TimeTrigger {
261
280
. with_ymd_and_hms ( year, month, day, hour, min, 0 )
262
281
. unwrap ( ) ;
263
282
let increment = if modulate { n - ( min as i64 ) % n } else { n } ;
264
- return time + Duration :: minutes ( increment) ;
283
+ let dur = try_from ! ( try_minutes, increment, interval) ;
284
+ return Ok ( time + dur) ;
265
285
}
266
286
267
287
let sec = current. second ( ) ;
@@ -270,7 +290,8 @@ impl TimeTrigger {
270
290
. with_ymd_and_hms ( year, month, day, hour, min, sec)
271
291
. unwrap ( ) ;
272
292
let increment = if modulate { n - ( sec as i64 ) % n } else { n } ;
273
- return time + Duration :: seconds ( increment) ;
293
+ let dur = try_from ! ( try_seconds, increment, interval) ;
294
+ return Ok ( time + dur) ;
274
295
}
275
296
panic ! ( "Should not reach here!" ) ;
276
297
}
@@ -283,8 +304,9 @@ impl Trigger for TimeTrigger {
283
304
let now = SystemTime :: now ( )
284
305
. duration_since ( UNIX_EPOCH )
285
306
. expect ( "system time before Unix epoch" ) ;
286
- NaiveDateTime :: from_timestamp_opt ( now. as_secs ( ) as i64 , now. subsec_nanos ( ) )
307
+ DateTime :: from_timestamp ( now. as_secs ( ) as i64 , now. subsec_nanos ( ) )
287
308
. unwrap ( )
309
+ . naive_local ( )
288
310
. and_local_timezone ( Local )
289
311
. unwrap ( )
290
312
} ;
0 commit comments