Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: How to get the current user's time zone when using Heroku

I set the time zone of our site on Heroku to Pacific Standard Time (PST) using:

heroku config:add TZ=America/Los_Angeles

Times for users are now always in PST--whether or not they are in the PST time zone.

What's the best way to get the user's actual time zone (i.e. the time zone of where they are physically located)?

I'm guessing that this can be solved using Rails (or Javascript?), as opposed to Heroku.

like image 993
ill_always_be_a_warriors Avatar asked Sep 07 '12 23:09

ill_always_be_a_warriors


3 Answers

There are two ways to do this.

  • Indeed, you can use javascript to fetch their current time/timezone. There is the possibility that the user's computer time is not set correctly, in which case the time zone you display will not be correct.

    Because you are using Rails, a recommended way is to get javascript already bundled as a gem, like detect_timezone_rails. This makes it easy to install (because it is all bundled automatically in the asset pipeline.

  • You can use the IP address to infer their country and time zone. The danger in this case is that a user may be using a proxy. Also, while the IP address generally has city-level resolution, it may be more or less accurate, which may in rare cases give the wrong time zone.

    Using the IP address, you can get their approximate city and latitude/longitude. There are many gems that can do this on Ruby Toolbox, eg. geocoder. With the latitude/longitude, you can get the time zone using a gem like timezone.

You can also use one of the above, and allow the user to manually change their time zone on your website (either storing this setting in a database if registered, or as a cookie on their browser). This is useful in case you got the timezone wrong.

like image 63
ronalchn Avatar answered Oct 22 '22 15:10

ronalchn


There is a couple of ways you could do this depending on how you app is set up. None of which are unique to the Heroku environment.

If your app allows users to sign up then you most probably have a User model, and you may be using the Devise gem for authentication/signup. Add a field to your db (:time_zone) and store the users time zone in this field when they sign up.

>> rails generate migration add_time_zone_to_users time_zone:string
>> rake db:migrate

Rails gives you a handy time_zone_select form helper which gives you a select list with all the Time zones in it which you can display to your user. Add it to the user sign up form and allow the user to set their time zone when signing up. http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/time_zone_select

In your Application Controller you can then do something like this;

before_filter :set_time_zone

def set_time_zone
    #current user is a devise method see https://github.com/plataformatec/devise
    Time.zone = current_user.time_zone if current_user
end

Then when you display a date in your app call .in_time_zone on the time instance which will display the time in the users time zone.

<%= Time.now.in_time_zone %> or <%= @your_model.created_at.in_time_zone %> 

If you don't have user authentication then you could fall back to javascript. To do this you could use the native javascript getTimezoneOffset() on the date object, or even better use the following jsTimezoneDetect plugin:

http://www.pageloom.com/automatic-timezone-detection-with-javascript

Finally you could use a hybrid of both and firstly detect their time zone offset using javascript and then store this value in a rails session/cookie and then use a before_filter to set the Time.zone as above but based on the session time_zone value previously calculated in javascript.

like image 42
ADAM Avatar answered Oct 22 '22 14:10

ADAM


Or you can use this awesome gem https://github.com/kbaum/browser-timezone-rails

like image 42
Mohamed Emad Hegab Avatar answered Oct 22 '22 15:10

Mohamed Emad Hegab