我正在创建一个使用 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)可以做到这一点?
最佳答案
有两个选项。第一个是我的首选推荐:
提取
Id
XML 的元素(或者您可能已经将其包含在事件数据中并且可以消除额外的 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"
)。计算当前年份内的日期,给定Month
,DayOfWeek
,和Occurrence
值(value)观。应用TimeOffset
从午夜开始的值来获取转换的时间(在本例中为00:00
+PT2H
==2:00 AM
)。确定哪个
里>Period
是否适用,取决于相关日期是在每个过渡日期之前还是之后。考虑到在北半球,首先过渡到夏令时,然后过渡到标准时间。在南半球,情况恰恰相反。这里的逻辑可能会变得棘手,您必须考虑本地时间落入前向“间隙”中的边缘情况,或者在后退“重叠”中出现两次的本地时间。使用
Period
值Bias
属性作为偏移量,反转符号。在这种情况下,PT5H
是 UTC-5,并且PT4H
是 UTC-4。
正如您所看到的,这非常复杂,并且可能无法在本网站上清晰地写出答案。想要为此编写库的人当然可以通过这些步骤来直接解决 XML 数据的偏移量 - 但第一个选项更容易 - 当您认为自己拥有完全控制权时更可靠自行更新时区数据。
关于python - EWS TimeZoneDefinitions : For a timezone, 如何计算当前时间的 UTC 偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34875594/