UNTIL在RRULE声明中的时区问题

时间:2018-04-23 23:38:16

标签: python timezone icalendar

以下代码抛出异常,这很可能与我需要修复其他错误的TZID替换有关。如果我删除" UNTIL"来自字符串的语句,代码工作得很好。

from icalendar.cal import Calendar
import datetime
from dateutil import rrule
from dateutil.tz import gettz

cal_str = "BEGIN:VEVENT\nDTSTART;TZID=America/Los_Angeles:20171019T010000\nDTEND;TZID=America/Los_Angeles:20171019T230000\nRRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;UNTIL=20180423T191500\nX-OP-ENTRY-STATE:unlocked\nEND:VEVENT"
ical = Calendar.from_ical(cal_str)
start_time_dt = ical.get("DTSTART").dt
end_time_dt = ical.get("DTEND").dt
tzinfo = gettz(str(start_time_dt.tzinfo)) 
start_time_dt = start_time_dt.replace(tzinfo=tzinfo)
recurring_rule = ical.get('RRULE').to_ical().decode('utf-8')
rules = rrule.rruleset()
first_rule = rrule.rrulestr(recurring_rule, dtstart=start_time_dt)
rules.rrule(first_rule)
event_delta = end_time_dt -start_time_dt
now = datetime.datetime.now(datetime.timezone.utc)
for s in rules.between(now - event_delta, now + datetime.timedelta(minutes=1)):
    print(s)

以下是例外:

Traceback (most recent call last):
  File "ical_test.py", line 27, in <module>
    for s in rules.between(now - event_delta, now + datetime.timedelta(minutes=1)):
  File "/usr/local/lib/python3.5/dist-packages/dateutil/rrule.py", line 290, in between
    for i in gen:
  File "/usr/local/lib/python3.5/dist-packages/dateutil/rrule.py", line 1362, in _iter
    self._genitem(rlist, gen)
  File "/usr/local/lib/python3.5/dist-packages/dateutil/rrule.py", line 1292, in __init__
    self.dt = advance_iterator(gen)
  File "/usr/local/lib/python3.5/dist-packages/dateutil/rrule.py", line 861, in _iter
    if until and res > until:
TypeError: can't compare offset-naive and offset-aware datetimes

任何人都可以帮助找出导致此错误的根本原因以及解决此问题的方法吗?

1 个答案:

答案 0 :(得分:1)

首先,他们修复了异常,使dateutil>2.7.1更加明确:

Traceback (most recent call last):
  File "ical_test.py", line 23, in <module>
    first_rule = rrule.rrulestr(recurring_rule, dtstart=start_time_dt)
  File "/usr/local/lib/python3.5/dist-packages/dateutil/rrule.py", line 1664, in __call__
    return self._parse_rfc(s, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/dateutil/rrule.py", line 1547, in _parse_rfc
    tzinfos=tzinfos)
  File "/usr/local/lib/python3.5/dist-packages/dateutil/rrule.py", line 1506, in _parse_rfc_rrule
    return rrule(dtstart=dtstart, cache=cache, **rrkwargs)
  File "/usr/local/lib/python3.5/dist-packages/dateutil/rrule.py", line 461, in __init__
    'RRULE UNTIL values must be specified in UTC when DTSTART '
ValueError: RRULE UNTIL values must be specified in UTC when DTSTART is timezone-aware

解决方案是以UTC计算UNTIL时间并将Z添加到时间字符串的末尾,如RFC中所述:

https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html

正确的RRULE字符串应如下所示:

cal_str = "BEGIN:VEVENT\nDTSTART;TZID=America/Los_Angeles:20171019T010000\nDTEND;TZID=America/Los_Angeles:20171019T230000\nRRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;UNTIL=20180423T001500Z\nX-OP-ENTRY-STATE:unlocked\nEND:VEVENT"