Almost all the web apps that I work with these days allow user to set their own timezone. Rails makes it really easy with all the Active Support timezone goodies.
One just needs to save the user's timezone in database and then it can be easily changed in the controller action per user session.
Time and time again, I have come across code which actually changes the application's timezone while trying to change the user's time zone.
before_action :set_current_user_timezone
def set_current_user_timezone
if current_user
Time.zone = current_user.time_zone
end
end
I have also come across code in other parts of the application which changes timezone as well.
Time.zone = user.time_zone
SyncUserData.new(user).process
This is even more dangerous because nobody knows what code will followup these two lines and it can run into weird issues because of using user's time zone instead of app time zone.
Instead a better way is to use Time.use_zone
which accepts a block and returns to the original timezone after the end of the block.
def perform_in_users_timezone(user)
Time.use_zone(user.time_zone) do
# perform
end
end
This is much better solution as we are hundred percent sure, that the change of timezone is only happening inside the block and there is no chance at all of it leaking out in other parts of the code.
Our original example of changing user's timezone per request can be achieved with the help of around_action
callback along with Time.use_zone
.
around_action :set_current_user_timezone
def set_current_user_timezone
if current_user
Time.use_zone(user.time_zone) { yield }
else
yield
end
end
So to recap, avoid setting time zone using Time.zone=
as much as possible. I will go ahead and say that just don't do it! Always use Time.use_zone.
Top comments (0)