【问题标题】:Timezone issue with pyExchangepyExchange 的时区问题
【发布时间】:2015-03-17 11:01:42
【问题描述】:

我在 Windows 7 机器上使用 pyExchange。我有一个简单的 python v2.7 脚本,可以从交换服务器检索 Outlook 日历事件。脚本如下:

代码

from pyexchange import Exchange2010Service, ExchangeNTLMAuthConnection
from datetime import datetime
import time
from pytz import timezone

def getEvents():
        URL = u'https://xxxxx.de/EWS/Exchange.asmx'
        USERNAME = u'MS.LOCAL\\xxxxx'
        PASSWORD = u"xxxxxx"

        connection = ExchangeNTLMAuthConnection(url=URL,
                                            username=USERNAME,
                                            password=PASSWORD)

        service = Exchange2010Service(connection)

        timestamp = datetime.now()
        print timestamp.strftime('%Y, %m, %d, %H, %M, %S')

        print time.timezone

        eventsList = service.calendar().list_events(
            start=timezone("Europe/Amsterdam").localize(datetime(2015, 1, 19, 0, 0, 0)),
            end=timezone("Europe/Amsterdam").localize(datetime(2015, 1, 19, 23, 59, 59)),
            details=True
        )

        for event in eventsList.events:
            print "{start} {stop} - {subject} - {room}".format(
                start=event.start,
                stop=event.end,
                subject=event.subject,
                room=event.location
            )

getEvents()

问题

事件的时间戳与 Outlook 中事件的时间戳不匹配。我使用 Outlook 以及 pyExchange 脚本手动创建了事件。

例如:如果我在 Outlook 中从11:00 AM - 11:30 AM 创建一个事件,那么上述脚本将返回该事件的时间戳为10:00 AM - 10:30 AM。时间少了一小时/后退。

如果我检查我的 time.timezone,它会返回 W. Europe Standard Time。我也在脚本中指定了我的时区,即。 Europe/Amsterdam。但问题仍然存在。我还检查了 Outlook 中的时区设置。如下图所示:

我登录了 Exchange 服务器,它也与我的客户端计算机位于同一时区。

关于为什么事件的时间不正确的任何建议?这是 pyExchange 中的错误吗?如果有人可以对此进行测试并在这里报告,我将不胜感激,以确保不仅是我面临这个问题。

【问题讨论】:

  • 这看起来像是 API 使用问题(传递了错误的参数,例如,它可能期望本地时区中的原始日期时间对象)或 Exchange 堆栈中的错误。 tzlocal.get_localzone() 返回什么?
  • 它返回Europe/Berlin,即使我在脚本中更改它而不是Europe/Amsterdam,也没有任何变化。问题依然存在。
  • Europe/BerlinEurope/Amsterdam 现在都是 CET+0100。最近日期的时区相同。我不希望有不同的结果(这只是一个健全的检查)。
  • 这里是包维护者,我去看看。时区是棘手的野兽,它很可能是包中的一个错误。抱歉问题!

标签: python python-2.7 outlook timezone pyexchange


【解决方案1】:

我看了看,这可能不是 pyexchange 中的错误,而是您如何处理时区。不丢人,可悲的是,它们在 Python 中非常令人困惑。

首先,程序包以 UTC 而非您的本地时间返回活动日期。由于您的时区是 +1 UTC,您看到的时间比预期的时间晚了一个小时。这是我使用您的脚本从我的日历中提取的一个事件(这是开始/结束/名称/房间):

2015-01-19 20:00:00+00:00 2015-01-19 21:00:00+00:00 - Lunch - Cafe

注意 +00:00 - 这意味着它是 UTC。加利福尼亚的中午是 20:00 UTC。

在处理日期时间时始终使用 UTC。这是来自 why localtimes are dangerous. 上的 pytz 人员的一些文档

PyExchange 尝试支持您并将本地时间转换为 UTC,但它始终返回 UTC。这是故意的,因为请参阅上一个链接。

现在,回答您有关使其正常工作的问题。首先,使用这些方便的技巧将您的本地时间转换为 UTC:

  1. 使用 datetime.now(pytz.utc) 获取当前日期时间
  2. 不要使用 datetime(..., tzinfo=timezone) 创建时区感知 datetime 对象,它是 broken。相反,创建 datetime 对象并在其上调用 timezone.localize。

对你来说,这意味着你必须做一些丑陋的事情,比如:

start = timezone("Europe/Amsterdam").localize(datetime(2015, 1, 19, 0, 0, 0))
start = start.astimezone(pytz.utc)

然后,当您想将 UTC 日期显示为您自己的时间时,请执行以下操作:

event.start.astimezone(timezone("Europe/Amsterdam"))

当我这样做时,我会从您的脚本中看到以下输出:

2015-01-19 21:00:00+01:00 2015-01-19 22:00:00+01:00 - Lunch - Cafe

这是我所期望的。中午我的时间是你的时间晚上 9 点。

Here's a gist of your script that I changed. 看看它是否能解决您的问题。如果没有,我很高兴再看一遍!

【讨论】:

  • pytz 谈到了代表当地时间的 naive 日期时间对象。包应该接受任何时区中的 aware 日期时间对象,例如 datetime.now(timezone('Europe/Amsterdam')) - 表示 Europe/Amsterdam 时区中的当前时间的可感知日期时间对象。 (如果需要,您始终可以在内部将它们转换为 UTC(忽略极端的日期时间值)。首选指定 is_dst=None 以在本地时间不明确或不存在时引发异常(错误不应被忽视,除非明确静音)调用 @ 987654334@.
  • 根据endstart 的含义,您可以使用以下方法find end - start
  • @J.F.Sebastian - 是的。 Pyexchange 确实接受任何时区中的任何感知日期时间对象,它只是不返回本地时区中的日期时间。或者应该。如果它不这样做,我认为这是一个错误。 :)
  • 我最近读到了"Unicode normalization insensitivity as a rule" -- 1. 不要修改输入(无论它是什么都保留) 2. 比较标准化。它转换为时区:1. 返回与您收到的日期时间对象完全相同的感知日期时间对象 2. 规范化(转换为 utc 以进行比较、日期算术等)。
  • 这可能适用于编码,但不适用于时区。从 UTC 你可以转换成任何东西,但反过来是不正确的,假设你可以是危险的。最佳做法是始终使用 UTC 并且仅使用本地时间进行显示。通读:lucumr.pocoo.org/2011/7/15/eppur-si-muove
猜你喜欢
  • 1970-01-01
  • 2020-09-18
  • 1970-01-01
  • 2013-09-16
  • 2016-09-12
  • 2020-07-11
  • 2012-02-27
  • 2011-06-15
  • 2021-01-26
相关资源
最近更新 更多