views:

80

answers:

5

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.

A: 

You can do it in two parts.

  1. Cron Job that triggers the application hourly,halfhourly or some other suitable frequency.

  2. The Application checks if its time for any alerts to be triggered. Adds those alerts to a sending list. Sends email alerts to those customers.

anijhaw
That was my first plan but i thought that if i had 50000 alerts (db) to check every hour it would be clearly inefficient Vs fetching only the one i know i have to send.Or i should do a mix and check all alerts between Day to Day + 7.
coulix
A: 

Try out something like this.

Select * from alerts where date in (GetDate(), GetDate()+2, GetDATE()+5, GETDATE()+7) and date-GetDate() =alertFrequency

Send the alerts to all the results of the above query

Sundararajan S
A: 

How about running a query like

SELECT `user` FROM `mytable` WHERE now() >= (`birthday` - INTERVAL `delta` DAY);

daily?

Fletcher Moore
+2  A: 

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.

Tendayi Mawushe
timedelta works well but that is not my problem.The problem i have is that i can not 'precaculte' the trigger date cause it may change from one year to the other.
coulix
Damn !THe only think i didnt thought about was to recalculate it for next year once fired ....Thanks
coulix
@coulix you are welcome.
Tendayi Mawushe
+2  A: 

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.

van