Хотя с помощью простого datetime
модуля Python вы сможете реализовать все, что вам нужно, доступно гораздо более мощное расширение python-dateutil , особенно если вам нужно работать с повторяющимися событиями. Код ниже должен дать вам представление о том, как достичь вашей цели:
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'
И я предлагаю вам не сохранять дату напоминания о следующем году, потому что delta
может измениться, или timezone
может измениться, и даже birthday
само по себе, так что вам придется пересчитать его. Приведенный выше метод в основном вычисляет дату и время напоминания на лету.
Еще одна вещь, которую я могу предложить - сохранить дату (день рождения, включая год) последнего напоминания. Таким образом, в случае простоя системы вы не пропустите напоминания, а отправите все, что не было отправлено. Вам нужно будет адаптировать код, чтобы выполнить дополнительную проверку и обновление.