2010-05-05 136 views
3

用户可以设置生日的提醒。 (我们不在乎出生年份) 他也会选择他是否希望在D日前的0天,1天,2天或者7天(三角洲)发出提醒。 用户有一个时区设置。Python中的周期性日期提醒

我希望服务器上午8时发送警报上的d日 - deleta + - 用户时区

例子:

6月12日,以“提醒我3天前”将给9 6月的

我的想法是在'recurrent event'对象上保存一个trigger_datetime额外的字段。 这样的一个cron我的服务器每小时运行的作业只会检查所有匹配当前时间小时,日期和月份的事件并发送到警报。

从一年到下一个问题trigger_date可能会改变! 如果警报设置在3月1日,延迟一天,可能是二月28日或29日..

也许我不应该使用触发日期技巧,并使用其他类型的计划。

所有的计划都欢迎。

回答

3

尽管使用普通的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本身,所以你需要重新计算它。上面的方法基本上可以即时计算提醒日期(和时间)。

我可以建议的另一件事是存储上次提醒已发送的日期(包括当年的生日)。因此,如果系统停机,您不会错过提醒,但会发送所有尚未发送的提醒。您需要修改代码才能进行额外的检查和更新。

0

你可以做两件事。

  1. Cron Job按小时,半小时或其他合适的频率触发应用程序。

  2. 该应用程序检查是否触发任何警报的时间。将这些警报添加到发送列表。向这些客户发送电子邮件提醒。

+0

这是我的第一个计划,但我认为如果我有50000警报(db)检查每个小时它将显然是低效率Vs只提取我知道我必须发送。 或者我应该做一个混合,并检查所有警报日间+7之间。 – coulix 2010-05-05 20:05:53

0

试试这样的事情。

选择从警报其中 日期(GETDATE(),GETDATE()+ 2,GETDATE()+ 5,GETDATE()+ 7) 和日期GETDATE()= alertFrequency

发送*提醒上述查询的所有结果

0

如何运行像

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

日常查询?

2

假设你不能使用existing library提供您所需要的Python标准库模块datetime特别是timedelta对象应该给你的原语来实现你需要的行为的功能:

from datetime import timedelta, date 
start_date = date(2010, 6, 12) 
notification_date = start_date + timedelta(days=365) - timedelta(days=3) 
print notification_date 

此代码片段打印:2011-06-09,timedelta也接受小时,所以你需要的精度是po ssible。您可以像上面定期展示的那样运行代码,查看是否有任何事件应该发送警报。在你的情况下,因为你甚至希望这种情况再次发生,你可以在启动警报时更新启动年,并将其设置为下一年。

+0

timedelta运作良好,但这不是我的问题。 我遇到的问题是我无法“预先”触发日期,因为它可能会从一年改变到另一年。 – coulix 2010-05-05 20:23:59

+1

该死! 只想到我没有想过要重新计算明年一旦被解雇...... 谢谢 – coulix 2010-05-05 20:48:53

+0

@coulix欢迎您。 – 2010-05-05 21:50:50