【问题标题】:EWS TimeZoneDefinitions: For a timezone, how to calculate UTC offset at present timeEWS TimeZoneDefinitions:对于时区,如何计算当前时间的 UTC 偏移量
【发布时间】:2016-04-24 20:32:17
【问题描述】:

我正在创建一个使用 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)可以做到这一点?

【问题讨论】:

  • 为什么不直接从 xml 中获取呢?
  • 是的,我想从 XML 中提取它。但是上面的 XML 看起来很神秘。我希望如果有人已经知道要从 XML 中提取偏移量要遵循的步骤。

标签: python timezone exchangewebservices


【解决方案1】:

有两种选择。第一个是我的首选建议:

  1. 安装tzlocalpytz 软件包。

  2. 提取 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提取sn-p。)

  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. 获取当前日期和时间 - 因为您想要 current 偏移量。 (尽管认识到它对于另一个日期和时间可能确实不同。)您需要获取与相关时区相关的本地时间,因为这是定义这些规则的基础(仅此一项就可能涉及 pytz 和 tzlocal)。

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

  3. 找到与上一步中的数字匹配的TransitionGroup (TransitionGroup Id="1")。根据 MonthDayOfWeekOccurrence 值计算当前年份内的日期。从午夜应用 TimeOffset 值以获取转换的时间(在本例中为 00:00 + PT2H == 2:00 AM)。

  4. 根据相关日期是在每个转换日期之前还是之后,确定适用的 Period。考虑到在北半球,首先转换到夏令时,然后转换到标准时间。在南半球,情况正好相反。这里的逻辑可能会变得棘手,您必须考虑本地时间落入弹簧前“间隙”或在后退“重叠”中出现两次的极端情况。

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

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

【讨论】:

  • 我尝试了 tzlocal 库方法。对于许多用户来说它失败了,因为 XML 的 Id 元素是 1. 空或 2. 一些随机字符串。例如:“tzone://Microsoft/Utc”、“GMT+00:00”、“印度时间”或 3. 包含 pytz 和 tzlocal 无法处理的 Unicode 字符。我意识到我不能依赖 ID,它可以是任何随机字符串,正确的做法是解析时区定义。我最终为 EWS 响应中提供的时区定义编写了一个解析器。
  • @Varun - 如果您可以分享解决方案,请这样做。您可以将其添加到此问题的答案中。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-17
  • 1970-01-01
相关资源
最近更新 更多