Skip to content

Commit

Permalink
Add an update_current argument to get_next/get_prev/all_next/all_pr…
Browse files Browse the repository at this point in the history
…ev (#84)

This fixes #83 .
  • Loading branch information
kiorky authored Jul 25, 2024
1 parent 2d31a52 commit 844e5fb
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 13 deletions.
3 changes: 1 addition & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ Changelog
3.0.1 (unreleased)
------------------

- Nothing changed yet.

- Add an `update_current` argument to get_next/get_prev/all_next/all_prev to facilitate writing of some downstream code, see #83. [kiorky]

3.0.0 (2024-07-23)
------------------
Expand Down
26 changes: 15 additions & 11 deletions src/croniter/croniter.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,13 @@ def _alphaconv(cls, index, key, expressions):
raise CroniterNotAlphaError(
"[{0}] is not acceptable".format(" ".join(expressions)))

def get_next(self, ret_type=None, start_time=None):
def get_next(self, ret_type=None, start_time=None, update_current=True):
if start_time and self._expand_from_start_time:
raise ValueError("start_time is not supported when using expand_from_start_time = True.")
self.set_current(start_time, force=True)
return self._get_next(ret_type or self._ret_type, is_prev=False)
return self._get_next(ret_type or self._ret_type, is_prev=False, update_current=update_current)

def get_prev(self, ret_type=None):
return self._get_next(ret_type or self._ret_type, is_prev=True)
def get_prev(self, ret_type=None, start_time=None, update_current=True):
return self._get_next(ret_type or self._ret_type, is_prev=True, update_current=update_current)

def get_current(self, ret_type=None):
ret_type = ret_type or self._ret_type
Expand Down Expand Up @@ -285,7 +284,9 @@ def _timedelta_to_seconds(cls, td):
"""
return timedelta_to_seconds(td)

def _get_next(self, ret_type=None, start_time=None, is_prev=None):
def _get_next(self, ret_type=None, start_time=None, is_prev=None, update_current=None):
if update_current is None:
update_current = True
self.set_current(start_time, force=True)
if is_prev is None:
is_prev = self._is_prev
Expand Down Expand Up @@ -360,7 +361,8 @@ def _get_next(self, ret_type=None, start_time=None, is_prev=None):
dtresult = dtresult_adjusted
result = result_adjusted
self.dst_start_time = result
self.cur = result
if update_current:
self.cur = result
if issubclass(ret_type, datetime.datetime):
result = dtresult
return result
Expand All @@ -369,7 +371,7 @@ def _get_next(self, ret_type=None, start_time=None, is_prev=None):
# objects in a loop, like "for dt in croniter('5 0 * * *'): ..."
# or for combining multiple croniters into single
# dates feed using 'itertools' module
def all_next(self, ret_type=None):
def all_next(self, ret_type=None, start_time=None, update_current=None):
'''Generator of all consecutive dates. Can be used instead of
implicit call to __iter__, whenever non-default
'ret_type' has to be specified.
Expand All @@ -378,19 +380,21 @@ def all_next(self, ret_type=None):
try:
while True:
self._is_prev = False
yield self._get_next(ret_type or self._ret_type)
yield self._get_next(ret_type or self._ret_type,
start_time=start_time, update_current=update_current)
except CroniterBadDateError:
if self._max_years_btw_matches_explicitly_set:
return
else:
raise

def all_prev(self, ret_type=None):
def all_prev(self, ret_type=None, start_time=None, update_current=None):
'''Generator of all previous dates.'''
try:
while True:
self._is_prev = True
yield self._get_next(ret_type or self._ret_type)
yield self._get_next(ret_type or self._ret_type,
start_time=start_time, update_current=update_current)
except CroniterBadDateError:
if self._max_years_btw_matches_explicitly_set:
return
Expand Down
66 changes: 66 additions & 0 deletions src/croniter/tests/test_croniter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1883,5 +1883,71 @@ def test_get_next_fails_with_expand_from_start_time_true(self):
self.assertRaises(ValueError, expanded_croniter.get_next, datetime, start_time=datetime(2024, 7, 12))


def test_get_next_update_current(self):
cron = croniter("* * * * * *")

cron.set_current(datetime(2024, 7, 12), force=True)
retn = [(cron.get_next(datetime), cron.get_current(datetime))
for a in range(3)]
self.assertEqual(
retn,
[(datetime(2024, 7, 12, 0, 0, 1), datetime(2024, 7, 12, 0, 0, 1)),
(datetime(2024, 7, 12, 0, 0, 2), datetime(2024, 7, 12, 0, 0, 2)),
(datetime(2024, 7, 12, 0, 0, 3), datetime(2024, 7, 12, 0, 0, 3))]
)

cron.set_current(datetime(2024, 7, 12), force=True)
retp = [(cron.get_prev(datetime), cron.get_current(datetime))
for a in range(3)]
self.assertEqual(
retp,
[(datetime(2024, 7, 11, 23, 59, 59), datetime(2024, 7, 11, 23, 59, 59)),
(datetime(2024, 7, 11, 23, 59, 58), datetime(2024, 7, 11, 23, 59, 58)),
(datetime(2024, 7, 11, 23, 59, 57), datetime(2024, 7, 11, 23, 59, 57))]
)

cron.set_current(datetime(2024, 7, 12), force=True)
r = cron.all_next(datetime)
retan = [(next(r), cron.get_current(datetime)) for a in range(3)]

cron.set_current(datetime(2024, 7, 12), force=True)
r = cron.all_prev(datetime)
retap = [(next(r), cron.get_current(datetime)) for a in range(3)]

self.assertEqual(retp, retap)
self.assertEqual(retn, retan)

cron.set_current(datetime(2024, 7, 12), force=True)
uretn = [(cron.get_next(datetime, update_current=False), cron.get_current(datetime))
for a in range(3)]
self.assertEqual(
uretn,
[(datetime(2024, 7, 12, 0, 0, 1), datetime(2024, 7, 12, 0, 0)),
(datetime(2024, 7, 12, 0, 0, 1), datetime(2024, 7, 12, 0, 0)),
(datetime(2024, 7, 12, 0, 0, 1), datetime(2024, 7, 12, 0, 0))]
)

cron.set_current(datetime(2024, 7, 12), force=True)
uretp = [(cron.get_prev(datetime, update_current=False), cron.get_current(datetime))
for a in range(3)]
self.assertEqual(
uretp,
[(datetime(2024, 7, 11, 23, 59, 59), datetime(2024, 7, 12, 0, 0)),
(datetime(2024, 7, 11, 23, 59, 59), datetime(2024, 7, 12, 0, 0)),
(datetime(2024, 7, 11, 23, 59, 59), datetime(2024, 7, 12, 0, 0))]
)

cron.set_current(datetime(2024, 7, 12), force=True)
r = cron.all_next(datetime, update_current=False)
uretan = [(next(r), cron.get_current(datetime)) for a in range(3)]

cron.set_current(datetime(2024, 7, 12), force=True)
r = cron.all_prev(datetime, update_current=False)
uretap = [(next(r), cron.get_current(datetime)) for a in range(3)]

self.assertEqual(uretp, uretap)
self.assertEqual(uretn, uretan)


if __name__ == '__main__':
unittest.main()

0 comments on commit 844e5fb

Please sign in to comment.