summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLowell Alleman <lowell@kintyre.co>2021-03-25 11:35:32 -0400
committerkiorky <kiorky@cryptelium.net>2021-04-07 17:01:14 +0200
commit8a83d37b6fe97c9dc74da2516d36d6047ef56155 (patch)
tree111847bef8d87d46d93a66cd4e06093394a35d99
parent9d3bbe81d2bea0d2361765855f3e0b11290bff5c (diff)
downloadcroniter-8a83d37b6fe97c9dc74da2516d36d6047ef56155.tar.gz
Refactoring
-rw-r--r--src/croniter/croniter.py60
-rwxr-xr-xsrc/croniter/tests/test_croniter.py33
2 files changed, 46 insertions, 47 deletions
diff --git a/src/croniter/croniter.py b/src/croniter/croniter.py
index 43f5ff5..0275061 100644
--- a/src/croniter/croniter.py
+++ b/src/croniter/croniter.py
@@ -131,13 +131,21 @@ class croniter(object):
def prep_expr(self, expr_format):
""" Intercept "<dow>L" entries in day-of-week and handle them specially.
Everything else is passed along as-is. Unpack / repack. """
- expressions = expr_format.split()
+ def handle_dow(day_of_week):
+ mo = re.match(r"^L([0-7])$", day_of_week, re.IGNORECASE)
+ if mo:
+ dow = int(mo.group(1)) % 7
+ self.last_weekday_of_month.add(dow)
+ # Last dow should always be either the 4 or 5th occurrence of that dow
+ return "L", "{dow}#4,{dow}#5".format(dow=dow)
+ return "other", day_of_week
+ expressions = expr_format.split()
# day of week field manipulations
found_types = set()
items = []
for dow in expressions[4].split(","):
- type_, dow = self.handle_dow(dow)
+ type_, dow = handle_dow(dow)
found_types.add(type_)
items.append(dow)
if len(found_types) > 1:
@@ -149,32 +157,6 @@ class croniter(object):
expr_format = " ".join(expressions)
return expr_format
- def handle_dow(self, day_of_week):
- mo = re.match(r"^L([0-7])$", day_of_week, re.IGNORECASE)
- if mo:
- dow = int(mo.group(1)) % 7
- self.last_weekday_of_month.add(dow)
- # Last dow should always be either the 4 or 5th occurrence of that dow
- return "L", "{dow}#4,{dow}#5".format(dow=dow)
- return "other", day_of_week
-
- @staticmethod
- def find_day_of_last_dow(timestamp, day_of_week):
- """ Given the year/month of timestamp, determine the last day of the
- month which is the day of the week. Calendar week starts on Sunday, to
- match cron day_of_week convention.
- """
- # How expensive is this? Easily cache by (year, month, dow)
- day_of_week = int(day_of_week)
- cal = calendar.Calendar(6).monthdayscalendar(timestamp.year, timestamp.month)
- week = -1
- while True:
- day = cal[week][day_of_week]
- if day == 0: # 0 means absent / different month
- week -= 1
- else:
- return day
-
@classmethod
def _alphaconv(cls, index, key, expressions):
try:
@@ -305,11 +287,12 @@ class croniter(object):
if self.last_weekday_of_month:
ts_dow = timestamp.isoweekday() % 7
if ts_dow in self.last_weekday_of_month:
- last_dow = self.find_day_of_last_dow(timestamp, ts_dow)
+ last_dow = self._get_last_weekday_of_month(
+ timestamp.year, timestamp.month, ts_dow)
return timestamp.day == last_dow
else:
# Have LDOM, but not for current day, return anyways???
- # Q: Can this still happen after blocking L/non-L missing in dow....
+ # Q: Can this still happen after blocking L/non-L mixing in dow?
return True
else:
# For all the other "normal" cron expression, no extra filter needed
@@ -612,6 +595,23 @@ class croniter(object):
return (candidate - x - range_val)
+ @staticmethod
+ def _get_last_weekday_of_month(year, month, day_of_week):
+ """ Given the year/month of timestamp, determine the last day of the
+ month which is a particular day of the week. Calendar week starts on
+ Sunday, to match cron's day_of_week convention.
+ """
+ # How expensive is this? Easily cache by (year, month, dow)
+ day_of_week = int(day_of_week)
+ cal = calendar.Calendar(6).monthdayscalendar(year, month)
+ week = -1
+ while True:
+ day = cal[week][day_of_week]
+ if day == 0: # 0 means absent / different month
+ week -= 1
+ else:
+ return day
+
def is_leap(self, year):
if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
return True
diff --git a/src/croniter/tests/test_croniter.py b/src/croniter/tests/test_croniter.py
index 3002a03..0948a5a 100755
--- a/src/croniter/tests/test_croniter.py
+++ b/src/croniter/tests/test_croniter.py
@@ -1102,27 +1102,26 @@ class CroniterTest(base.TestCase):
'2020-03-29T03:01:00+02:00'])
def test_last_wdom_simple(self):
- f = croniter.find_day_of_last_dow
+ f = croniter._get_last_weekday_of_month
sun, mon, tue, wed, thu, fri, sat = range(7)
- self.assertEqual(f(datetime(2021, 3, 6), sun), 28)
- self.assertEqual(f(datetime(2035, 12, 31), sat), 29)
- self.assertEqual(f(datetime(2000, 1, 1), fri), 28)
- self.assertEqual(f(datetime(2014, 8, 15), mon), 25)
- self.assertEqual(f(datetime(2022, 2, 19), tue), 22)
- self.assertEqual(f(datetime(1999, 10, 10), wed), 27)
- self.assertEqual(f(datetime(2005, 7, 19), thu), 28)
+ self.assertEqual(f(2021, 3, sun), 28)
+ self.assertEqual(f(2035, 12, sat), 29)
+ self.assertEqual(f(2000, 1, fri), 28)
+ self.assertEqual(f(2014, 8, mon), 25)
+ self.assertEqual(f(2022, 2, tue), 22)
+ self.assertEqual(f(1999, 10, wed), 27)
+ self.assertEqual(f(2005, 7, thu), 28)
def test_last_wdom_leap_year(self):
- f = croniter.find_day_of_last_dow
+ f = croniter._get_last_weekday_of_month
sun, mon, tue, wed, thu, fri, sat = range(7)
- self.assertEqual(f(datetime(2000, 2, 1), tue), 29)
- self.assertEqual(f(datetime(2000, 2, 10), tue), 29) # day doesn't matter
- self.assertEqual(f(datetime(2000, 2, 1), sun), 27)
- self.assertEqual(f(datetime(2000, 2, 1), mon), 28)
- self.assertEqual(f(datetime(2000, 2, 1), wed), 23)
- self.assertEqual(f(datetime(2000, 2, 1), thu), 24)
- self.assertEqual(f(datetime(2000, 2, 1), fri), 25)
- self.assertEqual(f(datetime(2000, 2, 1), sat), 26)
+ self.assertEqual(f(2000, 2, tue), 29)
+ self.assertEqual(f(2000, 2, sun), 27)
+ self.assertEqual(f(2000, 2, mon), 28)
+ self.assertEqual(f(2000, 2, wed), 23)
+ self.assertEqual(f(2000, 2, thu), 24)
+ self.assertEqual(f(2000, 2, fri), 25)
+ self.assertEqual(f(2000, 2, sat), 26)
def test_croniter_last_friday(self):
it = croniter("0 0 * * L5", datetime(1987, 1, 15), ret_type=datetime)