I have legacy postgresql database, and following settings in config/application.rb:
config.time_zone = 'Volgograd'
In rails console:
$ rails c
Loading development environment (Rails 3.2.1)
irb(main):001:0> Application.where(contract_id: 287572).first
=> #<Application ... created_at: "2011-12-30 09:27:23" ... >
irb(main):002:0> Application.where(contract_id: 287572).first.created_at
=> Fri, 30 Dec 2011 13:27:23 MSK +04:00
That's not ok, and this is what I actually see in the view.
irb(main):003:0> Application.where(contract_id: 287572).first.created_at.localtime
=> 2011-12-30 13:27:23 +0400
irb(main):004:0> Application.where(contract_id: 287572).first.created_at.utc
=> Fri, 30 Dec 2011 09:27:23 +0000
I expect, that .localtime method should return 09:27:23, but it is .utc which returns correct value for me.
And I can't use just created_at without any additional methods in my view. In views, it is almost ok, but it is the real trouble when ActiveAdmin is used.
According to documentation, default_timezone should be set to either :local or :utc (default is :local which means that database timestamps are treated to be in your app's timezone). I have config.time_zone set to Moscow and here is how it works for me
=> Mon, 06 Feb 2012 11:11:52 MSK +04:00
> ActiveRecord::Base.default_timezone = :utc
=> Mon, 06 Feb 2012 15:11:52 MSK +04:00
Any other options like your 'GMT-04:00' are just treated same as :utc.
So, if you have timestamps in your database stored in GMT+4, try setting default_timezone to :local or just removing the line.
Thank you for pointing out to documentation.
I tried to set different timezones and found that 'GMT-04:00' is not exactly the same with :utc. It gives same result when Application.where(contract_id: 287572).first.created_at is called, but in postgresql log, I see "SET time zone 'UTC'" only when :uts is set. Maybe it is ok, because if you use undocumented settings, you can expect unpredictable result :)
But something is wrong with :local setting: it is not set by default. No "SET time zone" translated to database (in both cases), and result is not the same for commented-out "config.active_record.default_timezone":
=> Fri, 30 Dec 2011 13:27:23 MSK +04:00
and for config.active_record.default_timezone = :local
=> Fri, 30 Dec 2011 09:27:23 MSK +04:00
Have you tried ―
I think Rails is going to store in the database in UTC format. After extracting out of the DB you can change the timezone. I have User preferred time zone settings so I use a before filter like so:
Time.zone = current_user.timezone.presence || "UTC"
I know this doesn't exactly answer your question but I hope it helps.
@tycoon: Default for ActiveRecord::Base.default_timezone is actually :utc, not :local. The API documentation is incorrect, but the edge documentation is up-to-date.
@rohit: my trouble with timezones was completely solved by using "config.active_record.default_timezone = :local", but your approach can be useful for dynamic timezone changes, thanks!
@denispeplin Awesome! Can you please close this issue? Thanks.
@rohit: there is still error in API documentation, should I close this issue now?
@denispeplin As Radar mentioned above the documentation is incorrect but the edge documentation is fixed. Please confirm that it's okay ― https://github.com/rails/rails/blob/master/activerecord/lib/active_record/core.rb#L46-50
When a Rails release happens the documentation will also be updated on http://api.rubyonrails.org
I don't completely understand how it works.
The documentation is built from code, right? But how it happens that in 3-2-stable branch default_timezone is still local? Look at this code:
In 3-2-stable it is set to local, but in master it is set to UTC. Documentation on api.rubyonrails.org is for latest stable. IMO the correct default is :utc.
It does not seems actually :local. I checked it with 3.2.1 and 3.1.3, both works like it is set to :utc.
Loading development environment (Rails 3.1.3)
Loading development environment (Rails 3.2.2)
@denispeplin Hey is this issue resolved? If yes can you close it? :)