2014-01-15 51 views
1

我正在使用vobject在Django中創建一個ical事件。我在較低級別的代碼中遇到問題。看起來ical正試圖抓住一個時區obj.add(TimezoneComponent(tzinfo=getTzid(tzid)))。但後來我從pytz得到raise NonExistentTimeError(dt)。有什麼建議做什麼?年,月,日顯示正確,因爲我用變量start1中的print語句查看它們。Django ical與pytz的Vobject問題

File "/home/git/chrono/chrono/requests_app/views.py", line 110, in form_valid 
    ics_form = create_ics(data) 
    File "/home/git/chrono/chrono/requests_app/views.py", line 126, in create_ics 
    response = HttpResponse(cal.serialize(), content_type='text/calendar') 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/base.py", line 186, in serialize 
    return behavior.serialize(self, buf, lineLength, validate) 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/behavior.py", line 147, in serialize 
    cls.generateImplicitParameters(obj) 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/icalendar.py", line 853, in generateImplicitParameters 
    obj.add(TimezoneComponent(tzinfo=getTzid(tzid))) 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/icalendar.py", line 75, in __init__ 
    self.tzinfo = tzinfo 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/base.py", line 468, in __setattr__ 
    prop.fset(self, value) 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/icalendar.py", line 145, in settzinfo 
    transition = getTransition(transitionTo, year, tzinfo) 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/icalendar.py", line 1856, in getTransition 
    uncorrected = firstTransition(generateDates(year, month, day), test) 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/icalendar.py", line 1816, in firstTransition 
    if not test(dt): 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/vobject/icalendar.py", line 1843, in test 
    def test(dt): return tzinfo.dst(dt) != zeroDelta 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/pytz/tzinfo.py", line 445, in dst 
    dt = self.localize(dt, is_dst) 
    File "/home/one/.virtualenvs/chronos/local/lib/python2.7/site-packages/pytz/tzinfo.py", line 327, in localize 
    raise NonExistentTimeError(dt) 
NonExistentTimeError: 2000-04-02 02:00:00 



def create_ics(data): 
    start1 = data['date_due'] 
    print start1.day 
    start2 = datetime.datetime(start1.year, start1.month, start1.day) 
    start3 = data['action'] 
    cal = vobject.iCalendar() 
    cal.add('method').value = 'PUBLISH' 
    vevent = cal.add('vevent') 
    vevent.add('dtstart').value = start1 
    vevent.add('dtend').value = start2 
    vevent.add('dtstamp').value = datetime.datetime.now() 
    vevent.add('summary').value = data['action'].name 
    response = HttpResponse(cal.serialize(), content_type='text/calendar') 
    response['Filename'] = 'filename.ics' 
    response['Content-Disposition'] = 'attachment; filename=filename.ics' 
    return response 

從型號,日期時間字段:

date_due = models.DateTimeField() 

UPDATE:

找到我只好就地:

>>> utc = vobject.icalendar.utc 
>>> start = cal.vevent.add('dtstart') 
>>> start.value = datetime.datetime(2006, 2, 16, tzinfo = utc) 

到它,它的工作。

+0

我嘗試添加該代碼,但我仍然有相同的崩潰。有沒有人知道2000年的日期來自哪裏,或者爲什麼添加另一個事件修復了@dman的崩潰? –

+0

已經很長時間了,在django世界裏可以改變很多東西:) – dman

+0

我不認爲這個bug實際上與Django有任何關係。就我而言,我發現我在轉換爲iCalendar之前不必要地調用了'pytz.timezone.normalize()'。我取消了通話,撞車消失了。 –

回答

2

簡短回答: vobject不是(0.9.2版本)與pytz兼容。因此,請確保每隔日期時間在您的vobject中iCalendar已被轉換爲UTC,然後嘗試序列化它,使用類似.astimezone(pytz.utc)

(這是爲dtstart,DTEND,dtstamp,創建,最後修改,也許其他一些VEVENT領域我忘了。)

龍答: VOBJECT試圖做正確的事情非UTC日期時間,但pytz會遇到麻煩。 「正確的事」來自RFC 5545指定的iCalendar:

  1. 表示使用DATE-TIME Form #3「日期與本地時間和時區參考」的日期時間。這可能類似於DTSTART;TZID=America/New_York:20160714T133000 - 注意事件時區的TZID。

  2. 爲您的事件中使用的每個唯一TZID添加VTIMEZONE塊到您的iCalendar。這是一個完整定義該時區:如何計算出UTC時間點可能出現的任何日期時間的偏移量,包括夏令時規則。 (RFC 5545 doesn't specify任何特定的時區的名字,所以你必須包括在的iCalendar本身時區定義。VOBJECT爲您完成此,自動)

搞清楚時區轉換規則,VOBJECT searches through "all time"(默認年2000-2030),尋找時區與UTC的偏移量的變化。這就是出錯的地方,因爲vobject代碼不能處理pytz的無效時間錯誤。

2000年4月2日凌晨2:00是2000年至2030年間的第一個DST過渡,這就是爲什麼你在那段時間出現錯誤(即使你沒有在自己的代碼中使用它)。

選項:

  • 使用date而不是datetime如果你不想一天中的特定時間(如在原來的問題)。日期沒有時區,所以這些都不適用。 (和vobject處理日期很好。)
  • 將所有datetime轉換爲以UTC識別日期時間。 UTC不需要VTIMEZONE定義。使用dateutil timezones而不是pytz。例如,from dateutil import tz; ... tzinfo=tz.gettz('America/Los_Angeles')。由於dateutil是一個vobject依賴項,我認爲這是vobject的VTIMEZONE生成器的設計格式。 (但還沒有廣泛的測試。另外,gettz需要TZDB安裝在計算機上的文件,所以也不是完全可移植的。)
  • 添加您自己的VTIMEZONE定義到的iCalendar爲每TZID使用,應避免有問題汽車vobject中的時區生成代碼。 (未經測試。複雜的得到正確一般情況下。)
  • 提交PR to fix vobject to work with pytz