Do not set Time.zone to avoid timezone issues in Rails
Setting Time.zone
in a Rails application changes time zone globally.
Whenever Time.now
is used in any other request,
it uses whatever Time.zone is set to earlier.
To avoid Time.zone issues, do not set Time.zone
.
Instead, use in_time_zone
method to get time in desired zone.
Problem
The other day when going through code,
found out a method with an argument time_zone
.
The time_zone
argument was used to set Time.zone
.
The code below Time zone set, was calculating some times,
which required the zone to be used which was passed in as an argument.
def perform_something_at(time_zone)
Time.zone = time_zone
some_date = Time.zone.yesterday.to_date
# process(some_date)
end
Setting Time.zone
sets the time zone,
and
is changed at application level.
This causes time zone issues at other places.
As other places do not want Time.zone
to be changed dynamically.
Solution: Avoid Setting Time.zone
To resolve, the problem at all other plcaes, we started using in_time_zone method.
Usage
time = Time.now
time = time.in_time_zone('Asia/Kolkata')
# Use time for whatever processing
Listing down the source code of the in_time_zone
method.
# File activesupport/lib/active_support/core_ext/date_and_time/zones.rb, line 19
def in_time_zone(zone = ::Time.zone)
time_zone = ::Time.find_zone! zone
time = acts_like?(:time) ? self : nil
if time_zone
time_with_zone(time, time_zone)
else
time || self.to_time
end
end
This returns TimeWithZone
object in time zone passed to it as an argument.
in_time_zone
method is available on
DateTime
and
Date
as well.
Summary
- Practice using
in_time_zone
zone to convert Time in the desired zone. - Use
Time.current
instead ofTime.now
if you prefer everything in UTC. - Use
DateTime.current
instead ofDateTime.now
if you prefer everything in UTC.
Subscribe to Ruby in Rails
Get the latest posts delivered right to your inbox
