diff --git a/.gitignore b/.gitignore index e403a912..c4f37115 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ build/ dist/ *.egg-info/ .tox/ +.env/ +.idea/ \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 03b67a06..c526b410 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ click==4.0 redis==2.10.5 structlog==15.1.0 +croniter==0.3.17 \ No newline at end of file diff --git a/setup.py b/setup.py index bed79906..d6e40a5a 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,10 @@ install_requires = [ 'click', 'redis', - 'structlog' + 'structlog', + 'croniter', + 'pytz', + 'tzlocal', ] tests_require = install_requires + [ diff --git a/tasktiger/schedule.py b/tasktiger/schedule.py index 4ef44fdf..39f46af1 100644 --- a/tasktiger/schedule.py +++ b/tasktiger/schedule.py @@ -1,6 +1,9 @@ import datetime +import pytz +import tzlocal +import croniter -__all__ = ['periodic'] +__all__ = ['periodic', 'cron_expr'] def _periodic(dt, period, start_date, end_date): if end_date and dt >= end_date: @@ -39,3 +42,16 @@ def periodic(seconds=0, minutes=0, hours=0, days=0, weeks=0, start_date=None, # Saturday at midnight start_date = datetime.datetime(2000, 1, 1) return (_periodic, (period, start_date, end_date)) + +def _cron_expr(naive_utc_dt, expr): + aware_utc_dt = pytz.utc.localize(naive_utc_dt) + local_timezone = tzlocal.get_localzone() + local_dt = aware_utc_dt.astimezone(local_timezone) + local_dt = local_timezone.normalize(local_dt) + next_dt = croniter.croniter(expr, start_time=local_dt).get_next(ret_type=datetime.datetime) + next_utc = next_dt.astimezone(pytz.utc) + next_utc = pytz.utc.normalize(next_utc) + return next_utc + +def cron_expr(expr_format): + return _cron_expr, (expr_format, )