Rails and timezone in created_at - ruby-on-rails

ruby-1.9.2-p0 > SalesData.last
=> #<SalesData id: 196347, created_at: "2011-04-05 18:53:15", updated_at: "2011-04-05 18:53:15">
ruby-1.9.2-p0 > SalesData.last.created_at
=> Tue, 05 Apr 2011 20:53:21 CEST +02:00
application.rb:
config.time_zone = 'Copenhagen'
I don't get it - anyone?

I assume you're asking why the created_at datetimestamps appear to differ. In short, they don't.
Rails always stores datetimes in UTC, converting them to your configured timezone on the fly while loading the record. I don't know exactly when that conversion happens, but I'm betting you're just seeing those two states.

Related

Rails app not following the timezone configured in config/application.rb

I'm new to configuring timezones and confused about a few points. Any advice on the correct configuration would be appreciated.
My understanding is that it's best practice to store all timestamps as UTC in the DB (I'm using PostgreSQL). On the other hand, in the actual app, I'd like to see the timestamps in my local timezone (JST +9:00).
I've configured config/application.rb like this:
module MyApp
class Application < Rails::Application
config.load_defaults 5.2
config.time_zone = 'Tokyo'
end
end
However, I'm not sure it's configured correctly, because I'm getting mixed results in the rails console. Time.zone and Time.now tell me the timezone is set to JST, but the created_at and updated_at timestamps are rendered as UTC when I do User.first.
User.first
#=> #<User id: 1, first_name: "Bob", last_name: "Smith", created_at: "2019-04-09 08:54:30", updated_at: "2019-04-09 08:54:30">
But then, the time is rendered as JST if I specifically ask for the created_at time:
User.first.created_at
#=> Tue, 09 Apr 2019 17:54:30 JST +09:00
Why are the timestamps being rendered as UTC unless I specifically ask for the time itself? Is this normal? The same phenomenon is happening for DateTime columns in my other tables as well.
All your dates seems to be the same, it's just how they are represented on different contexts.
This:
User.first
#=> #<User id: 1, first_name: "Bob", last_name: "Smith", created_at: "2019-04-09 08:54:30", updated_at: "2019-04-09 08:54:30">
renders the result of .inspect
This:
User.first.created_at
#=> Tue, 09 Apr 2019 17:54:30 JST +09:00
is the console guessing you want the date formated with the current time zone.
You could force some representation being explicit
User.first.created_at.to_formatted_s(:db) #should print the same as you see on the inspect
I18n.localize(User.first.created_at) #should localize the date with the default date format
I18n.localize(USer.first.created_at, format: :something) #should localize the date as the format you defined as ":something" on your locale file

Rails model attribute (a DateTime) has different value depending on how its called

I am using Rails 4.2 and Ruby 2.2.0. I have a model called Ride that has a DateTime attribute called start_time. When I call Ride.find(1803), The start_time is shown as January 9th. But when I call Ride.find(1803).start_time, It returns a start_time on January 9th. How is this possible and how do I fix it? Here's the full code I ran in the console:
irb(main):028:0> Ride.find(1803)
=> #<Ride id: 1803, start_time: "2016-01-09 00:00:00", end_time: nil, created_at: "2016-01-05 16:55:44", updated_at: "2016-01-05 20:35:38", user_id: 29, ride_type: nil, horse_id: nil, notes: "", available_to_ride_additional_horses: nil, admin_approved: false, weekday: nil, unavailable_to_ride: false, time_range_dropdown: "Morning", rider_name: "Matti Fisher", rider_last_name: "Fisher", rider_first_name: "Matti", edited_at: nil, requested_time: "2016-01-09 19:30:00">
irb(main):029:0> Ride.find(1803).start_time
=> Fri, 08 Jan 2016 19:00:00 EST -05:00
This is because a date/time value is stored in the database as UTC and the default implementation of inspect for an ActiveRecord model doesn't apply any timezone conversion.
However, when you access the date/time value, Rails will apply the current timezone settings.
You can do the math. Since your timezone is UTC-5, both datetime represent the same object
2016-01-09 00:00:00 UTC
Fri, 08 Jan 2016 19:00:00 EST -05:00
As a proof, you can call
Ride.find(1803).start_time.utc
and you will get the date/time as UTC, that will probably be the same value you see when you print out the full record representation.

Ruby String to_time broken?

