2014-01-15 17 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