1
1
//! Holiday hours metadata parsing and evaluation logic
2
2
3
+ #[ allow( deprecated) ]
3
4
use {
4
5
super :: legacy_schedule:: {
5
6
LegacySchedule ,
19
20
chrono_tz:: Tz ,
20
21
std:: {
21
22
fmt:: Display ,
23
+ ops:: RangeInclusive ,
22
24
str:: FromStr ,
23
25
} ,
24
26
winnow:: {
@@ -129,6 +131,7 @@ impl FromStr for MarketSchedule {
129
131
}
130
132
}
131
133
134
+ #[ allow( deprecated) ]
132
135
impl From < LegacySchedule > for MarketSchedule {
133
136
fn from ( legacy : LegacySchedule ) -> Self {
134
137
Self {
@@ -190,19 +193,19 @@ impl Display for HolidayDaySchedule {
190
193
}
191
194
}
192
195
193
- #[ derive( Clone , Debug , Eq , PartialEq , Copy ) ]
196
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
194
197
pub enum ScheduleDayKind {
195
198
Open ,
196
199
Closed ,
197
- TimeRange ( NaiveTime , NaiveTime ) ,
200
+ TimeRanges ( Vec < RangeInclusive < NaiveTime > > ) ,
198
201
}
199
202
200
203
impl ScheduleDayKind {
201
204
pub fn can_publish_at ( & self , when_local : NaiveTime ) -> bool {
202
205
match self {
203
206
Self :: Open => true ,
204
207
Self :: Closed => false ,
205
- Self :: TimeRange ( start , end ) => start <= & when_local && & when_local <= end ,
208
+ Self :: TimeRanges ( ranges ) => ranges . iter ( ) . any ( |range| range . contains ( & when_local) ) ,
206
209
}
207
210
}
208
211
}
@@ -218,8 +221,20 @@ impl Display for ScheduleDayKind {
218
221
match self {
219
222
Self :: Open => write ! ( f, "O" ) ,
220
223
Self :: Closed => write ! ( f, "C" ) ,
221
- Self :: TimeRange ( start, end) => {
222
- write ! ( f, "{}-{}" , start. format( "%H%M" ) , end. format( "%H%M" ) )
224
+ Self :: TimeRanges ( ranges) => {
225
+ let mut ranges = ranges. iter ( ) . peekable ( ) ;
226
+ while let Some ( range) = ranges. next ( ) {
227
+ write ! (
228
+ f,
229
+ "{}-{}" ,
230
+ range. start( ) . format( "%H%M" ) ,
231
+ range. end( ) . format( "%H%M" )
232
+ ) ?;
233
+ if ranges. peek ( ) . is_some ( ) {
234
+ write ! ( f, "&" ) ?;
235
+ }
236
+ }
237
+ Ok ( ( ) )
223
238
}
224
239
}
225
240
}
@@ -234,21 +249,21 @@ fn time_parser<'s>(input: &mut &'s str) -> PResult<NaiveTime> {
234
249
. parse_next ( input)
235
250
}
236
251
237
- fn time_range_parser < ' s > ( input : & mut & ' s str ) -> PResult < ScheduleDayKind > {
252
+ fn time_range_parser < ' s > ( input : & mut & ' s str ) -> PResult < RangeInclusive < NaiveTime > > {
238
253
seq ! (
239
254
time_parser,
240
255
_: "-" ,
241
256
time_parser,
242
257
)
243
- . map ( |s| ScheduleDayKind :: TimeRange ( s. 0 , s. 1 ) )
258
+ . map ( |s| s. 0 ..= s. 1 )
244
259
. parse_next ( input)
245
260
}
246
261
247
262
fn schedule_day_kind_parser < ' s > ( input : & mut & ' s str ) -> PResult < ScheduleDayKind > {
248
263
alt ( (
249
264
"C" . map ( |_| ScheduleDayKind :: Closed ) ,
250
265
"O" . map ( |_| ScheduleDayKind :: Open ) ,
251
- time_range_parser,
266
+ separated ( 1 .. , time_range_parser, "&" ) . map ( ScheduleDayKind :: TimeRanges ) ,
252
267
) )
253
268
. parse_next ( input)
254
269
}
@@ -267,7 +282,7 @@ impl From<MHKind> for ScheduleDayKind {
267
282
match mhkind {
268
283
MHKind :: Open => ScheduleDayKind :: Open ,
269
284
MHKind :: Closed => ScheduleDayKind :: Closed ,
270
- MHKind :: TimeRange ( start, end) => ScheduleDayKind :: TimeRange ( start, end) ,
285
+ MHKind :: TimeRange ( start, end) => ScheduleDayKind :: TimeRanges ( vec ! [ start..= end] ) ,
271
286
}
272
287
}
273
288
}
@@ -290,6 +305,7 @@ mod tests {
290
305
let open = "O" ;
291
306
let closed = "C" ;
292
307
let valid = "1234-1347" ;
308
+ let valid_double = "1234-1347&1400-1500" ;
293
309
let valid2400 = "1234-2400" ;
294
310
let invalid = "1234-5668" ;
295
311
let invalid_format = "1234-56" ;
@@ -304,17 +320,25 @@ mod tests {
304
320
) ;
305
321
assert_eq ! (
306
322
valid. parse:: <ScheduleDayKind >( ) . unwrap( ) ,
307
- ScheduleDayKind :: TimeRange (
308
- NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( ) ,
309
- NaiveTime :: from_hms_opt( 13 , 47 , 0 ) . unwrap( ) ,
310
- )
323
+ ScheduleDayKind :: TimeRanges ( vec![
324
+ NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( )
325
+ ..=NaiveTime :: from_hms_opt( 13 , 47 , 0 ) . unwrap( )
326
+ ] )
327
+ ) ;
328
+ assert_eq ! (
329
+ valid_double. parse:: <ScheduleDayKind >( ) . unwrap( ) ,
330
+ ScheduleDayKind :: TimeRanges ( vec![
331
+ NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( )
332
+ ..=NaiveTime :: from_hms_opt( 13 , 47 , 0 ) . unwrap( ) ,
333
+ NaiveTime :: from_hms_opt( 14 , 0 , 0 ) . unwrap( )
334
+ ..=NaiveTime :: from_hms_opt( 15 , 0 , 0 ) . unwrap( ) ,
335
+ ] )
311
336
) ;
312
337
assert_eq ! (
313
338
valid2400. parse:: <ScheduleDayKind >( ) . unwrap( ) ,
314
- ScheduleDayKind :: TimeRange (
315
- NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( ) ,
316
- MAX_TIME_INSTANT ,
317
- )
339
+ ScheduleDayKind :: TimeRanges ( vec![
340
+ NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( ) ..=MAX_TIME_INSTANT
341
+ ] )
318
342
) ;
319
343
assert ! ( invalid. parse:: <ScheduleDayKind >( ) . is_err( ) ) ;
320
344
assert ! ( invalid_format. parse:: <ScheduleDayKind >( ) . is_err( ) ) ;
@@ -347,10 +371,10 @@ mod tests {
347
371
let expected = HolidayDaySchedule {
348
372
month : 04 ,
349
373
day : 12 ,
350
- kind : ScheduleDayKind :: TimeRange (
351
- NaiveTime :: from_hms_opt ( 12 , 34 , 0 ) . unwrap ( ) ,
352
- NaiveTime :: from_hms_opt ( 13 , 47 , 0 ) . unwrap ( ) ,
353
- ) ,
374
+ kind : ScheduleDayKind :: TimeRanges ( vec ! [
375
+ NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( )
376
+ ..= NaiveTime :: from_hms_opt( 13 , 47 , 0 ) . unwrap( ) ,
377
+ ] ) ,
354
378
} ;
355
379
let parsed = input. parse :: < HolidayDaySchedule > ( ) ?;
356
380
assert_eq ! ( parsed, expected) ;
@@ -371,14 +395,13 @@ mod tests {
371
395
timezone : Tz :: America__New_York ,
372
396
weekly_schedule : vec ! [
373
397
ScheduleDayKind :: Open ,
374
- ScheduleDayKind :: TimeRange (
375
- NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( ) ,
376
- NaiveTime :: from_hms_opt( 13 , 47 , 0 ) . unwrap( ) ,
377
- ) ,
378
- ScheduleDayKind :: TimeRange (
379
- NaiveTime :: from_hms_opt( 09 , 30 , 0 ) . unwrap( ) ,
380
- MAX_TIME_INSTANT ,
381
- ) ,
398
+ ScheduleDayKind :: TimeRanges ( vec![
399
+ NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( )
400
+ ..=NaiveTime :: from_hms_opt( 13 , 47 , 0 ) . unwrap( ) ,
401
+ ] ) ,
402
+ ScheduleDayKind :: TimeRanges ( vec![
403
+ NaiveTime :: from_hms_opt( 09 , 30 , 0 ) . unwrap( ) ..=MAX_TIME_INSTANT ,
404
+ ] ) ,
382
405
ScheduleDayKind :: Closed ,
383
406
ScheduleDayKind :: Closed ,
384
407
ScheduleDayKind :: Closed ,
@@ -398,18 +421,17 @@ mod tests {
398
421
HolidayDaySchedule {
399
422
month: 04 ,
400
423
day: 14 ,
401
- kind: ScheduleDayKind :: TimeRange (
402
- NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( ) ,
403
- NaiveTime :: from_hms_opt( 13 , 47 , 0 ) . unwrap( ) ,
404
- ) ,
424
+ kind: ScheduleDayKind :: TimeRanges ( vec! [
425
+ NaiveTime :: from_hms_opt( 12 , 34 , 0 ) . unwrap( )
426
+ ..= NaiveTime :: from_hms_opt( 13 , 47 , 0 ) . unwrap( ) ,
427
+ ] ) ,
405
428
} ,
406
429
HolidayDaySchedule {
407
430
month: 12 ,
408
431
day: 30 ,
409
- kind: ScheduleDayKind :: TimeRange (
410
- NaiveTime :: from_hms_opt( 09 , 30 , 0 ) . unwrap( ) ,
411
- MAX_TIME_INSTANT ,
412
- ) ,
432
+ kind: ScheduleDayKind :: TimeRanges ( vec![
433
+ NaiveTime :: from_hms_opt( 09 , 30 , 0 ) . unwrap( ) ..=MAX_TIME_INSTANT ,
434
+ ] ) ,
413
435
} ,
414
436
] ,
415
437
} ;
@@ -476,18 +498,24 @@ mod tests {
476
498
}
477
499
478
500
prop_compose ! {
479
- fn schedule_day_kind( ) (
480
- r in any:: <u8 >( ) ,
501
+ fn time_range( ) (
481
502
t1 in any:: <u32 >( ) ,
482
503
t2 in any:: <u32 >( ) ,
504
+ ) -> RangeInclusive <NaiveTime > {
505
+ NaiveTime :: from_hms_opt( t1 % 24 , t1 / 24 % 60 , 0 ) . unwrap( ) ..=
506
+ NaiveTime :: from_hms_opt( t2 % 24 , t2 / 24 % 60 , 0 ) . unwrap( )
507
+ }
508
+ }
509
+
510
+ prop_compose ! {
511
+ fn schedule_day_kind( ) (
512
+ r in any:: <u8 >( ) ,
513
+ ranges in proptest:: collection:: vec( time_range( ) , 1 ..3 ) ,
483
514
) -> ScheduleDayKind {
484
515
match r % 3 {
485
516
0 => ScheduleDayKind :: Open ,
486
517
1 => ScheduleDayKind :: Closed ,
487
- _ => ScheduleDayKind :: TimeRange (
488
- NaiveTime :: from_hms_opt( t1 % 24 , t1 / 24 % 60 , 0 ) . unwrap( ) ,
489
- NaiveTime :: from_hms_opt( t2 % 24 , t2 / 24 % 60 , 0 ) . unwrap( ) ,
490
- ) ,
518
+ _ => ScheduleDayKind :: TimeRanges ( ranges) ,
491
519
}
492
520
}
493
521
}
0 commit comments