Rails app not following the timezone configured in config/application.rb - ruby-on-rails

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

Related

Adding year for all records with update_all

I need to update all records in my model by adding another year before the date saved , seek information and an option is with update_all , I really would help an example with dates update_all database: PostgreSQL
An example:
the saved date is this 15/01/16 after executing the action 01/15/17 and so on all records.
or some other option would be very helpful!
If you use the PostgreSQL database you can use the interval from datetime functions:
$ rails console
=> User.last
=#<User:0x00563c0ed6e0c0
id: 7,
name: "foo",
email: "foo#test.ru",
created_at: Tue, 15 Mar 2016 19:54:52 MSK +03:00,
^^^^
.......
=> User.update_all("created_at = created_at + '1 year'::interval")
=> #<User:0x00563c0c9e4f78
id: 7,
name: "foo",
email: "foo#test.ru",
created_at: Wed, 15 Mar 2017 19:54:52 MSK +03:00,
^^^^
........
If MySQL database you can use the DATE_ADD function.
All of this should work if the column have a right type.

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.

Rails, how to get hours of a datetime in the correct time zone?

I have an offer model. and when I access it from the command line, it is displayed in the following format:
1.9.3p392 :058 > o = Offer.last
=> #<Offer id: 15, title: "Testing", valid_from: "2013-04-12 09:00:00", valid_until: "2013-04-12 14:00:00", created_at: "2013-04-12 18:31:54", updated_at: "2013-04-12 18:31:54">
In this output, valid_from and valid_until are formatted as I would expect. however, when I access them directly, I get something different:
1.9.3p392 :059 > o.valid_from
=> Fri, 12 Apr 2013 05:00:00 EDT -04:00
The issue comes with this function I have inside of app/models/offer_model.rb :
def start_hour
self.valid_from.strftime('%l').to_i unless self.valid_from.nil?
end
When I run this command, with the model above, the output is 5. I would expect it to return 9 in this case. How can I get start_hour to return the hour adjusted for the time zone in this case?
What Time zone are you using in config/application.rb? Rails adjust printed date to the Time Zone set in this file.

Rails and timezone in created_at

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.

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