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

调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 00:44:51