#106 Time Zones in Rails 2.1
In the past, time zones have been very difficult to work with, but no longer! Rails 2.1 brings with it great time zone support as you can see in this episode.
- Download:
- source codeProject Files in Zip (132 KB)
- mp4Full Size H.264 Video (8.07 MB)
- m4vSmaller H.264 Video (5.83 MB)
- webmFull Size VP8 Video (17.3 MB)
- ogvFull Size Theora Video (11.1 MB)
What happens if in time_zone_select you want a different set of Zones to be up the top (i.e a non US application)
This's what I waiting for :) Thanks
I feel very bad when I see such shortcut : #us_zones. US is not the center of the world.
Do we still think that US is more important than other countries ? Why not #russia_zones or #china_zones ? or at least #euro_zones ? or if we really want to be america centric why not #canada_zones ?
We shouldn't have such shortcut in the core, we should *never* have US be a prioritized value or even a default value. This is very bad practice.
Worse, we have a #us_zones and we don't even have a #utc_timezone or #gmt_timezone shortcut.
lolz. then contribute one if you like. :)
Why exactly are you so worked up over this issue? There are rake tasks for all timezones and one that guesses your local timezone based on your system time.
While I agree having some degree of internationalization would be nice Rails has many other instances where specific internationalization support is not offered. The timezone Internationalization issue isn't really out of line with the existing core development philosophy.
exactly what i was waiting for :P thx
When you use the time_zone_select in Rails 2.1 it also displays the time zones as an offset from UTC rather than GMT.
e.g. "(UTC-10:00) Hawaii" instead of "(GMT-10:00) Hawaii"
Its only a minor point, but UTC wont mean much to end users whereas GMT would.
Does anyone know if you can change this?
@Eric, I would like to see more support for international users as well. Please do consider submitting a ticket/patch on this.
@David, this is actually generated by the TimeZone#to_s method, so you can override that if you want something different. That feels a bit hackish, so alternatively you can subclass TimeZone and pass that to the select field. I'm not sure if this will work though:
http://pastie.caboo.se/196823
You may want to submit ticket/patch for this.
No need for the tzinfo gem?
In reply to myself, it's bundled in Rails 2.1: http://mad.ly/2008/04/09/rails-21-time-zone-support-an-overview/#more-26
Bliss.
I'm still having the sound issues with this one. Does anyone else have a problem right about 37 seconds into the cast?
Thanks again Ryan. I've turned to your site a primary source of learning rails ideas (and rails in general).
Have you (would you) consider posting the projects you use in the screen casts on your site?
I know there are many times, I would love to be able to peer through the code itself (in the event I missed you explaining something previously).
@Matt, I'm just starting to do this actually. You can find the code here:
http://github.com/ryanb/railscasts-episodes/
Quoting one of my favorite simpsons episodes:
"Dear die hard...you rock! P.S. Do you know mad max?"
Seriously...you rock.
I hope time zone support is good in Active Resource for rails 2.1. A lot of bugs existed in 2.0.2.
In the before filter, you change the value of Time.zone, does it automatically get changed back at the end of the request? So if a logged in user with their time zone set to a Russian TZ logs in and then an non-logged in user goes to the site immediately after that, do they see the previous user's time zone?
@Arya, good question. I believe Time.zone does reset when the request ends. I have read this elsewhere. However I honestly have not fully tested it.
@Ryan: excellent screencast!
@Arya: when you set Time.zone, this zone is stored in the Thread.current hash, so there's no possibility that the zone set for one request will leak into another.
@David: regarding TimeZone#to_s, I'm actually inclined to change this back to showing GMT -- I've started a thread about this on the Rails Core list.
I recently implemented time zone support using Rails 2.0.2 and TzInfo and I think it uses different time zone names or am I incorrect? If so, is there then a way of converting my existing user accounts to use the other, default time zone names?
The new timezone support is really good, however so far I prefer to write out times in UTC and then to use javascript to substitute the correct time using the timezone set on the client. This of cause requires the clients timezone to be set correctly, but that is usually the case I think.
I prefer this solution for two reasons:
1. No need for the user to set his timezone in the app.
2. People are travelling a lot nowadays. When I'm opening a website while in a different country, I like to see times in local time, not my "home" time.
Maybe it is also possible to first render the page without the times and then using a remote call to pass in the user timezone to the rails app which than renders the correct times using ajax. However, the javascript client site solution is probably faster as it saves the second server request.
Anyone know why the following code defaults to selecting the UTC time zone (instead of the config.time_zone or Time.zone setting):
<code>
<%= f.time_zone_select :time_zone, TimeZone.us_zones %>
</code>
Many thanks,
Chris
some ActiveRecord caveat to care about regarding UTC conversions:
>> time_str = "2008-07-30T09:44:28+02:00"
>> time = Time.parse time_str
if used then like this:
>> XXX.find_all_by_YYY('yyy', :conditions => ["created_at >= ?", time_str])
you see this query in the log:
SELECT * FROM "XXX" WHERE (created_at >= '2008-07-30T09:44:28+02:00')
same happens with:
>> XXX.find_all_by_YYY('yyy', :conditions => ["created_at >= ?", time])
in the mean time, USE this:
>> XXX.find_all_by_YYY('yyy', :conditions => ["created_at >= ?", time.utc])
then you get this perfectly in the log:
SELECT * FROM "messages" WHERE (created_at >= '2008-07-30 07:44:28')
Is there any way to get the name of the zone DateTime object is in that is in the format used by 'in_time_zone'?
I want to do datetime1.in_time_zone(datetime2.zone) but zone method returns the name in a different format.
I would have thought this to be trivial, but I've been banging my head for hours and can't find a clean way to convert one DateTime to another DateTime's zone.
Ultimately, I want to compare two DateTimes after taking the time zone into account. A normal comparison doesn't seem to do it: start_date_time < 1.hours.from_now doesn't work if the user is in a different time zone from the server.
I'm getting the following error on my view:
"uninitialized constant ActionView::Base::CompiledTemplates::TimeZone"
If I remove the TimeZone.us_zones parameter from the selection list the error goes away -- but then I get all time zones in the list. Any idea what could be wrong?
I'm using Rails 2.2.2 so maybe there's an issue with this version.
Found the answer to my own question.
In Rails 2.2.2 TimeZone lives in ActiveSupport, so I had to change the parameter to:
ActiveSupport::TimeZone.us_zones
I've got a strange problem: I followed these steps, and everything works perfectly when I save to the db and pull records out of the db: that nice Pacific Time translation happens automatically.
The problem is that when I use Time.now I get Pacific Time -0800, which is a double offset! It should either be UTC -0800 or simply Pacific Time. Any thoughts?
Ryan,
As usual great screencast. I borrowed from this teaching some time ago, however, w/Rails 2.3.2 time_zone is no longer a defined method (e.g. NoMethodError (undefined method `time_zone')
...and, thus far, I have wasted 30 minutes trying to find it's equivalent.
Thanks in advance for any pointers,
Jonathan
oops; nevermind, my mistake. Just forget I mentioned it. (my issue was actually the user.time_zone field in the database)
Be careful. Auto-conversion to UTC does not happen in time fields in the database, only datetime, and timestamp.
@Ryan and @Geoff,
Even though Time.zone is thread-local, that won't prevent it from leaking from one request to a subsequent request on the same thread.
Here's the fix for that:
https://gist.github.com/809775
I just went through and followed this for a Rails 3.1.1 app. It was a great help with the appropriate pointers. What I found with my 3.1.1 usage was:
1) I had to adjust the config/environment.rb line(s).
Myappname::Application.configure do
config.time_zone = "Eastern Time (US & Canada)"
end
2) I am using simple form and found that just <%= f.input :time_zone %> does the automagic for me, which was a treat
Thanks for the great content! The 'classic' episodes remain a useful reference.