google-api-ruby-client设置日历事件起止时间时区异常问题
I’ve run into this exact issue before—it’s all about how your time objects are being parsed and passed to the API. Let’s break down what’s happening and how to fix it:
What’s Going Wrong
Your code uses DateTime.parse(date_string) which creates a time object in your local timezone (looks like Pacific Time, -0700) instead of the Europe/London timezone you specified. When you pass this local-time DateTime to the API alongside time_zone: "Europe/London", Google’s API gets confused: it takes the -0700 offset time, converts it to UTC, then shifts it again to Europe/London time—resulting in that incorrect early-morning time you’re seeing.
The Fix: Ensure Your Time Objects Are in the Target Timezone
You need to explicitly parse or convert your time to the Europe/London timezone before sending it to the API. Here are two common approaches depending on whether you’re using Rails or plain Ruby:
Option 1: If You’re Using Rails (ActiveSupport)
Rails makes timezone handling straightforward. Use ActiveSupport::TimeZone to parse the time directly into your target timezone:
def service secrets = setup_credentials service = Google::Apis::CalendarV3::CalendarService.new service.client_options.application_name = 'Quickstart' service.authorization = secrets.to_authorization event_id = "yyyzzzzzzxxxxx" # Parse the time directly in Europe/London timezone target_tz = ActiveSupport::TimeZone.new("Europe/London") date = target_tz.parse("2018-4-23 10:45AM") end_date = date + 1.hour event = { summary: "hype event", start: {date_time: date, time_zone: "Europe/London"}, end: {date_time: end_date, time_zone: "Europe/London"} } service.update_event('primary', event_id, event, send_notifications: true) end
Option 2: Plain Ruby (Using tzinfo Gem)
If you’re not using Rails, add the tzinfo gem to your project (it handles timezone conversions reliably):
- Add
gem 'tzinfo'to your Gemfile and runbundle install - Update your code to parse the time into the correct timezone:
require 'tzinfo' def service secrets = setup_credentials service = Google::Apis::CalendarV3::CalendarService.new service.client_options.application_name = 'Quickstart' service.authorization = secrets.to_authorization event_id = "yyyzzzzzzxxxxx" # Get the Europe/London timezone object london_tz = TZInfo::Timezone.get("Europe/London") # Parse the input string as a local time in Europe/London date = london_tz.strptime("2018-4-23 10:45AM", "%Y-%m-%d %I:%M%p") end_date = date + 3600 # Add 1 hour in seconds to avoid timezone drift # Pass the time as an RFC3339 string (the API loves this format) event = { summary: "hype event", start: {date_time: date.rfc3339, time_zone: "Europe/London"}, end: {date_time: end_date.rfc3339, time_zone: "Europe/London"} } service.update_event('primary', event_id, event, send_notifications: true) end
Another Quick Hack: Use RFC3339 Strings Directly
If you want to bypass timezone object headaches, you can construct the time as an RFC3339 string with the correct London timezone offset (remember, London uses BST in April, so +01:00):
date_string = "2018-04-23T10:45:00+01:00" end_date_string = "2018-04-23T11:45:00+01:00" event = { summary: "hype event", start: {date_time: date_string, time_zone: "Europe/London"}, end: {date_time: end_date_string, time_zone: "Europe/London"} }
After making these changes, the API should return the correct Europe/London timezone times in the response, matching what you intended to save.
内容的提问来源于stack exchange,提问作者brg

