如何格式化日期时间数据以适合 google 日历 api 的日期字段?

How do I format datetime data to fit google calendar api's date field?

目标:创建一个 Google 日历事件。

拦截器:日期格式。


背景:我正在尝试创建一个膳食计划器,它从给定的数据库中获取食谱并在 google 日历中创建带有名称的事件。数据库如下所示:

d = {'recipe_id': ['carrot salad', 'leek fritters'], 'meal_date': ['2020-05-28 22:28:01.204464+00:00', '2020-05-29 22:28:01.204464+00:00']}    
df = pd.DataFrame(data=d)

用餐日期是两个的乘积

today_date = datetime.datetime.utcnow().isoformat() + 'Z'
df['menu_date'] = today_date
df['menu_date'] = pd.to_datetime(df['menu_date'])
df['meal_date'] = df['menu_date'] + df['meal'].apply(pd.offsets.Day)

其中 'meal' 只是一个数字(1、2 等),最后一个命令只是将今天的日期移动该数量。

当我使用以下代码上传到 google 日历时出现错误:

def myconverter(o):
    '''
    call the __str__ method of the datetime object that will return a string representation of the value
    ___

    shoutout: https://code-maven.com/serialize-datetime-object-as-json-in-python
    '''
    if isinstance(o, datetime.datetime):
        return o.__str__()

def add_to_calendar(df, calendar_id):
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print('Adding meals to calendar')

    for i, r in df.iterrows():
        event = {
        'summary': r.name,
        'description': r.meal_period,
        'start': {
            'date': json.dumps(r.meal_date, default=myconverter),
            'timeZone': 'America/Los_Angeles'
        },
        'end': {
            'date': json.dumps(r.meal_date, default=myconverter),
            'timeZone': 'America/Los_Angeles'
        }
        }
        event = service.events().insert(calendarId=calendar_id, body=event).execute()

运行这段代码,我得到以下错误:

HttpError: <HttpError 400 when requesting https://www.googleapis.com/calendar/v3/calendars/CALENDAR_ID/events?alt=json returned "Invalid value for: Invalid format: ""2020-05-28 22:28:01.204464+00:00""">

其中 CALENDAR_ID 是我的 google 日历 ID。

如果有人知道如何使用 python 代码解决此日期问题,这将非常有帮助。

这个答案怎么样?

修改点:

  • 如果要使用 start.dateend.date 作为全天活动,格式需要为 yyyy-mm-dd。在这种情况下,timeZone 不是必需的。
  • 如果要使用start.dateTimeend.dateTime作为全天事件,格式需要为RFC3339。在这种情况下,timeZone 是必需的。

从以上情况来看,当你的脚本修改后,下面的模式如何?

模式 1:

在此模式中,使用了 start.dateend.date。为此,请修改如下。

发件人:

'start': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
}

收件人:

'start': {
    'date': 'date': parse(r.meal_date).strftime("%Y-%m-%d"),
},
'end': {
    'date': 'date': parse(r.meal_date).strftime("%Y-%m-%d"),
}

模式二:

在此模式中,使用了 start.dateTimeend.dateTime。为此,请修改如下。

发件人:

'start': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
}

收件人:

'start': {
    'dateTime': parse(r.meal_date).isoformat(),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'dateTime': parse(r.meal_date).isoformat(),
    'timeZone': 'America/Los_Angeles'
}

注:

  • 在此修改中,使用from dateutil.parser import parse
  • 从你的脚本中,我看不到你正在使用的范围。所以如果出现范围相关的错误,请使用https://www.googleapis.com/auth/calendar作为范围。届时请删除token.pickle的文件,重新授权作用域。请注意这一点。

参考: