thumbtackthief
thumbtackthief

Reputation: 6211

Handle time zones in a Rails App with Google Calendar API

I am building an application in which users enter data on a form, including a date and time, which then populates their Google Calendar with events based on that information. I can't seem to figure out how to handle time zones, and I'm not sure whether the issue is with Ruby/Rails or the Google Calendar API, both of which have documentation which is... not great.

If I enter 10:00AM on my form, the Google Calendar invite is created at 6:00 AM. I'm at -0400 from UTC, which accounts for that. Ideally, I'd like for the user to not have to worry about time zones at all, but if I have to have my user choose a time zone from a dropdown it's not the end of the world.

Here's my form (which I am free to modify in any way as long as I have a way for the user to enter a time and date):

<%= date_field(:calendar, "start_date", min: Date.today, :value => Time.now.strftime('%Y-%m-%d'), :class=>'form-control') %>


<input type="time" id="calendar_start_time" name="calendar[start_time]" min="9:00" max="18:00"  value="10:00" step="900" />

    <%= select("calendar", "time_zone", @timezones, {:class=>'form-control'}) %>

And my controller:

  def create
    calendar_id = params[:calendar][:id]
    start_date = params[:calendar][:start_date]
    start_time = params[:calendar][:start_time]
    time_zone = params[:calendar][:time_zone]
    lesson_hash = get_module_lectures(module_number)
    # Time.zone = 'America/New_York'
    lesson_hash.each do |days_from_start, lesson_name|
      lesson_datetime = Time.parse("#{start_date} #{start_time}").advance(:days => days_from_start)
      new_event(calendar_id, lesson_datetime, lesson_name, time_zone)
    end
    redirect_to calendars_url
  end

  def new_event(calendar_id, lesson_datetime, lesson_name, time_zone)
      client = Signet::OAuth2::Client.new(client_options)
      client.update!(session[:authorization])

      service = Google::Apis::CalendarV3::CalendarService.new
      service.authorization = client


      event = Google::Apis::CalendarV3::Event.new({
        # start: Google::Apis::CalendarV3::EventDateTime.new(datetime: lesson_datetime),
        # end: Google::Apis::CalendarV3::EventDateTime.new(datetime: lesson_datetime.advance(:hours => 1)),
        start: {
          'date_time': lesson_datetime,
          # 'time_zone': 'America/New_York'
        },
        end:{
          'date_time': lesson_datetime.advance(:hours => 1),
          # 'time_zone': 'America/New_York'
        },
        summary: lesson_name
      })
      service.insert_event(calendar_id, event)

    end

As you can see, I've tried hard-coding the time zone in a few places for testing but none of them seem to have any effect on the events created--they're always offset by 4 hours. I'm using Rails 5.2

Upvotes: 3

Views: 669

Answers (1)

gwcodes
gwcodes

Reputation: 5690

The DateTime must be set up with the TimeZone:

lesson_hash.each do |days_from_start, lesson_name|
  lesson_datetime = ActiveSupport::TimeZone["America/New_York"].parse("#{start_date} #{start_time}").advance(:days => days_from_start)
  new_event(calendar_id, lesson_datetime, lesson_name, time_zone)
end

The time needs to be formatted correctly. Try this:

event = Google::Apis::CalendarV3::Event.new(
  start: Google::Apis::CalendarV3::EventDateTime.new(date_time: lesson_datetime.to_datetime.rfc3339),
  end: Google::Apis::CalendarV3::EventDateTime.new(date_time: lesson_datetime.advance(:hours => 1).to_datetime.rfc3339),
  summary: lesson_name
)
service.insert_event(calendar_id, event)

Upvotes: 2

Related Questions