You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用O365库获取微软日历全天事件时的查询异常问题

O365库查询土耳其时区全天日历事件时返回前一天事件的问题解决

问题场景

使用O365库查询伊斯坦布尔时区(Turkey Standard Time)下指定日期(2022-09-18)的日历事件时,结果意外包含了前一天(2022-09-17)的全天事件dummy 1,而预期只获取当天的dummy 2、event 2和event 4。

实现代码如下:

...
start_date = pytz.timezone("Europe/Istanbul").localize(datetime(2022, 9, 18))
end_date = pytz.timezone("Europe/Istanbul").localize(datetime(2022, 9, 19))
q = calendar.new_query('start').greater_equal(start_date)
q.chain('and').on_attribute('end').less(end_date)
events = calendar.get_events(query=q, include_recurring=True)
pprint(
    [
        (
            g.to_api_data()["subject"],
            g.to_api_data()["start"],
            g.to_api_data()["end"]
        ) for g in events])

实际输出:

[('dummy 1',
  {'dateTime': '2022-09-17T03:00:00', 'timeZone': 'Turkey Standard Time'},
  {'dateTime': '2022-09-18T03:00:00', 'timeZone': 'Turkey Standard Time'}),
 ('event 2',
  {'dateTime': '2022-09-18T00:00:00', 'timeZone': 'Turkey Standard Time'},
  {'dateTime': '2022-09-18T00:30:00', 'timeZone': 'Turkey Standard Time'}),
 ('dummy 2',
  {'dateTime': '2022-09-18T03:00:00', 'timeZone': 'Turkey Standard Time'},
  {'dateTime': '2022-09-19T03:00:00', 'timeZone': 'Turkey Standard Time'}),
 ('event 4',
  {'dateTime': '2022-09-18T23:30:00', 'timeZone': 'Turkey Standard Time'},
  {'dateTime': '2022-09-19T00:00:00', 'timeZone': 'Turkey Standard Time'})
]

原因分析

微软Graph/Exchange API中,全天事件的时间戳是基于UTC转换为当地时区的:

  • 土耳其时区为UTC+3,当天的全天事件会被存储为UTC时间的YYYY-MM-DDT00:00:00,转换为当地时间就是YYYY-MM-DDT03:00:00
  • 前一天的全天事件(如dummy 1)的结束时间是UTC2022-09-18T00:00:00,转换为土耳其时间就是2022-09-18T03:00:00,这个时间落在查询的end_date(2022-09-19T00:00:00)之前,所以被误纳入结果。

而普通事件的时间是直接按当地时区存储的,不会出现这种偏移。

解决方案

针对全天事件和非全天事件分别构建查询条件,再通过OR逻辑合并,避免时区偏移带来的查询错误:

  1. 非全天事件:保留原有的时间范围条件(start >= 2022-09-18T00:00 且 end < 2022-09-19T00:00)
  2. 全天事件:直接匹配事件的start.date等于目标日期(2022-09-18),API会自动按日历时区解析日期

修改后的代码示例:

import pytz
from datetime import datetime
from pprint import pprint

...

target_date = datetime(2022, 9, 18).date()
tz = pytz.timezone("Europe/Istanbul")
start_datetime = tz.localize(datetime(2022, 9, 18))
end_datetime = tz.localize(datetime(2022, 9, 19))

# 构建非全天事件查询
non_all_day_q = calendar.new_query('isAllDay').equals(False)
non_all_day_q.chain('and').on_attribute('start').greater_equal(start_datetime)
non_all_day_q.chain('and').on_attribute('end').less(end_datetime)

# 构建全天事件查询
all_day_q = calendar.new_query('isAllDay').equals(True)
all_day_q.chain('and').on_attribute('start').equals(target_date)

# 合并两个查询(OR逻辑)
combined_q = calendar.new_query().or_query(non_all_day_q, all_day_q)

# 获取事件
events = calendar.get_events(query=combined_q, include_recurring=True)

# 输出结果
pprint(
    [
        (
            g.to_api_data()["subject"],
            g.to_api_data()["start"],
            g.to_api_data()["end"]
        ) for g in events])

内容的提问来源于stack exchange,提问作者Benyamin Jafari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:40:23