2010-05-05 139 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