调用Google Calendar API时遭遇400 Bad Request错误求助
Google Calendar API 400 Bad Request 错误解决
错误信息
C:\Users\Documents\Calendar Add-On>python calendar_v2.py Traceback (most recent call last): File "C:\Users\Documents\Calendar Add-On\calendar_v2.py", line 68, in <module> create_events(calendar_id) File "C:\Users\Documents\Calendar Add-On\calendar_v2.py", line 46, in create_events events_result = service.events().list( File "C:\Users\anaconda3\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper return wrapped(*args, **kwargs) File "C:\Users\anaconda3\lib\site-packages\googleapiclient\http.py", line 938, in execute raise HttpError(resp, content, uri=self.uri) googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=2024-05-15T20%3A43%3A15.671352&timeMax=2024-06-14T20%3A43%3A15.671352&singleEvents=true&alt=json returned "Bad Request". Details: "[{'domain': 'global', 'reason': 'badRequest', 'message': 'Bad Request'}]">
问题代码片段
from google.oauth2 import service_account from googleapiclient.discovery import build from datetime import datetime, timedelta # Define the service account credentials SERVICE_ACCOUNT_FILE = r'path_to_service_account_file.json' SCOPES = ['https://www.googleapis.com/auth/calendar'] # Authenticate and build the Calendar API client credentials = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES) service = build('calendar', 'v3', credentials=credentials) # Function to add buffer before and after each event def add_event_buffer(event): start_time = event['start'].get('dateTime') end_time = event['end'].get('dateTime') if start_time and end_time: start_dt = datetime.fromisoformat(start_time) end_dt = datetime.fromisoformat(end_time) buffer_time = timedelta(minutes=10) buffered_start_time = (start_dt - buffer_time).strftime('%Y-%m-%dT%H:%M:%S.%fZ') buffered_end_time = (end_dt + buffer_time).strftime('%Y-%m-%dT%H:%M:%S.%fZ') event['start']['dateTime'] = buffered_start_time event['end']['dateTime'] = buffered_end_time event['summary'] = 'Travel Time - ' + event['summary'] return event # Function to create buffered events on the calendar def create_buffered_events(calendar_id): try: start_time = datetime.now().isoformat() end_time = (datetime.now() + timedelta(days=30)).isoformat() events_result = service.events().list( calendarId=calendar_id, timeMin=start_time, timeMax=end_time, singleEvents=True ).execute() events = events_result.get('items', []) if not events: print('No events found.') else: for event in events: if 'Travel Time' in event.get('summary', ''): print(f'Skipping buffered event for: {event["summary"]} (already buffered)') continue buffered_event = add_event_buffer(event) if 'id' in event: service.events().update(calendarId=calendar_id, eventId=event['id'], body=buffered_event).execute() print(f'Buffered event updated for: {buffered_event["summary"]}') else: service.events().insert(calendarId=calendar_id, body=buffered_event).execute() print(f'Buffered event created for: {buffered_event["summary"]}') except Exception as e: print("An error occurred:", e) raise # Example usage if __name__ == '__main__': calendar_id = 'calendar_id@gmail.com' create_buffered_events(calendar_id)
错误原因及修复方案
1. 时间格式不符合API要求
Google Calendar API要求timeMin和timeMax必须遵循RFC3339格式,即需包含时区信息(后缀Z表示UTC时区,或带时区偏移如+08:00)。当前代码用datetime.now().isoformat()生成的时间字符串无时区标识(如错误信息中的2024-05-15T20:43:15.671352),直接触发400错误。
修复代码:
替换时间生成逻辑为UTC时间并添加Z后缀:
start_time = datetime.utcnow().isoformat() + 'Z' end_time = (datetime.utcnow() + timedelta(days=30)).isoformat() + 'Z'
2. 服务账号权限验证(额外注意)
即使修复时间格式,若服务账号未获目标日历授权,仍可能报错:
- 从JSON密钥文件的
client_email字段获取服务账号邮箱 - 登录Google Calendar,打开目标日历共享设置,将该邮箱添加为日历编辑者
3. 事件逻辑优化(可选)
当前代码直接修改原事件,建议创建独立缓冲事件避免覆盖原数据:
def create_buffered_events(calendar_id): try: start_time = datetime.utcnow().isoformat() + 'Z' end_time = (datetime.utcnow() + timedelta(days=30)).isoformat() + 'Z' events_result = service.events().list( calendarId=calendar_id, timeMin=start_time, timeMax=end_time, singleEvents=True ).execute() events = events_result.get('items', []) if not events: print('No events found.') else: for event in events: if 'Travel Time' in event.get('summary', ''): print(f'Skipping buffered event for: {event["summary"]} (already buffered)') continue buffered_event = add_event_buffer(event.copy()) # 复制原事件避免修改源数据 buffered_event.pop('id', None) # 移除原ID确保创建新事件 service.events().insert(calendarId=calendar_id, body=buffered_event).execute() print(f'Buffered event created for: {buffered_event["summary"]}') except Exception as e: print("An error occurred:", e) raise
内容的提问来源于stack exchange,提问作者Danish Karmally
相关产品推荐
相关产品推荐

