A user can set a day alert for a birthday. (We do not care about the year of birth) He also picks if he wants to be alerted 0, 1, 2, ou 7 days (Delta) before the D day. Users have a timezone setting.
I want the server to send the alerts at 8 am on the the D day - deleta +- user timezone
Example:
12 jun, with "alert me 3 days before" will give 9 of Jun.
My idea was to have a trigger_datetime extra field saved on the 'recurrent event' object. Like this a cron Job running every hour on my server will just check for all events matching irs current time hour, day and month and send to the alert.
The problem from a year to the next the trigger_date could change ! If the alert is set on 1st of March, with a one day delay that could be either 28 or 29 of February ..
Maybe i should not use the trigger date trick and use some other kind of scheme.
All plans are welcome.
Although using plain datetime python module you will be able to implement all you need, a much more powerful python-dateutil extension is available, especially if you need to work with recurring events. The code below should give you an indication of how to achieve your goal:
from datetime import *
from dateutil.rrule import rrule, YEARLY
# GLOBAL CONFIG
td_8am = timedelta(seconds=3600*8)
td_jobfrequency = timedelta(seconds=3600) # hourly job
# USER DATA::
# birthday: assumed to be retrieved from some data source
bday = date(1960, 5, 12)
# reminder delta: number of days before the b-day
td_delta = timedelta(days=6)
# difference between the user TZ and the server TZ
tz_diff = timedelta(seconds=3600*5) # example: +5h
# from current time minus the job periodicity and the delta
sday = date.today()
# occr will return the first birthday from today on
occr = rrule(YEARLY, bymonth=bday.month, bymonthday=bday.day, dtstart=sday, count=1)[0]
# adjust: subtract the reminder delta, fixed 8h (8am) and tz difference
occr -= (td_delta + td_8am + tz_diff)
# send the reminder when the adjusted occurance is within this job time period
if datetime.now() - td_jobfrequency < occr < datetime.now():
print occr, '@todo: send the reminder'
else:
print occr, 'no reminder'
And I suggest that you do not store the next year reminder date, because the delta may change, or timezone may change, and even birthday itself, so you would need to recompute it. The method above basically computes the reminder date (and time) on the fly.
One more thing I can suggest is to store for which date (birthday including the year) the last reminder has been sent. So if there is a system downtime you would not miss the reminders but send all that have not been sent. You will need to adapt the code to have this additional check and update.
Assuming you cannot use an existing library to provide the functionality you require the Python standard library module datetime in particular the timedelta object should give you the primitives to implement the behaviour you need:
from datetime import timedelta, date
start_date = date(2010, 6, 12)
notification_date = start_date + timedelta(days=365) - timedelta(days=3)
print notification_date
This code snippet prints: 2011-06-09, timedelta also accepts hours so the precision you require is possible. You could run code like I have shown above on a regular basis on all your events to see if any of them should send an alert. In your case since you want this even to recur you could just update the start year when the alert is fired setting it up for the next year.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With