4

We have a Rails 4 application . What is the best way to schedule whenever task in rails in midnight usa with daylight saving ?

We need to send email at 11.58pm in night of a day's report .

We are using tzinfo gem

TZInfo::Timezone.get('America/Denver').local_to_utc(Time.parse('11:58pm')).strftime('%H:%M%p')

is not sending email at the time .

Debadatt
  • 5,935
  • 4
  • 27
  • 40

2 Answers2

8

This works around the timezone issue, server is at UTC and users in another time zone (with daylight saving time). define a local action and use in cronjob.

schedule.rb

require "tzinfo"

def local(time)
  TZInfo::Timezone.get('America/Denver').local_to_utc(Time.parse(time))
end

every :sunday, at: local("11:58 pm") do
 #your email sending task
end

hope it will help you.

Community
  • 1
  • 1
Rehan Munir
  • 245
  • 1
  • 3
0

Rehan's answer was SO great! In my use case I ran into an issue where the time zone conversion also changed the day of the week the task would be scheduled for.

Perhaps there is an easier way but here is what I did. The timezone conversion we needed would only advance the weekday. If your use case requires the weekday to be retreated then you will need to edit this, but it should be an easy fix.

def local(time, est_weekday = nil)
  days = [:sunday, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday]
  local_time = Time.parse(time)
  utc_time = TZInfo::Timezone.get('America/New_York').local_to_utc(local_time)
  utc_time_formatted = utc_time.strftime("%I:%M %p")
  if est_weekday && days.include?(est_weekday.downcase.to_sym)
    #extract intended wday for ruby datetime and assign
    weekday_index = days.index(est_weekday.downcase.to_sym)
    #get placeholder wday from desired EST day/time
    temp_est_weekday_index = local_time.wday
    #get placeholder wday from adjusted UTC day/time
    temp_utc_weekday_index = utc_time.wday
    #has the conversion to UTC advanced the wday?
    weekday_advances = temp_utc_weekday_index != temp_est_weekday_index
    #adjust wday index if timezone conversion has advanced weekday
    weekday_index += 1 if weekday_advances
    weekday = days[weekday_index]
    return {time: utc_time_formatted, day: weekday || nil }
  else
    return utc_time_formatted
  end
end
Andrew A.
  • 3
  • 2