|
This post originated from an RSS feed registered with Ruby Buzz
by rwdaigle.
|
Original Post: What's New in Edge Rails: Easier Timezones
Feed Title: Ryan's Scraps
Feed URL: http://feeds.feedburner.com/RyansScraps
Feed Description: Ryan Daigle's various technically inclined rants along w/ the "What's new in Edge Rails" series.
|
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by rwdaigle
Latest Posts From Ryan's Scraps
|
|
The days of forcing time-zone support into your Rails apps with not one, but two plugins are over. It would appear that Rails now has its own way of dealing with timezones via a custom implementation (though it’s still based on the tzinfo gem).
Here’s the deal. You can now create an ActiveSupport::TimeWithZone from an instance of a UTC-based Time and then switch between time-zones at will:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# Use a UTC time as your base
utc = Time.utc(2000, 1, 1, 0) #=> Sat Jan 01 00:00:00 UTC 2000
# And set the initial timezone
time = ActiveSupport::TimeWithZone.new(utc, TimeZone['Eastern Time (US & Canada)'])
#=> 1999-12-31 19:00:00 -0500
# And now you can display the time in different timezones without changing the time itself
time.in_time_zone('London') #=> 2000-01-01 00:00:00 -0000
time #=> 1999-12-31 19:00:00 -0500
# Or if you do want to change the timezone
time.change_time_zone('London')
time #=> 2000-01-01 00:00:00 -0000 |
So how can we use this new timezone support in the real world – as in our Rails apps where you let users define their own timezone? We can do this using an around filter to set a timezone class variable, much in the same way you’re used to doing:
1
2
3
4
5
6
7
8
9
10
11
12
|
class ApplicationController < ActionController::Base
around_filter :set_timezone
def set_timezone
# current_user.time_zone #=> 'London'
before, Time.zone = Time.zone, Time.get_zone(current_user.time_zone)
yield
ensure
Time.zone = before
end
end |
Now your controller actions and views can access the time in the current (user’s) timezone:
1
2
|
<!-- current_user.registered_at is a UTC datetime -->
<%= TimeWithZone.new(current_user.registered_at).in_current_time_zone %> |
One could easily imagine using a view helper to reduce the verbosity of the above statement:
1
2
3
|
def current_time(utc)
TimeWithZone.new(utc).in_current_time_zone
end |
So you can now do this in your views:
|
<%= current_time(current_user.registered_at) %> |
You can also create a TimeWithZone instance from the local time if you’re not dealing with UTC instances:
1
2
|
# Set the initial time based on the local timezone
time = ActiveSupport::TimeWithZone.new(nil, TimeZone['London'], london_time) |
At the end of the day you’ve got a timezone solution built into Rails that avoids needless dependencies and establishes a common practice for multi-timezone applications.
This was a pretty fragmented post – let me know if you spot any discrepancies or blatant errors.
tags: ruby,
rubyonrails


Read: What's New in Edge Rails: Easier Timezones