我正在使用vobject在Django中创建一个ical事件。我遇到了较低级代码的问题。看起来ical正试图用obj.add(TimezoneComponent(tzinfo=getTzid(tzid)))
抓住时区。但是我从pytz得到raise NonExistentTimeError(dt)
。有关该怎么办的任何建议?当我使用print语句查看变量start1时,年,月,日显示正确。
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()
更新:
发现我不得不放置:
>>> utc = vobject.icalendar.utc
>>> start = cal.vevent.add('dtstart')
>>> start.value = datetime.datetime(2006, 2, 16, tzinfo = utc)
进入它,这是有效的。
答案 0 :(得分:2)
简答: vobject不是(与0.9.2一样)与pytz兼容。因此,在尝试使用.astimezone(pytz.utc)
之类的序列化之前,请确保vobject iCalendar中的每个日期时间已转换为UTC。
(那是每个 dtstart,dtend,dtstamp,创建,最后修改,以及其他一些我已经忘记的其他修道院。)
答案很长: vobject尝试为非UTC日期时间做正确的事情,但是遇到了pytz问题。正确的事情"来自RFC 5545,它指定了iCalendar:
使用DATE-TIME Form #3"日期与当地时间和时区参考"表示日期时间。这可能类似于DTSTART;TZID=America/New_York:20160714T133000
- 注意事件时区的TZID。
为您的iCalendar添加一个VTIMEZONE块,用于您的活动中使用的每个唯一TZID。这是该时区的完整定义:如何确定时区与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定义。from dateutil import tz; ... tzinfo=tz.gettz('America/Los_Angeles')
。由于dateutil是一个vobject依赖项,我认为这是vobject的VTIMEZONE生成器的格式。 (但是没有经过广泛的测试。另外,gettz需要在你的机器上安装tzdb文件,因此不能完全移植。)