From f79fe83f490bdfbfcff14ffec72e3a7b985d2837 Mon Sep 17 00:00:00 2001 From: Lukasz Janyst Date: Thu, 23 Nov 2017 15:44:30 +0100 Subject: [PATCH 01/12] Add support for parsing of interval definitions --- schedule/__init__.py | 111 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/schedule/__init__.py b/schedule/__init__.py index 89ff3b1f..ba1dec48 100644 --- a/schedule/__init__.py +++ b/schedule/__init__.py @@ -127,6 +127,21 @@ def every(self, interval=1): job = Job(interval, self) return job + def when(self, interval_definition): + """ + Schedule a new periodic job. + + :param interval_definition: See :meth:`Job.when `. + :return: A partially configured :class:`Job ` + """ + job = Job(1, self) + try: + job.when(interval_definition) + except Exception: + self.cancel_job(job) + raise + return job + def _run_job(self, job): ret = job.run() if isinstance(ret, CancelJob) or ret is CancelJob: @@ -181,6 +196,7 @@ def __init__(self, interval, scheduler=None): self.start_day = None # Specific day of the week to start on self.tags = set() # unique set of tags for the job self.scheduler = scheduler # scheduler to register with + self.directive_map = None # map of directive names to function calls def __lt__(self, other): """ @@ -391,6 +407,94 @@ def do(self, job_func, *args, **kwargs): self.scheduler.jobs.append(self) return self + def _build_directive_map(self): + """ + Build a map of directive names to function calls for the parser + """ + if self.directive_map is not None: + return + + # a list of valid directives + directive_names = ['second', 'seconds', 'minute', 'minutes', 'hour', + 'hours', 'day', 'days', 'week', 'weeks', 'monday', + 'tuesday', 'wednesday', 'thursday', 'friday', + 'saturday', 'sunday', 'at', 'to'] + + # get an appropriate setter reference + def get_attr(obj, attr): + for obj in [obj] + obj.__class__.mro(): + if attr in obj.__dict__: + ret = obj.__dict__[attr] + if isinstance(ret, property): + return lambda x: ret.__get__(x, type(x)) + return ret + + # build the dictionary of properties + self.directive_map = {} + for d in directive_names: + self.directive_map[d] = get_attr(self, d) + + def when(self, interval_definition): + """ + Schedule a job according to an interval definition. The definition + is a string that is the same as a sequence of method calls, except + that dots and parentheses are replaced with spaces. For example: + `when('every monday at 17:51')`. + + :param interval_definition: the interval definition + :return: The invoked job instance + """ + directives = interval_definition.lower().split() + assert len(directives) >= 2, 'definition too short' + assert directives[0] == 'every', \ + 'the definition must start with "every"' + + # set up the interval if necessary + try: + interval = int(directives[1]) + self.interval = interval + assert len(directives) >= 3, "definition to short" + directives = directives[2:] + except ValueError: + directives = directives[1:] + + # parse the definition + self._build_directive_map() + directives.reverse() + while directives: + directive = directives.pop() + assert directive in self.directive_map, \ + 'unknown directive: '+directive + + args = [] + + # check the argument to "to" + if directive == 'to': + arg = directives.pop() + try: + arg = int(arg) + except ValueError: + assert False, 'the "to" directive expects an integer' + args.append(arg) + + # check the argument to "at" + elif directive == 'at': + arg = directives.pop() + arg_split = arg.split(':') + assert len(arg_split) == 2, \ + 'the "at" directive expects a string like "12:34"' + try: + int(arg_split[0]) + int(arg_split[1]) + except ValueError: + assert False, \ + 'the "at" directive expects a string like "12:34"' + args.append(arg) + + # call the setter function + self.directive_map[directive](self, *args) + return self + @property def should_run(self): """ @@ -483,6 +587,13 @@ def every(interval=1): return default_scheduler.every(interval) +def when(interval_definition): + """Calls :meth:`when ` on the + :data:`default scheduler instance `. + """ + return default_scheduler.when(interval_definition) + + def run_pending(): """Calls :meth:`run_pending ` on the :data:`default scheduler instance `. From ef6ae36bf4fc1f38ee934d937dc022f807594bf1 Mon Sep 17 00:00:00 2001 From: Lukasz Janyst Date: Thu, 23 Nov 2017 15:48:43 +0100 Subject: [PATCH 02/12] Test parsing of interval definitions --- test_schedule.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test_schedule.py b/test_schedule.py index 139745ff..e4294c88 100644 --- a/test_schedule.py +++ b/test_schedule.py @@ -9,7 +9,7 @@ # pylint: disable-msg=R0201,C0111,E0102,R0904,R0901 import schedule -from schedule import every +from schedule import every, when def make_mock_job(name=None): @@ -121,6 +121,27 @@ def test_next_run_time(self): assert every().saturday.do(mock_job).next_run.day == 9 assert every().sunday.do(mock_job).next_run.day == 10 + def test_when(self): + mock_job = make_mock_job() + + invalid_definitions = ['', 'foo bar', 'every 2', 'every 2 foobar', + 'every 2 to foo days', 'every monday at foo', + 'every monday at foo:bar'] + valid_definitions = ['every 2 days', 'every 3 to 5 days', + 'every monday at 17:51'] + + for definition in invalid_definitions: + try: + when(definition).do(mock_job) + assert False, "Invalid definition should not be parsed" + except Exception: + pass + + for definition in valid_definitions: + when(definition).do(mock_job) + + when('every 2 days').when('every 2 days').do(mock_job) + def test_run_all(self): mock_job = make_mock_job() every().minute.do(mock_job) From 0d08f595c4333cbc43d294d083a0e77b7c279b79 Mon Sep 17 00:00:00 2001 From: Lukasz Janyst Date: Thu, 23 Nov 2017 15:49:32 +0100 Subject: [PATCH 03/12] Add interval definition parsing to the docs --- AUTHORS.rst | 1 + README.rst | 2 ++ docs/api.rst | 1 + docs/index.rst | 2 ++ 4 files changed, 6 insertions(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index 05864c8b..648e0f31 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -15,3 +15,4 @@ Thanks to all the wonderful folks who have contributed to schedule over the year - schnepp - grampajoe - gilbsgilbs +- ljanyst diff --git a/README.rst b/README.rst index 2725f294..94048b7c 100644 --- a/README.rst +++ b/README.rst @@ -48,6 +48,8 @@ Usage schedule.every(5).to(10).minutes.do(job) schedule.every().monday.do(job) schedule.every().wednesday.at("13:15").do(job) + schedule.when('every wednesday at 13:15').do(job) + schedule.when('every 15 seconds').do(job) while True: schedule.run_pending() diff --git a/docs/api.rst b/docs/api.rst index 4add1b4c..62c7eda2 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -16,6 +16,7 @@ Main Interface .. autodata:: jobs .. autofunction:: every +.. autofunction:: when .. autofunction:: run_pending .. autofunction:: run_all .. autofunction:: clear diff --git a/docs/index.rst b/docs/index.rst index 5507b731..e8004386 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -47,6 +47,8 @@ Usage schedule.every().day.at("10:30").do(job) schedule.every().monday.do(job) schedule.every().wednesday.at("13:15").do(job) + schedule.when('every wednesday at 13:15').do(job) + schedule.when('every 15 seconds').do(job) while True: schedule.run_pending() From 02dedc457e4c0e1ed7edc8d1c43ce09441a1be52 Mon Sep 17 00:00:00 2001 From: Taha Jahangir Date: Sun, 11 Mar 2018 15:35:09 +0330 Subject: [PATCH 04/12] Feature to specify seconds in HH:MM:SS format in `at` --- schedule/__init__.py | 12 +++++++++--- test_schedule.py | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/schedule/__init__.py b/schedule/__init__.py index 89ff3b1f..50354b13 100644 --- a/schedule/__init__.py +++ b/schedule/__init__.py @@ -338,19 +338,25 @@ def at(self, time_str): Calling this is only valid for jobs scheduled to run every N day(s). - :param time_str: A string in `XX:YY` format. + :param time_str: A string in `HH:MM` or `HH:MM:SS` format. :return: The invoked job instance """ assert self.unit in ('days', 'hours') or self.start_day - hour, minute = time_str.split(':') + parts = time_str.split(':') + assert 1 < len(parts) < 4, '`XX:YY` or `XX:YY:ZZ` format expected' + if len(parts) == 2: + parts.append(0) + hour, minute, second = parts minute = int(minute) + second = int(second) if self.unit == 'days' or self.start_day: hour = int(hour) assert 0 <= hour <= 23 elif self.unit == 'hours': hour = 0 assert 0 <= minute <= 59 - self.at_time = datetime.time(hour, minute) + assert 0 <= second <= 59 + self.at_time = datetime.time(hour, minute, second) return self def to(self, latest): diff --git a/test_schedule.py b/test_schedule.py index 139745ff..f7f19e8e 100644 --- a/test_schedule.py +++ b/test_schedule.py @@ -91,6 +91,8 @@ def test_at_time(self): mock_job = make_mock_job() assert every().day.at('10:30').do(mock_job).next_run.hour == 10 assert every().day.at('10:30').do(mock_job).next_run.minute == 30 + assert every().day.at('10:30').do(mock_job).next_run.second == 0 + assert every().day.at('10:30:20').do(mock_job).next_run.second == 20 def test_at_time_hour(self): with mock_datetime(2010, 1, 6, 12, 20): From a39888332646b197fbc1a9fabb56c84b7541c3ce Mon Sep 17 00:00:00 2001 From: Steve Arnold Date: Fri, 9 Nov 2018 12:59:00 -0800 Subject: [PATCH 05/12] schedule: make datetime objs timezone-aware and UTC default * fix mock now() and tests with a timezone * allow flake8-max-line-length to be 90 * fixes for lack of datetime.timezone in python 2.7 (simple UTC) Signed-off-by: Steve Arnold --- schedule/__init__.py | 22 +++++++++++++++------- schedule/timezone.py | 18 ++++++++++++++++++ test_schedule.py | 15 ++++++++++++--- tox.ini | 3 +++ 4 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 schedule/timezone.py diff --git a/schedule/__init__.py b/schedule/__init__.py index 45a6f1d2..b67cd787 100644 --- a/schedule/__init__.py +++ b/schedule/__init__.py @@ -44,6 +44,14 @@ import random import time +try: + from datetime import timezone + utc = timezone.utc +except ImportError: + from schedule.timezone import UTC + utc = UTC() + + logger = logging.getLogger('schedule') @@ -149,7 +157,7 @@ def idle_seconds(self): :return: Number of seconds until :meth:`next_run `. """ - return (self.next_run - datetime.datetime.now()).total_seconds() + return (self.next_run - datetime.datetime.now(utc)).total_seconds() class Job(object): @@ -191,7 +199,7 @@ def __lt__(self, other): def __repr__(self): def format_time(t): - return t.strftime('%Y-%m-%d %H:%M:%S') if t else '[never]' + return t.strftime('%Y-%m-%d %H:%M:%S %Z') if t else '[never]' timestats = '(last run: %s, next run: %s)' % ( format_time(self.last_run), format_time(self.next_run)) @@ -396,7 +404,7 @@ def should_run(self): """ :return: ``True`` if the job should be run now. """ - return datetime.datetime.now() >= self.next_run + return datetime.datetime.now(utc) >= self.next_run def run(self): """ @@ -406,7 +414,7 @@ def run(self): """ logger.info('Running job %s', self) ret = self.job_func() - self.last_run = datetime.datetime.now() + self.last_run = datetime.datetime.now(utc) self._schedule_next_run() return ret @@ -423,7 +431,7 @@ def _schedule_next_run(self): interval = self.interval self.period = datetime.timedelta(**{self.unit: interval}) - self.next_run = datetime.datetime.now() + self.period + self.next_run = datetime.datetime.now(utc) + self.period if self.start_day is not None: assert self.unit == 'weeks' weekdays = ( @@ -454,7 +462,7 @@ def _schedule_next_run(self): # If we are running for the first time, make sure we run # at the specified time *today* (or *this hour*) as well if not self.last_run: - now = datetime.datetime.now() + now = datetime.datetime.now(utc) if (self.unit == 'days' and self.at_time > now.time() and self.interval == 1): self.next_run = self.next_run - datetime.timedelta(days=1) @@ -462,7 +470,7 @@ def _schedule_next_run(self): self.next_run = self.next_run - datetime.timedelta(hours=1) if self.start_day is not None and self.at_time is not None: # Let's see if we will still make that time we specified today - if (self.next_run - datetime.datetime.now()).days >= 7: + if (self.next_run - datetime.datetime.now(utc)).days >= 7: self.next_run -= self.period diff --git a/schedule/timezone.py b/schedule/timezone.py new file mode 100644 index 00000000..042ed529 --- /dev/null +++ b/schedule/timezone.py @@ -0,0 +1,18 @@ +import datetime + + +class UTC(datetime.tzinfo): + """tzinfo derived concrete class named "UTC" with offset of 0""" + # can be configured here + _offset = datetime.timedelta(seconds=0) + _dst = datetime.timedelta(0) + _name = "UTC" + + def utcoffset(self, dt): + return self.__class__._offset + + def dst(self, dt): + return self.__class__._dst + + def tzname(self, dt): + return self.__class__._name diff --git a/test_schedule.py b/test_schedule.py index 139745ff..e94cf1a7 100644 --- a/test_schedule.py +++ b/test_schedule.py @@ -11,6 +11,13 @@ import schedule from schedule import every +try: + from datetime import timezone + utc = timezone.utc +except ImportError: + from schedule.timezone import UTC + utc = UTC() + def make_mock_job(name=None): job = mock.Mock() @@ -36,9 +43,10 @@ def today(cls): return cls(self.year, self.month, self.day) @classmethod - def now(cls): + def now(cls, tz=None): return cls(self.year, self.month, self.day, - self.hour, self.minute) + self.hour, self.minute).replace(tzinfo=tz) + self.original_datetime = datetime.datetime datetime.datetime = MockDate @@ -258,7 +266,8 @@ def test_next_run_property(self): every().hour.do(hourly_job) assert len(schedule.jobs) == 2 # Make sure the hourly job is first - assert schedule.next_run() == original_datetime(2010, 1, 6, 14, 16) + assert schedule.next_run() == original_datetime(2010, 1, 6, 14, 16, + tzinfo=utc) assert schedule.idle_seconds() == 60 * 60 def test_cancel_job(self): diff --git a/tox.ini b/tox.ini index 932d656b..43b26127 100644 --- a/tox.ini +++ b/tox.ini @@ -6,6 +6,9 @@ envlist = py27, py36, docs 3.5 = py35, docs 3.6 = py36, docs +[flake8] +max-line-length = 90 + [testenv] deps = -rrequirements-dev.txt commands = From 76483ceeb5843a8f6d8a0a7800b1c990ff481573 Mon Sep 17 00:00:00 2001 From: Steve Arnold Date: Tue, 13 Nov 2018 09:48:07 -0800 Subject: [PATCH 06/12] Update utc class and add tests for the new code Signed-off-by: Steve Arnold --- schedule/timezone.py | 15 ++++++++------- test_schedule.py | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/schedule/timezone.py b/schedule/timezone.py index 042ed529..1530e389 100644 --- a/schedule/timezone.py +++ b/schedule/timezone.py @@ -3,16 +3,17 @@ class UTC(datetime.tzinfo): """tzinfo derived concrete class named "UTC" with offset of 0""" - # can be configured here - _offset = datetime.timedelta(seconds=0) - _dst = datetime.timedelta(0) - _name = "UTC" + # can be changed to another timezone name/offset + def __init__(self): + self.__offset = datetime.timedelta(seconds=0) + self.__dst = datetime.timedelta(0) + self.__name = "UTC" def utcoffset(self, dt): - return self.__class__._offset + return self.__offset def dst(self, dt): - return self.__class__._dst + return self.__dst def tzname(self, dt): - return self.__class__._name + return self.__name diff --git a/test_schedule.py b/test_schedule.py index e94cf1a7..82a863b2 100644 --- a/test_schedule.py +++ b/test_schedule.py @@ -1,4 +1,5 @@ """Unit tests for schedule.py""" +import sys import datetime import functools import mock @@ -72,6 +73,22 @@ def test_singular_time_units_match_plural_units(self): assert every().day.unit == every().days.unit assert every().week.unit == every().weeks.unit + def test_utc_is_normal(self): + fo = utc + self.assertIsInstance(fo, datetime.tzinfo) + dt = datetime.datetime.now() + self.assertEqual(fo.utcoffset(dt), datetime.timedelta(0)) + self.assertEqual(fo.tzname(dt), "UTC") + + def test_utc_dst_is_dt(self): + fo = utc + dt = datetime.datetime.now() + if sys.version_info > (3, 0, 0): + dst_arg = None + else: + dst_arg = datetime.timedelta(0) + self.assertEqual(fo.dst(dt), dst_arg) + def test_time_range(self): with mock_datetime(2014, 6, 28, 12, 0): mock_job = make_mock_job() From ca710a67625d156ad56603d0789a021db1507542 Mon Sep 17 00:00:00 2001 From: Walter Antolini Date: Sun, 25 Nov 2018 01:47:41 +0100 Subject: [PATCH 07/12] Manual merge pull request #148 --- schedule/__init__.py | 19 +++++++++++++++++++ setup.py | 2 +- test_schedule.py | 19 ++++++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/schedule/__init__.py b/schedule/__init__.py index 7f973ffd..998fba3a 100644 --- a/schedule/__init__.py +++ b/schedule/__init__.py @@ -648,3 +648,22 @@ def idle_seconds(): :data:`default scheduler instance `. """ return default_scheduler.idle_seconds + + +def repeat(job): + """Decorator for scheduled functions/methods. The decorated + functions/methods should not accept any arguments. + Usage: + >>> from schedule import every, repeat + >>> import schedule + >>> import time + >>> @repeat(every(10).minutes) + >>> def job(): + >>> print("I am a scheduled job") + >>> while True: + >>> schedule.run_pending() + >>> time.sleep(1)""" + def _inner_decorator(decorated_function): + job.do(decorated_function) + return decorated_function + return _inner_decorator diff --git a/setup.py b/setup.py index f6ae20d4..00974f1a 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ from setuptools import setup -SCHEDULE_VERSION = '0.5.0' +SCHEDULE_VERSION = '0.5.1' SCHEDULE_DOWNLOAD_URL = ( 'https://github.com/dbader/schedule/tarball/' + SCHEDULE_VERSION ) diff --git a/test_schedule.py b/test_schedule.py index a7363b93..b0c8f30a 100644 --- a/test_schedule.py +++ b/test_schedule.py @@ -10,7 +10,7 @@ # pylint: disable-msg=R0201,C0111,E0102,R0904,R0901 import schedule -from schedule import every, when +from schedule import every, when, repeat try: from datetime import timezone @@ -177,6 +177,23 @@ def test_run_all(self): schedule.run_all() assert mock_job.call_count == 3 + def test_run_all_with_decorator(self): + mock_job = make_mock_job() + + @repeat(every().minute) + def _job1(): + mock_job() + + @repeat(every().hour) + def _job2(): + mock_job() + + @repeat(every().day.at('11:00')) + def _job3(): + mock_job() + schedule.run_all() + assert mock_job.call_count == 3 + def test_job_func_args_are_passed_on(self): mock_job = make_mock_job() every().second.do(mock_job, 1, 2, 'three', foo=23, bar={}) From a58a3d1811453dca17d0c0f3953ae776061425b6 Mon Sep 17 00:00:00 2001 From: Walter Antolini Date: Sun, 25 Nov 2018 02:14:57 +0100 Subject: [PATCH 08/12] Updated AUTHORS.rst --- AUTHORS.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index 648e0f31..08e4ae97 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -16,3 +16,5 @@ Thanks to all the wonderful folks who have contributed to schedule over the year - grampajoe - gilbsgilbs - ljanyst +- antwal + From b0c2d7baabd407fe6fac605ccb598d1c8a7c1470 Mon Sep 17 00:00:00 2001 From: Walter Antolini Date: Sun, 25 Nov 2018 02:42:46 +0100 Subject: [PATCH 09/12] Updated Docs for pull request #148, #179 --- FAQ.rst | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- docs/index.rst | 2 -- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/FAQ.rst b/FAQ.rst index 2712fbb9..b391b7ef 100644 --- a/FAQ.rst +++ b/FAQ.rst @@ -216,4 +216,52 @@ How can I pass arguments to the job function? print('Hello', name) schedule.every(2).seconds.do(greet, name='Alice') - schedule.every(4).seconds.do(greet, name='Bob') + schedule.every(4).seconds.do(greet, name='Bob') + +How to run a job with decorator? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + from schedule import every, repeat + import schedule + import time + + @repeat(every(1).minutes) + def job_a(): + print("Called function job_a()") + + @repeat(every(15).seconds) + def job_b(): + print("Called function job_b()") + + while True: + schedule.run_pending() + time.sleep(1) + +How to run a job with string interval definitions? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + import threading + from schedule import when + import schedule + import time + + def run_threaded(job_func): + job_thread = threading.Thread(target=job_func) + job_thread.start() + + def job_a(): + print("Called function job_a()") + + def job_b(): + print("Called function job_b()") + + schedule.when('every 15 seconds').do(run_threaded, job_a) + schedule.when('every 1 minute').do(run_threaded, job_b) + + while True: + schedule.run_pending() + time.sleep(1) diff --git a/docs/index.rst b/docs/index.rst index e8004386..5507b731 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -47,8 +47,6 @@ Usage schedule.every().day.at("10:30").do(job) schedule.every().monday.do(job) schedule.every().wednesday.at("13:15").do(job) - schedule.when('every wednesday at 13:15').do(job) - schedule.when('every 15 seconds').do(job) while True: schedule.run_pending() From ce8fe79aa972c5247062019e3eaa66bec8ed8913 Mon Sep 17 00:00:00 2001 From: Walter Antolini Date: Sun, 25 Nov 2018 02:44:21 +0100 Subject: [PATCH 10/12] Updated README --- README.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.rst b/README.rst index d1494bc1..693c60d1 100644 --- a/README.rst +++ b/README.rst @@ -48,8 +48,6 @@ Usage schedule.every(5).to(10).minutes.do(job) schedule.every().monday.do(job) schedule.every().wednesday.at("13:15").do(job) - schedule.when('every wednesday at 13:15').do(job) - schedule.when('every 15 seconds').do(job) while True: schedule.run_pending() From 59ffb7088f719c0d1f16ab96a7eaed9ea88d02f7 Mon Sep 17 00:00:00 2001 From: Walter Antolini Date: Sun, 25 Nov 2018 13:47:21 +0100 Subject: [PATCH 11/12] Updated Docs for pull request #205 --- docs/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 5507b731..a93ad41b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -44,9 +44,9 @@ Usage schedule.every(10).minutes.do(job) schedule.every().hour.do(job) - schedule.every().day.at("10:30").do(job) + schedule.every().day.at("10:30:00").do(job) schedule.every().monday.do(job) - schedule.every().wednesday.at("13:15").do(job) + schedule.every().wednesday.at("13:15:20").do(job) while True: schedule.run_pending() From 5608c5c92f3ff8056850b5bc98572d3253a62735 Mon Sep 17 00:00:00 2001 From: Walter Antolini Date: Sun, 25 Nov 2018 13:54:32 +0100 Subject: [PATCH 12/12] Updated README --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 693c60d1..07a0a000 100644 --- a/README.rst +++ b/README.rst @@ -44,10 +44,10 @@ Usage schedule.every(10).minutes.do(job) schedule.every().hour.do(job) - schedule.every().day.at("10:30").do(job) + schedule.every().day.at("10:30:00").do(job) schedule.every(5).to(10).minutes.do(job) schedule.every().monday.do(job) - schedule.every().wednesday.at("13:15").do(job) + schedule.every().wednesday.at("13:15:20").do(job) while True: schedule.run_pending()