I was having a doozy of a time implementing TimeZone aware-ness in an application I’m buidling in Rails, until I found some excellent posts (see the bottom for spoiler). Here’s how I did it.
First, let’s make sure you’re storing every date in ActiveRecord in UTC.
You can either set your machine default to be UTC ( in gentoo linux that’s copying over a file from /usr/share/zoneinfo, in OS X, in the System Preferences), or you can setup your default rails environment to use UTC:
in environment.rb:
ActiveRecord::Base.default_timezone = :utc
Now, go and get the TZinfo gem, it’s a fix to the TimeZone support included in Ruby to make it Daylight Savings aware.
you could do:
$ sudo gem install TZInfo
Now add one more line to environment.rb:
Now, let’s say you’ve got a user with a time_zone — this could be as simple as (db migration magic here): add_column :users, :time_zone, :string ) of ‘America/Detroit’.
Add to the User Model:
class User < ActiveRecord::Base
# …
composed_of :tz, :class_name => ‘TZInfo::Timezone’,
:mapping => %w(time_zone time_zone)
end
You can now say (script/console magic here) assuming your something object has the magic created_at datetime field:
something = Something.create
=> # < something :0×22db8d0 @errors=#<activerecord ::Errors:0×22d52a0 @errors={}, @base=# <Something:0×22db8d0 …> >, @attributes={"updated_at"=>Tue Mar 14 15:58:33 UTC 2006, "something"=>"", "created_at"=>Tue Mar 14 15:58:33 UTC 2006}, @new_record_before_save=true, @new_record=false>
user.tz.utc_to_local(something.created_at)
=> Tue Mar 14 10:58:33 UTC 2006
Not there’s still a “UTC” stamp on that bad boy, but now you’ll never show that long format since you’ve got it stored with their Time zone.
Update: You can do:
< %= time_zone_select ‘user’, ‘time_zone’, TZInfo::Timezone.us_zones.sort, :model => TZInfo::Timezone % >
which sorts the us_zones, but hmmm, as for the rest of ‘em, good luck.
How very American, eh?
See Using TZInfo in Rails and the TZInfo - Ruby Timezone Library for more info.