July 11, 2019

Time.use_zone for different timezones in Rails app

Prefer Time.use_zone {} over Time.zone=

Time.use_zone for different timezones in Rails app

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.

Subscribe to my newsletter to know more about such interesting tidbits about how to use Rails effectively.

Happy hacking!