我正在创建一个使用EWS APIs来同步用户的应用程序' 将日历交换到他们的移动设备。从Exchange服务器获取的日历事件包含此事件的开始时间和结束时间的时区信息。正如here所述,EWS响应中的时区项目如下所示:
<m:TimeZoneDefinitions>
<t:TimeZoneDefinition Name="(GMT-05:00) Eastern Time (US & Canada)" Id="Eastern Standard Time">
<t:Periods>
<t:Period Bias="PT5H" Name="Standard" Id="trule:Microsoft/Registry/Eastern Standard Time/2006-Standard"/>
<t:Period Bias="PT4H" Name="Daylight" Id="trule:Microsoft/Registry/Eastern Standard Time/2006-Daylight"/>
<t:Period Bias="PT5H" Name="Standard" Id="trule:Microsoft/Registry/Eastern Standard Time/2007-Standard"/>
<t:Period Bias="PT4H" Name="Daylight" Id="trule:Microsoft/Registry/Eastern Standard Time/2007-Daylight"/>
</t:Periods>
<t:TransitionsGroups>
<t:TransitionsGroup Id="0">
<t:RecurringDayTransition>
<t:To Kind="Period">trule:Microsoft/Registry/Eastern Standard Time/2006-Daylight</t:To>
<t:TimeOffset>PT2H</t:TimeOffset>
<t:Month>4</t:Month>
<t:DayOfWeek>Sunday</t:DayOfWeek>
<t:Occurrence>1</t:Occurrence>
</t:RecurringDayTransition>
<t:RecurringDayTransition>
<t:To Kind="Period">trule:Microsoft/Registry/Eastern Standard Time/2006-Standard</t:To>
<t:TimeOffset>PT2H</t:TimeOffset>
<t:Month>10</t:Month>
<t:DayOfWeek>Sunday</t:DayOfWeek>
<t:Occurrence>-1</t:Occurrence>
</t:RecurringDayTransition>
</t:TransitionsGroup>
<t:TransitionsGroup Id="1">
<t:RecurringDayTransition>
<t:To Kind="Period">trule:Microsoft/Registry/Eastern Standard Time/2007-Daylight</t:To>
<t:TimeOffset>PT2H</t:TimeOffset>
<t:Month>3</t:Month>
<t:DayOfWeek>Sunday</t:DayOfWeek>
<t:Occurrence>2</t:Occurrence>
</t:RecurringDayTransition>
<t:RecurringDayTransition>
<t:To Kind="Period">trule:Microsoft/Registry/Eastern Standard Time/2007-Standard</t:To>
<t:TimeOffset>PT2H</t:TimeOffset>
<t:Month>11</t:Month>
<t:DayOfWeek>Sunday</t:DayOfWeek>
<t:Occurrence>1</t:Occurrence>
</t:RecurringDayTransition>
</t:TransitionsGroup>
</t:TransitionsGroups>
<t:Transitions>
<t:Transition>
<t:To Kind="Group">0</t:To>
</t:Transition>
<t:AbsoluteDateTransition>
<t:To Kind="Group">1</t:To>
<t:DateTime>2007-01-01T00:00:00</t:DateTime>
</t:AbsoluteDateTransition>
</t:Transitions>
</t:TimeZoneDefinition>
</m:TimeZoneDefinitions>
我需要的是: 从上面的TimeZoneDefinition XML,目前什么是UTC的时间偏移?
任何人都可以向我解释我应该遵循的算法来计算它。是否存在执行此操作的现有库(python)?
答案 0 :(得分:4)
有两种选择。第一个是我的首选建议:
提取XML的Id
元素(或者您已经在事件数据中拥有它,可以消除额外的Web服务调用)。在上面的示例中,Windows时区ID为"Eastern Standard Time"
。
import lxml.etree as et
xml = et.fromstring(open("in.xml").read())
windowsTimeZoneId = xml.xpath("//*[local-name() = 'TimeZoneDefinition']/@Id")
(感谢Padraic Cunningham上述XML提取代码段。)
使用tzlocal从Windows时区ID解析IANA时区,利用此库中包含的基于CLDR的Windows到IANA映射文件。
from tzlocal.windows_tz import win_tz
ianaTimeZoneId = win_tz.get(windowsTimeZoneId)
这应该会给你"America/New_York"
。
将pytz与生成的时区标识符一起使用
from datetime import datetime
import pytz
tz = pytz.timezone(ianaTimeZoneId)
now = datetime.now(tz)
另一种选择是通过算法解析XML来确定相关时间的偏移量。我会告诉你所涉及的步骤(如果需要,别人可以提供代码):
获取当前日期和时间 - 因为您需要当前偏移量。 (虽然认识到它可能确实与另一个日期和时间不同。)您需要获得与所讨论的时区相关的本地时间,因为这是如何定义这些规则的基础(仅此一项可能涉及pytz和tzlocal)。
检查Transitions
部分,找到适用的部分。在您的示例中,第一个规则是全能,第二个规则从2007年开始有效,因此第二个规则适用于当前时间。它被标记为第1组。
找到与上一步(TransitionGroup
)中的数字相匹配的TransitionGroup Id="1"
。计算当前年份内的日期gien Month
,DayOfWeek
和Occurrence
值。从午夜开始应用TimeOffset
值来获取转换的时间(在此情况下为00:00
+ PT2H
== 2:00 AM
)。
根据相关日期是在每个过渡日期之前还是之后确定哪个Period
适用。考虑到在北半球,向日光时间的过渡首先发生,然后向标准时间过渡发生。在南半球,情况正好相反。这里的逻辑可能会变得棘手,你必须考虑具有落入弹簧前向“间隙”的局部时间的边缘情况,或者在后退“重叠”中出现两次的边缘情况。
使用Period
值的Bias
属性作为偏移量,反转符号。在这种情况下,PT5H
为UTC-5,PT4H
为UTC-4。
正如您所看到的,这是非常复杂的,并且可能不是可以作为本网站上的答案干净地编写的内容。想要为此编写库的人当然可以通过这些步骤直接解决XML数据的偏移 - 但第一个选项很多更容易 - 当你认为你完全控制时更可靠过度更新时区数据。