Sunday, December 4, 2016

Finding All Cron Events Between Two Times With Python and Croniter

I've been playing around with the idea of a discrete event simulator for a while but I needed a clear way to specify when events will occur,  particularly recurring ones.  In situations like this I try to use standards that already exist, so the cron format seemed ideal.  The goal is to supply a start and end time with a cron string and have all the events in between automatically generate and with the help of the croniter package this a relatively painless process.

I've thrown together a quick demonstration of how I intend to use the package including using datetime objects with timezones attached.  I'm not sure if I'll eventually use timezones or not but I wanted to make sure I knew how it worked.

The example below calculates all the cron events that occur in December 2016.  In this case cron events occur at 8 am on Monday, Tuesday and Thursday.

from croniter import croniter
from datetime import datetime
import pytz

simulation_timezone = pytz.timezone('Australia/Brisbane')
simulation_start_time = simulation_timezone.localize(datetime
                                                     (2016, 12, 1, 0, 0, 0))
simulation_end_time = simulation_timezone.localize(datetime
                                                   (2016, 12, 31, 23, 59, 59))

cron_iterator = croniter('00 8 * * 1-2,4', simulation_start_time)

print("---------start time---------")
print(simulation_start_time)
print(simulation_start_time.timestamp())
print("-----------events-----------")

while True:
    next_event = cron_iterator.get_next(datetime)
    if next_event > simulation_end_time:
        break
    print(next_event)
    print(next_event.timestamp())

print("----------end time----------")
print(simulation_end_time)
print(simulation_end_time.timestamp())
print("----------------------------")

You start by defining a base time, in this case it is simulation_start_time.  A croniter iterator can then be declared.  This is done by supplying a cron string and a base time.  You can now step forward and backward through events with the get_next and get_prev methods.  These return a float or a datetime object depending on what type you pass as an argument.

---------start time---------
2016-12-01 00:00:00+10:00
1480514400.0
-----------events-----------
2016-12-01 08:00:00+10:00
1480543200.0
2016-12-05 08:00:00+10:00
1480888800.0
2016-12-06 08:00:00+10:00
1480975200.0
2016-12-08 08:00:00+10:00
1481148000.0
2016-12-12 08:00:00+10:00
1481493600.0
2016-12-13 08:00:00+10:00
1481580000.0
2016-12-15 08:00:00+10:00
1481752800.0
2016-12-19 08:00:00+10:00
1482098400.0
2016-12-20 08:00:00+10:00
1482184800.0
2016-12-22 08:00:00+10:00
1482357600.0
2016-12-26 08:00:00+10:00
1482703200.0
2016-12-27 08:00:00+10:00
1482789600.0
2016-12-29 08:00:00+10:00
1482962400.0
----------end time----------
2016-12-31 23:59:59+10:00
1483192799.0
----------------------------

By stepping through events until the end time, all events are found.  I'm still working on making everything more readable and clearer for the end user, but this gets me 90% of the way there.

No comments:

Post a Comment