66
66
len (SECOND_FIELDS ): SECOND_FIELDS ,
67
67
len (YEAR_FIELDS ): UNIX_FIELDS ,
68
68
}
69
- UNIX_CRON_LEN = 5
70
- SECOND_CRON_LEN = 6
71
- YEAR_CRON_LEN = 7
72
- VALID_LEN_EXPRESSION = set ([UNIX_CRON_LEN , SECOND_CRON_LEN ])
69
+ UNIX_CRON_LEN = len (UNIX_FIELDS )
70
+ SECOND_CRON_LEN = len (SECOND_FIELDS )
71
+ YEAR_CRON_LEN = len (YEAR_FIELDS )
72
+ # retrocompat
73
+ VALID_LEN_EXPRESSION = set ([a for a in CRON_FIELDS if isinstance (a , int )])
73
74
EXPRESSIONS = {}
74
75
75
76
@@ -295,20 +296,23 @@ def _get_next(self, ret_type=None, start_time=None, is_prev=None):
295
296
296
297
# exception to support day of month and day of week as defined in cron
297
298
dom_dow_exception_processed = False
298
- if (expanded [2 ][0 ] != '*' and expanded [4 ][0 ] != '*' ) and self ._day_or :
299
+ if (expanded [DAY_FIELD ][0 ] != '*' and expanded [DOW_FIELD ][0 ] != '*' ) and self ._day_or :
299
300
# If requested, handle a bug in vixie cron/ISC cron where day_of_month and day_of_week form
300
301
# an intersection (AND) instead of a union (OR) if either field is an asterisk or starts with an asterisk
301
302
# (https://crontab.guru/cron-bug.html)
302
- if self ._implement_cron_bug and (re_star .match (self .expressions [2 ]) or re_star .match (self .expressions [4 ])):
303
+ if (
304
+ self ._implement_cron_bug and
305
+ (re_star .match (self .expressions [DAY_FIELD ]) or re_star .match (self .expressions [DOW_FIELD ]))
306
+ ):
303
307
# To produce a schedule identical to the cron bug, we'll bypass the code that
304
308
# makes a union of DOM and DOW, and instead skip to the code that does an intersect instead
305
309
pass
306
310
else :
307
- bak = expanded [4 ]
308
- expanded [4 ] = ['*' ]
311
+ bak = expanded [DOW_FIELD ]
312
+ expanded [DOW_FIELD ] = ['*' ]
309
313
t1 = self ._calc (self .cur , expanded , nth_weekday_of_month , is_prev )
310
- expanded [4 ] = bak
311
- expanded [2 ] = ['*' ]
314
+ expanded [DOW_FIELD ] = bak
315
+ expanded [DAY_FIELD ] = ['*' ]
312
316
313
317
t2 = self ._calc (self .cur , expanded , nth_weekday_of_month , is_prev )
314
318
if not is_prev :
@@ -400,12 +404,12 @@ def _calc(self, now, expanded, nth_weekday_of_month, is_prev):
400
404
now = math .ceil (now )
401
405
nearest_diff_method = self ._get_prev_nearest_diff
402
406
sign = - 1
403
- offset = (len (expanded ) == 6 or now % 60 > 0 ) and 1 or 60
407
+ offset = (len (expanded ) > UNIX_CRON_LEN or now % 60 > 0 ) and 1 or 60
404
408
else :
405
409
now = math .floor (now )
406
410
nearest_diff_method = self ._get_next_nearest_diff
407
411
sign = 1
408
- offset = (len (expanded ) == 6 ) and 1 or 60
412
+ offset = (len (expanded ) > UNIX_CRON_LEN ) and 1 or 60
409
413
410
414
dst = now = self ._timestamp_to_datetime (now + sign * offset )
411
415
@@ -415,10 +419,10 @@ def _calc(self, now, expanded, nth_weekday_of_month, is_prev):
415
419
416
420
def proc_month (d ):
417
421
try :
418
- expanded [3 ].index ('*' )
422
+ expanded [MONTH_FIELD ].index ('*' )
419
423
except ValueError :
420
424
diff_month = nearest_diff_method (
421
- d .month , expanded [3 ], self .MONTHS_IN_YEAR )
425
+ d .month , expanded [MONTH_FIELD ], self .MONTHS_IN_YEAR )
422
426
days = DAYS [month - 1 ]
423
427
if month == 2 and self .is_leap (year ) is True :
424
428
days += 1
@@ -441,21 +445,21 @@ def proc_month(d):
441
445
442
446
def proc_day_of_month (d ):
443
447
try :
444
- expanded [2 ].index ('*' )
448
+ expanded [DAY_FIELD ].index ('*' )
445
449
except ValueError :
446
450
days = DAYS [month - 1 ]
447
451
if month == 2 and self .is_leap (year ) is True :
448
452
days += 1
449
- if 'l' in expanded [2 ] and days == d .day :
453
+ if 'l' in expanded [DAY_FIELD ] and days == d .day :
450
454
return False , d
451
455
452
456
if is_prev :
453
457
days_in_prev_month = DAYS [
454
458
(month - 2 ) % self .MONTHS_IN_YEAR ]
455
459
diff_day = nearest_diff_method (
456
- d .day , expanded [2 ], days_in_prev_month )
460
+ d .day , expanded [DAY_FIELD ], days_in_prev_month )
457
461
else :
458
- diff_day = nearest_diff_method (d .day , expanded [2 ], days )
462
+ diff_day = nearest_diff_method (d .day , expanded [DAY_FIELD ], days )
459
463
460
464
if diff_day is not None and diff_day != 0 :
461
465
if is_prev :
@@ -469,10 +473,10 @@ def proc_day_of_month(d):
469
473
470
474
def proc_day_of_week (d ):
471
475
try :
472
- expanded [4 ].index ('*' )
476
+ expanded [DOW_FIELD ].index ('*' )
473
477
except ValueError :
474
478
diff_day_of_week = nearest_diff_method (
475
- d .isoweekday () % 7 , expanded [4 ], 7 )
479
+ d .isoweekday () % 7 , expanded [DOW_FIELD ], 7 )
476
480
if diff_day_of_week is not None and diff_day_of_week != 0 :
477
481
if is_prev :
478
482
d += relativedelta (days = diff_day_of_week ,
@@ -535,9 +539,9 @@ def proc_day_of_week_nth(d):
535
539
536
540
def proc_hour (d ):
537
541
try :
538
- expanded [1 ].index ('*' )
542
+ expanded [HOUR_FIELD ].index ('*' )
539
543
except ValueError :
540
- diff_hour = nearest_diff_method (d .hour , expanded [1 ], 24 )
544
+ diff_hour = nearest_diff_method (d .hour , expanded [HOUR_FIELD ], 24 )
541
545
if diff_hour is not None and diff_hour != 0 :
542
546
if is_prev :
543
547
d += relativedelta (
@@ -549,9 +553,9 @@ def proc_hour(d):
549
553
550
554
def proc_minute (d ):
551
555
try :
552
- expanded [0 ].index ('*' )
556
+ expanded [MINUTE_FIELD ].index ('*' )
553
557
except ValueError :
554
- diff_min = nearest_diff_method (d .minute , expanded [0 ], 60 )
558
+ diff_min = nearest_diff_method (d .minute , expanded [MINUTE_FIELD ], 60 )
555
559
if diff_min is not None and diff_min != 0 :
556
560
if is_prev :
557
561
d += relativedelta (minutes = diff_min , second = 59 )
@@ -561,11 +565,11 @@ def proc_minute(d):
561
565
return False , d
562
566
563
567
def proc_second (d ):
564
- if len (expanded ) == 6 :
568
+ if len (expanded ) > UNIX_CRON_LEN :
565
569
try :
566
- expanded [5 ].index ('*' )
570
+ expanded [SECOND_FIELD ].index ('*' )
567
571
except ValueError :
568
- diff_sec = nearest_diff_method (d .second , expanded [5 ], 60 )
572
+ diff_sec = nearest_diff_method (d .second , expanded [SECOND_FIELD ], 60 )
569
573
if diff_sec is not None and diff_sec != 0 :
570
574
d += relativedelta (seconds = diff_sec )
571
575
return True , d
@@ -706,7 +710,7 @@ def _expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_time
706
710
raise CroniterBadCronError (
707
711
"[{0}] is not acceptable. Question mark can not "
708
712
"used with other characters" .format (expr_format ))
709
- if i not in [2 , 4 ]:
713
+ if i not in [DAY_FIELD , DOW_FIELD ]:
710
714
raise CroniterBadCronError (
711
715
"[{0}] is not acceptable. Question mark can only used "
712
716
"in day_of_month or day_of_week" .format (expr_format ))
@@ -720,7 +724,7 @@ def _expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_time
720
724
e = e_list .pop ()
721
725
nth = None
722
726
723
- if i == 4 :
727
+ if i == DOW_FIELD :
724
728
# Handle special case in the dow expression: 2#3, l3
725
729
special_dow_rem = special_dow_re .match (str (e ))
726
730
if special_dow_rem :
@@ -760,7 +764,7 @@ def _expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_time
760
764
# early abort if low/high are out of bounds
761
765
762
766
(low , high , step ) = m .group (1 ), m .group (2 ), m .group (4 ) or 1
763
- if i == 2 and high == 'l' :
767
+ if i == DAY_FIELD and high == 'l' :
764
768
high = '31'
765
769
766
770
if not only_int_re .search (low ):
@@ -773,7 +777,7 @@ def _expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_time
773
777
not low or not high or int (low ) > int (high )
774
778
or not only_int_re .search (str (step ))
775
779
):
776
- if i == 4 and high == '0' :
780
+ if i == DOW_FIELD and high == '0' :
777
781
# handle -Sun notation -> 7
778
782
high = '7'
779
783
else :
@@ -796,7 +800,7 @@ def _expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_time
796
800
raise CroniterBadCronError (
797
801
'invalid range: {0}' .format (exc ))
798
802
e_list += (["{0}#{1}" .format (item , nth ) for item in rng ]
799
- if i == 4 and nth and nth != "l" else rng )
803
+ if i == DOW_FIELD and nth and nth != "l" else rng )
800
804
else :
801
805
if t .startswith ('-' ):
802
806
raise CroniterBadCronError ((
@@ -831,7 +835,7 @@ def _expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_time
831
835
832
836
res .append (t )
833
837
834
- if i == 4 and nth :
838
+ if i == DOW_FIELD and nth :
835
839
if t not in nth_weekday_of_month :
836
840
nth_weekday_of_month [t ] = set ()
837
841
nth_weekday_of_month [t ].add (nth )
@@ -841,8 +845,8 @@ def _expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_time
841
845
if len (res ) == cls .LEN_MEANS_ALL [i ]:
842
846
# Make sure the wildcard is used in the correct way (avoid over-optimization)
843
847
if (
844
- (i == 2 and '*' not in expressions [4 ]) or
845
- (i == 4 and '*' not in expressions [2 ])
848
+ (i == DAY_FIELD and '*' not in expressions [DOW_FIELD ]) or
849
+ (i == DOW_FIELD and '*' not in expressions [DAY_FIELD ])
846
850
):
847
851
pass
848
852
else :
@@ -854,11 +858,11 @@ def _expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_time
854
858
855
859
# Check to make sure the dow combo in use is supported
856
860
if nth_weekday_of_month :
857
- dow_expanded_set = set (expanded [4 ])
861
+ dow_expanded_set = set (expanded [DOW_FIELD ])
858
862
dow_expanded_set = dow_expanded_set .difference (nth_weekday_of_month .keys ())
859
863
dow_expanded_set .discard ("*" )
860
864
# Skip: if it's all weeks instead of wildcard
861
- if dow_expanded_set and len (set (expanded [4 ])) != cls .LEN_MEANS_ALL [4 ]:
865
+ if dow_expanded_set and len (set (expanded [DOW_FIELD ])) != cls .LEN_MEANS_ALL [DOW_FIELD ]:
862
866
raise CroniterUnsupportedSyntaxError (
863
867
"day-of-week field does not support mixing literal values and nth day of week syntax. "
864
868
"Cron: '{}' dow={} vs nth={}" .format (expr_format , dow_expanded_set , nth_weekday_of_month ))
@@ -887,15 +891,15 @@ def expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_times
887
891
@classmethod
888
892
def _get_low_from_current_date_number (cls , i , step , from_timestamp ):
889
893
dt = datetime .datetime .fromtimestamp (from_timestamp , tz = datetime .timezone .utc )
890
- if i == 0 :
894
+ if i == MINUTE_FIELD :
891
895
return dt .minute % step
892
- if i == 1 :
896
+ if i == HOUR_FIELD :
893
897
return dt .hour % step
894
- if i == 2 :
898
+ if i == DAY_FIELD :
895
899
return ((dt .day - 1 ) % step ) + 1
896
- if i == 3 :
900
+ if i == MONTH_FIELD :
897
901
return dt .month % step
898
- if i == 4 :
902
+ if i == DOW_FIELD :
899
903
return (dt .weekday () + 1 ) % step
900
904
901
905
raise ValueError ("Can't get current date number for index larger than 4" )
0 commit comments