Rails 2.2 has straightforward, plugin-free support for timezones and localization. Woot to rails core, goodbye to tzinfo.
But what if you need to use a variable using a MySQL::time column – like lunch_time that describes a time of day? Lets use the example of an ActiveRecord class Schedule with a column lunch_time. A function like1 2 3 |
def missed_lunch?(sched) Time.zone.now > sched.lunch_time + 30.minutes end |
doesn’t work. Why? MySQL::time columns are 24-hour naked times (like 13:30:04), with no zone, date, or AM/PM within MySQL. When loaded by AR the column is converted into a Ruby::Time object in UTC time on 1/1/2000, since Ruby has no native time_of_day-like class. 9:15 (in MySQL::time) becomes Sat Jan 01 9:15:00 UTC 2000 ( in ruby Time).
Time.zone.now). It’s best to tackle this problem at the model level, so the rest of our code can deal with time_of_day consistently. We extend ruby Time with a method to convert unruly MySQL::time columns into local-zone, ‘today’ times:
1 2 3 4 5 |
class Time
def from_mysql_time
return Time.zone.now.change(:hour => self.hour, :min => self.min, :sec => self.sec)
end
end |
1 2 3 4 5 6 7 |
class Schedule < ActiveRecord::Base
# lunch_time time
(...)
def lunch_time
read_attribute(:lunch_time).from_mysql_time
end
end |
>> Time.zone.now
=> Wed, 11 Mar 2009 11:46:51 EDT -04:00
>> my_sched.lunch_time
=> Wed, 11 Mar 2009 12:30:00 EDT -04:00
>> missed_lunch?(my_sched)
false
This solution works consistenly for all timezones. If your app uses localization, you can relax knowing your time_of_day comparisons will be done correctly in any Time.zone
Leave a Comment