I would expect Time and to_time to be reflective.
UPDATE
This is the answer, if you add the parameter :local, it doesn't ignore the offset. I find it wierd that it ignores data (the offset) by default, though...
Time.zone.now.to_s.to_time(:local) returns 2012-03-20 14:39:03 +0100
/UPDATE
> Time.zone.now.to_s
=> "2012-03-20 12:50:05 +0100"
> Time.zone.now.to_s.to_time.to_s
=> "2012-03-20 12:50:05 UTC"
# PROBLEM:
# UTC is +0000, meaning that there is 1 hour diff in the above
> Time.zone.now
=> Tue, 20 Mar 2012 12:51:32 CET +01:00
> Time.zone.now.to_time
=> Tue, 20 Mar 2012 12:51:32 CET +01:00
> Time.zone.now.to_json
=> "\"2012-03-20T12:50:36+01:00\""
> Time.zone.now.to_json.to_time
=> 2012-03-20 12:50:36 UTC
I have this problem with JSON messages. Anyway, I wouldn't expect to_time to actually change the time. OK to translate to UTC, probably, but it should adjust time accordingly. Anybody know if this is a known issue or "by design"?
This method, String#to_time, defined in ActiveSupport takes one parameter, form, which can be either :utc (default) or :local. So by default, it always returns a Time in UTC.
To get a Time with timezone:
Time.zone.parse("2012-03-20T12:50:36+01:00")

Daylight Savings Time not calculated properly in Rails 2.3.5?

I have a very strange issue with Daylight Savings Time (DST) in my app. For some reason, whenever I receive a time from the table, it doesn't adjust itself for DST. For example, if I create a new Time in the console, in the appropriate time zone, write it to the database, and then try to retrieve it from the database, it comes back as one hour earlier.
Here's an example:
Here, we can see that using the console, creating a new Time at 15:00 EST is equal to 19:00 UTC (since adjusted for DST, which makes it -0400 instead of the usual -0500):
ruby-1.8.6-p114 > Time.zone
=> #<ActiveSupport::TimeZone:0x12b1b68 #name="UTC", #tzinfo=nil, #utc_offset=0>
ruby-1.8.6-p114 > Time.zone = "Eastern Time (US & Canada)"
=> "Eastern Time (US & Canada)"
ruby-1.8.6-p114 > Time.zone.parse("15:00")
=> Thu, 09 Sep 2010 15:00:00 EDT -04:00
ruby-1.8.6-p114 > Time.zone.parse("15:00").utc
=> Thu Sep 09 19:00:00 UTC 2010
ruby-1.8.6-p114 > Time.zone.parse("15:00").dst?
=> true
Now, I try to write that same time to the database, and retrieve it back:
ruby-1.8.6-p114 > b = Book.new
=> #<Book id: nil, return_time: nil, created_at: nil, updated_at: nil>
ruby-1.8.6-p114 > b.return_time = Time.zone.parse("15:00")
=> Thu, 09 Sep 2010 15:00:00 EDT -04:00
ruby-1.8.6-p114 > b.save
=> true
ruby-1.8.6-p114 > result = Book.find(:last).return_time
=> Sat Jan 01 19:00:00 UTC 2000
ruby-1.8.6-p114 > result.zone
=> "UTC"
ruby-1.8.6-p114 > result.in_time_zone
=> Sat, 01 Jan 2000 14:00:00 EST -05:00
ruby-1.8.6-p114 > result.dst?
=> false
My environment.rb has this:
config.time_zone = 'UTC'
And application_controller.rb has this:
before_filter :set_user_time_zone
def set_user_time_zone
if current_user
Time.zone = current_user.time_zone
else
Rails.logger.error '[Time.zone.now.to_s][ERROR]: Missing current_user from in set_user_time_zone!'
end
end
Any ideas as to what could be happening here and how to fix it? I've been at this for days now, so really, any help would be greatly appreciated!
Thank you very much.
It looks like you're only saving the time portion; note how the date part goes from Thu, 09 Sep 2010 to Sat, 01 Jan 2000. Since the DST calculation depends on the date, this is probably where you're losing the information. (January 1st is not in DST, so assuming that date, the DST calculation is correct). You probably need to save a DATETIME in the database, not just TIME.
I'm not sure what version of Rails you're using, but I had the same problem in 2.1.2. It seems the time zone library included just doesn't work half the year, but the developers didn't think it was worth switching; hopefully they've rethought that decision by now.
In any case, we ended up using the tzinfo_timezone plugin, which computes UTC offsets correctly during daylight savings time.

Weird created_at behavior

I've set config.time_zone = 'UTC' in environment.rb, and yet still I get some weird behavior with Rails' built-in datetime fields:
>> Time.now
=> Sun Jun 21 17:05:59 -0700 2009
>> Feedback.create(:body => "testing")
=> #<Feedback id: 23, body: "testing", email_address: nil, name: nil, created_at: "2009-06-22 00:06:09", updated_at: "2009-06-22 00:06:09">
>> Time.parse(Feedback.last.created_at.to_s)
=> Mon Jun 22 00:06:09 UTC 2009
Any thoughts?
It looks like it's properly setting the timezone in the ActiveRecord object, so I don't think you need to worry too much. If you want to force your timestamp from Rails to use UTC, you can use Time.utc.
Time.now.utc
=> Mon Jun 22 00:54:21 UTC 2009

Resources