How to set custom time zone in Rails? "-03:30GMT" - ruby-on-rails

I know we can set time zone with
Time.zone = "Eastern Time (US & Canada)"
But how to set with UTC/GMT time, I want to set time zone to -03:30GMT, but I cant find any place which lies in that time zone, so how to set it by giving values?

try this. this will work
Time.zone = -12600

this will give you the full list of timezones from the library
ActiveSupport::TimeZone.zones_map.values.collect { |z| z.tzinfo.name }.compact.uniq.each do |tz|
puts "#{ActiveSupport::TimeZone.seconds_to_utc_offset(Time.now.in_time_zone(tz).utc_offset)}\t#{tz}"
end; nil
I cant find any place which lies in that time zone
It looks like all zones are covered

Related

Rails 4 - how to set a timezone for strftime?

Every user in our database can select his/her own timezone. The default timezone of our application Eastern Time:
config.time_zone = 'Eastern Time (US & Canada)'
config.active_record.default_timezone = 'Eastern Time (US & Canada)'
When I display some dates/times in the application, I usually use for that purpose .strftime. How can I give a parameter to strftime to display the date/time properly (in the given timezone for the specific user)?
Or is there a better way than to format every date/time with using strftime?
EDIT:
Every user has a time_zone string column, where is stored the timezone like this: "Eastern Time (US & Canada)".
As the every date/time will be re-calculated for every timezone, how about the performance? Will this not slow down too much rendering views?
Set your time object in_time_zone() before strftime.
Say you're displaying created_at, you'd do:
object.created_at.in_time_zone(current_user.timezone).strftime("...")

Trouble on handling cookie data with time zones

I am using Ruby on Rails 4 and I would like to handle data present in cookies the proper way. That is, when I store to cookie data as-like (GMT-06:00) Central Time (US & Canada)
cookies.permanent[:time_zone] = "(GMT-06:00) Central Time (US & Canada)"
then in the cookie content it is stored %28GMT-06%3A00%29+Central+Time+%28US+%26+Canada%29.
That way, when I use the cookies[:time_zone] data in my code
Time.use_zone(cookies[:time_zone], &block)
then I get ArgumentError Invalid Timezone: (GMT-06:00) Central Time (US & Canada).
I think the problem is due to the fact that the cookies[:time_zone] data is read from cookies "as it is" (%28GMT-06%3A00%29+Central+Time+%28US+%26+Canada%29), so it generates the error when called in Time.use_zone.
How should I read / write the cookie data?
UPDATE after #Matt Johnson comment
My "hadcode" is
time_zone = cookies[:time_zone] || Time.zone
so that I can use the time_zone variable for my matters. However, I noted that Time.zone returns always
(GMT-06:00) Central Time (US & Canada)
# instead of "Central Time (US & Canada)"
It is the problem: in my "hardcode" when the cookie is nil then Time.zone should return the proper value for my matters, that is Central Time (US & Canada).
So my question become: how should I handle the issue in order to properly set the time_zone variable?
Notes: The Time.zone documentation states that the method
Returns the TimeZone for the current request, if this has been set
(via ::zone=). If Time.zone has not been set for the current request,
returns the TimeZone specified in config.time_zone.
and in my application.rb file I have set
`config.time_zone = 'Central Time (US & Canada)'`
Rails time zones are listed here. In this particular case, you should drop the first part of your string and just pass "Central Time (US & Canada)".
You may also want to read the timezone tag wiki, which has a section about Rails time zones toward the bottom.
Updated Answer
Based on your update, I can see that you are using Time.zone. This doesn't return a string, but returns a TimeZone object. So you are getting the effect of TimeZone.to_s() which includes the GMT portion.
You should instead use Time.zone.name, which just returns the string identifier of the time zone.

How do I get my own TimeZone in ruby?

