DEV Community

Prathamesh Sonpatki
Prathamesh Sonpatki

Posted on • Originally published at prathamesh.tech on

Time.use_zone for different timezones in Rails app

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)