如何匹配 dateuilts.rrule 和 python icalendar 夏令时感知

问题描述 投票:0回答:1

我正在处理一些实际问题。

我有一个特殊事件。

BEGIN:VEVENT
UID:Event/termine/gps/[email protected] 
DTSTART;TZID=CET:20150529T190000
DTEND;TZID=CET:20150529T220000
CATEGORIES:Arbeitsgruppe
DTSTAMP:20110620T075538Z
EXDATE;TZID=CET:20151225T190000
LAST-MODIFIED:20150424T201707Z
LOCATION:Vereinsräume des Augsburger Computer Forum e.V.
PRIORITY:5
RRULE:FREQ=MONTHLY;BYDAY=-1FR
SUMMARY:GPS-Arbeitsgruppe
URL:https://www.augusta.de/termine/gps
END:VEVENT

如您所见,每个月的最后一个星期五都有一个 RRule 重复此事件。

我用 calendar 解析了这个 ical。

我正在使用:

start = iobj.get( 'DTSTART' ).dt
rrset = rruleset()
rrule = iobj.get( 'RRULE' )
exdate = iobj.get( 'EXDATE' )
rrset.rrule( rrule.rrulestr( rule.to_ical(), dtstart = start ) )
for edate in exdate.dts : 
    rrset.exdate( edate.dt )

到目前为止一切都运行良好。

当我尝试获取下一个 10 个日期时:

list(rrset)[:10] 

我得到:

[datetime.datetime(2015, 5, 29, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2015, 6, 26, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2015, 7, 31, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2015, 8, 28, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2015, 9, 25, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2015, 10, 30, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2015, 11, 27, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2015, 12, 25, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2016, 1, 29, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
 datetime.datetime(2016, 2, 26, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)]

乍一看似乎没问题,但更深入的检查发现,从 10 月 30 日开始,夏令时于 10 月 25 日结束,但日期时间对象的 tzinfo 信息仍然是“DstTzInfo 'CET' CEST+2:00:00 DST” ”

第二个问题是 12 月 25 日位于此列表中,而不是跳过 EXDATE 中指定的日期。在解析 exdate 规则夏令时时,问题接缝是正确计算的,因此 exdate 19:00:00+01:00 与计算的重复时间 19:00:00+02:00 不匹配。

我在那里做错了什么吗?

将所有内容转换为 UTC 并在那里进行处理并没有帮助,因为 17:00:00 UTC 也不匹配 18:00:00 UTC。

python date datetime icalendar rrule
1个回答
0
投票

recurring-ical-events 处理这种特殊情况:

>>> import icalendar, recurring_ical_events
>>> s = """BEGIN:VEVENT
... UID:Event/termine/gps/[email protected] 
... DTSTART;TZID=CET:20150529T190000
... DTEND;TZID=CET:20150529T220000
... CATEGORIES:Arbeitsgruppe
... DTSTAMP:20110620T075538Z
... EXDATE;TZID=CET:20151225T190000
... LAST-MODIFIED:20150424T201707Z
... LOCATION:Vereinsräume des Augsburger Computer Forum e.V.
... PRIORITY:5
... RRULE:FREQ=MONTHLY;BYDAY=-1FR
... SUMMARY:GPS-Arbeitsgruppe
... URL:https://www.augusta.de/termine/gps
... END:VEVENT"""
>>> event = icalendar.Event.from_ical(s)
>>> for e in recurring_ical_events.of(event).at(2015):
...   print(e["DTSTART"].dt)
... 
2015-05-29 19:00:00+02:00
2015-06-26 19:00:00+02:00
2015-07-31 19:00:00+02:00
2015-08-28 19:00:00+02:00
2015-09-25 19:00:00+02:00
2015-10-30 19:00:00+01:00
2015-11-27 19:00:00+01:00

可以看到12月的EXDATE没有列出。

© www.soinside.com 2019 - 2024. All rights reserved.