looking for a way to get my own time zone that I can pass to config.time_zone in application.rb order to set it in Rails. Background: I'm allowing the user to specify their timezone in a yaml config, but if it's not set, I want to explicitly use the box's timezone. I have to have a value set because I'm using it as reference to convert timezones for display -- each user logging into the Rails app can set their personal timezone and I will do the conversion for them.
However, there seems to be no good API for doing this in Ruby or Rails. Time.now.zone returns the 3-letter code (EDT or CDT, for example), but you can't pass this because it's not specific enough -- the TZInfo class will only accept the "long" descriptions.
Here's what I'm doing now, which seems pretty hacky:
time_zone = CONFIG[:time_zone] # set your local time zone here. use rake time:zones:local to choose a value, or use UTC.
unless time_zone
# try to detect one
if File.exists?('/etc/localtime')
path = File.readlink('/etc/localtime')
items = path.split("zoneinfo/")
if items.length == 2
time_zone = items[1]
end
end
unless time_zone
puts "*** Warning: no time zone is set in config/config.yaml and could not detect system time. Using UTC as the default time; behavior may be unexpected."
time_zone = "UTC"
end
end
config.time_zone = time_zone
Any better ideas guys?
Any reason why this wouldn't work?:
Time.now.zone
Edit:
Before getting the zone, you can do Time.now.gmt_offset to get your GMT offset in seconds. After that, you can do Time.now.zone to get your zone code.
You can try the following:
off_set = Time.now.gmt_offset
p ActiveSupport::TimeZone[off_set].name # "Atlantic Time (Canada)"
or
p ActiveSupport::TimeZone[off_set].tzinfo.name # "America/Halifax"
Since the 3-letter codes are not precise enough, have the user specify the full name from the IANA time zone database.
Then you can use Time.zone = 'America/Halifax' (for example).
Time.zone.name returns back the IANA name, and Time.zone.now returns the current time in the specified timezone.
To find the timezone in this format programically, you may be able to use /etc/timezone if it's available. Other systems have other methods (if there is even one available).
If you want the time zone offset in hours, as some databases do (like Postgres), you can use this method:
2.3.1 :063 > Time.zone.formatted_offset
"-07:00"
or this approach if you need the offset in seconds:
2.3.1 :059 > Time.zone.utc_offset
-25200

Ruby: convert "US/Eastern" time zone names to "Central Time (US & Canada)"

I've got an old database with time zone formats like:
US/Eastern
Australia/Melbourne
In my new Rails app, I'm saving them as:
Eastern Time (US & Canada)
Melbourne
How can I convert the old to the new? I've been messing around with ActiveSupport::TimeZone, but can't figure out the right combination to get from one to the other.
I was hoping I could create a new object, then return the newly formatted name, but it just returns the name I gave it. Example:
> tz = ActiveSupport::TimeZone.new("US/Eastern")
=> (GMT-05:00) US/Eastern
> tz.name
=> "US/Eastern"
Thanks in advance!
This is pretty ugly, but it's the only way I've found to do it:
city = TZInfo::Timezone.get('US/Eastern').instance_eval('#linked_timezone').name
ActiveSupport::TimeZone::MAPPING.invert[city]
Edit:
For this code to work with either city or zone, you can do this:
zone = TZInfo::Timezone.get(zone_name)
city = (zone.instance_eval('#linked_timezone') || zone).name
ActiveSupport::TimeZone::MAPPING.invert[city]

Rails and dates, are they stored in UTC by default?

What is the best way for me to handle dates and timezones in rails?
Scenerio: I have customers who purchase products on a website from all over the world, and when they log in they will be able to choose which timezone they are from.
So I believe I should be storing everything in the database at UTC, and then on the front-end I should be converting the dates to the users set timezone preference.
Are their any gotchas with Ruby and Rails and datetimes etc?
I'm new to rails, so I am looking for guidance on how to handle this properly.
Fortunately Rails will pretty much handle things for you. As others pointed out, dates are stored by AR in UTC format. If you have a time_zone field for your users table you can do something like this:
# application.rb
config.time_zone = "Mountain Time (US & Canada)" # Default time zone
-
# application_controller.rb
before_filter :set_time_zone, :if => :logged_in?
protected
def set_time_zone
Time.zone = current_user.time_zone if current_user.time_zone
end
All the datetimes should be shown in the proper time zone in your views.
I have had one production app that didn't like using the default time zone, but I can't remember which version of Rails/Ruby it was running.
Ok so take a look at your config/application.rb file.
You should find commented lines:
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
So default is UTC but you can set whatever ou need there.
Yes, they are. In app, whenever you display date or time for user, everything you need is just adding timezone offset (for example: date + 1.hour for GMT+1). Remember that you need to take care of daylight saving, too. For efficency, consider adding 2 columns in your user table: timezone and time_offset. Then you would on each case do something like
= #order.created_at + session[:user].time_offset
Instead of always checking offset for each timezone set in profile.
I found
rake time:zones:all
to be really useful. It shows a list of offsets and then zone name strings under that. eg:
* UTC +12:00 *
Auckland
Fiji
Kamchatka
Magadan
Marshall Is.
Solomon Is.
Wellington
I needed below in application.rb (not intuitive given default time zone string of "Mountain Time (US & Canada)"):
config.time_zone = 'Wellington'

Resources