Google Calendar API获取指定日期事件异常:为何返回次日全天事件?
问题描述
我正在使用Python和Google Calendar API开发日历功能,希望获取指定日期(格式为'yyyy-mm-dd')的所有事件。我编写了如下函数,但它仍会返回指定日期的事件以及次日的全天事件。
from datetime import * import pytz def get_events_by_date(api_service, event_date): split_date = event_date.split('-') event_date = datetime(int(split_date[0]), int(split_date[1]), int(split_date[2]), 00, 00, 00, 0) event_date = pytz.UTC.localize(event_date).isoformat() end = datetime(int(split_date[0]), int(split_date[1]), int(split_date[2]), 23, 59, 59, 999999) end = pytz.UTC.localize(end).isoformat() events_result = api_service.events().list(calendarId='primary', timeMin=event_date,timeMax=end).execute() return events_result.get('items', []) >>all_events = get_events_by_date(api, '2022-09-24') >>for event in all_events: print(event['summary'])
例如调用该函数获取2022-09-24的事件时,会打印当天所有事件以及2022-09-25的全天事件。请问这是什么原因?或者有更好的实现方式吗?
注:时区转换的思路来自帖子《在Python中生成RFC 3339时间戳》
问题原因
Google Calendar API里,全天事件的时间会被存储为UTC时区的前一天午夜到当天午夜。比如你创建的2022-09-25的全天事件,在UTC时区对应的时间范围是2022-09-24T00:00:00Z到2022-09-25T00:00:00Z。而你设置的timeMax是2022-09-24T23:59:59.999999Z,这个时间点刚好落在该全天事件的时间范围内,所以会被包含进来。
解决方案
方案1:调整timeMax为次日UTC午夜
把timeMax设置为指定日期的次日00:00:00 UTC,就能精准排除次日的全天事件:
from datetime import * import pytz def get_events_by_date(api_service, event_date): split_date = event_date.split('-') year, month, day = map(int, split_date) # 计算当天UTC起始时间 start_date = datetime(year, month, day, 0, 0, 0, tzinfo=pytz.UTC) # 计算次日UTC起始时间作为timeMax end_date = start_date + timedelta(days=1) events_result = api_service.events().list( calendarId='primary', timeMin=start_date.isoformat(), timeMax=end_date.isoformat() ).execute() return events_result.get('items', [])
方案2:兼容重复事件的优化方案
如果日历中有重复事件,加上singleEvents=True可以将重复事件展开为单个实例,同时配合正确的时间范围,能更准确获取目标日期的事件:
from datetime import * import pytz def get_events_by_date(api_service, event_date): split_date = event_date.split('-') year, month, day = map(int, split_date) start_date = datetime(year, month, day, 0, 0, 0, tzinfo=pytz.UTC) end_date = start_date + timedelta(days=1) events_result = api_service.events().list( calendarId='primary', timeMin=start_date.isoformat(), timeMax=end_date.isoformat(), singleEvents=True, # 展开重复事件为单个实例 orderBy='startTime' # 按事件开始时间排序,可选 ).execute() return events_result.get('items', [])
内容的提问来源于stack exchange,提问作者user19245296
相关产品推荐
相关产品推荐

