python - EWS TimeZoneDefinitions : For a timezone, 如何计算当前时间的 UTC 偏移量

标签 python timezone exchangewebservices

我正在创建一个使用 EWS APIs 的应用程序同步用户的 将日历交换到他们的移动设备。从 Exchange 服务器获取的日历事件包含该事件的开始时间和结束时间的时区信息。正如所解释的here EWS 响应中的时区项表示如下:

      <m:TimeZoneDefinitions>
        <t:TimeZoneDefinition Name="(GMT-05:00) Eastern Time (US &amp; 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)可以做到这一点?

最佳答案

有两个选项。第一个是我的首选推荐:

  1. 安装tzlocalpytz包。

  2. 提取 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 提取片段。)

  3. 使用 tzlocal 从 Windows 时区 ID 解析 IANA 时区,并利用此库中包含的基于 CLDR 的 Windows 到 IANA 映射文件。

    from tzlocal.windows_tz import win_tz
    ianaTimeZoneId = win_tz.get(windowsTimeZoneId)
    

    这应该给你 "America/New_York" .

  4. 使用 pytz 和生成的时区标识符

    from datetime import datetime
    import pytz
    tz = pytz.timezone(ianaTimeZoneId)
    now = datetime.now(tz)
    

另一个选项是通过算法解析 XML 以确定相关时间的偏移量。我将向您详细介绍所涉及的步骤(如果需要,其他人可以提供代码):

  1. 获取当前日期和时间 - 因为您需要当前偏移量。 (尽管认识到其他日期和时间可能确实有所不同。)您需要获取与相关时区相关的本地时间,因为这是如何定义这些规则的基础(仅此一项就可能涉及 pytz 和 tzlocal)。

  2. 检查 Transitions部分并找到适用的部分。在您的示例中,第一个规则是包罗万象的,第二个规则从 2007 年起有效,因此第二个规则适用于当前时间。它被标记为组 1。

  3. 查找TransitionGroup匹配上一步中的编号 ( TransitionGroup Id="1" )。计算当前年份内的日期,给定 Month , DayOfWeek ,和Occurrence值(value)观。应用TimeOffset从午夜开始的值来获取转换的时间(在本例中为 00:00 + PT2H == 2:00 AM)。

  4. 确定哪个 Period是否适用,取决于相关日期是在每个过渡日期之前还是之后。考虑到在北半球,首先过渡到夏令时,然后过渡到标准时间。在南半球,情况恰恰相反。这里的逻辑可能会变得棘手,您必须考虑本地时间落入前向“间隙”中的边缘情况,或者在后退“重叠”中出现两次的本地时间。

  5. 使用 PeriodBias属性作为偏移量,反转符号。在这种情况下,PT5H是 UTC-5,并且 PT4H是 UTC-4。

正如您所看到的,这非常复杂,并且可能无法在本网站上清晰地写出答案。想要为此编写库的人当然可以通过这些步骤来直接解决 XML 数据的偏移量 - 但第一个选项更容易 - 当您认为自己拥有完全控制权时更可靠自行更新时区数据。

关于python - EWS TimeZoneDefinitions : For a timezone, 如何计算当前时间的 UTC 偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34875594/

相关文章:

c# - Exchange Web 服务,将项目从收件箱中移出它已从收件箱中删除但未显示在目标文件夹中

python - 用什么命令代替 urllib.request.urlretrieve?

python - 提高网页抓取的速度/性能,但有很多异常(exception)情况

javascript - 在不使用 Geonames.org 等 Web 服务的情况下根据纬度/经度确定时区

java - Struts2 日期标签时区行为

c# - 如何从 EWS 中的传入电子邮件中获取 UniqueBody?

python - pickle 时保留 numpy View

python - 在 python 和 numpy 中处理大数据,没有足够的内存,如何将部分结果保存在磁盘上?

Php 设置时区

java - Exchange 日历、创建约会和唯一 ID