Schleichermann
Schleichermann

Reputation: 1156

Rails 5 API: Globally Set config.time_zone to UTC

Rails 5.0.2 API only application running on Ruby 2.4.1.

  1. Set time_zone in config to "UTC"
  2. Set ActiveRecord default_timezone to :utc
  3. Application restarted multiple times after the config change

application.rb

config.time_zone = "UTC"
config.active_record.default_timezone = :utc

Model query

weight_entry = @current_user.weight_entries
                            .where(taken_on: Time.now.beginning_of_day..Time.now.end_of_day)
                            .first

Executes the following query

WeightEntry Load (3.2ms)  SELECT  "weight_entries".* 
FROM "weight_entries" WHERE "weight_entries"."user_id" = $1 
AND ("weight_entries"."taken_on" BETWEEN $2 AND $3) 
ORDER BY "weight_entries"."id" 
ASC LIMIT $4  [["user_id", 3], 
["taken_on", 2017-06-07 06:00:00 UTC], 
["taken_on", 2017-06-08 05:59:59 UTC], ["LIMIT", 1]]

As you can see, despite setting UTC globally, the ActiveRecord query against the database is still using an offset (6 hours) in the time component:

["taken_on", 2017-06-07 06:00:00 UTC], 
["taken_on", 2017-06-08 05:59:59 UTC], ["LIMIT", 1]]

I expect, with UTC being the default across the application, that the timestamps would look more like this:

["taken_on", 2017-06-07 00:00:00 UTC], 
["taken_on", 2017-06-08 23:59:59 UTC], ["LIMIT", 1]]

If I change the model query to this (inserting utc manually):

weight_entry = @current_user.weight_entries
                        .where(taken_on: Time.now.utc.beginning_of_day..Time.now.utc.end_of_day)
                        .first

I get the expected results:

["taken_on", 2017-06-07 00:00:00 UTC], 
["taken_on", 2017-06-08 23:59:59 UTC], ["LIMIT", 1]]

Do I really need to insert .utc every time I use a time element when inserting and querying the database via Rails, even though I have set UTC as the default timezone?

What am I missing here?

Upvotes: 2

Views: 4888

Answers (1)

Shani
Shani

Reputation: 2541

you should use Time.zone.now instead of Time.now or Time.now.utc

Good explanation here

https://rails-bestpractices.com/posts/2014/10/22/use-time-zone-now-instead-of-time-now/

http://danilenko.org/2012/7/6/rails_timezones/

Upvotes: 5

Related Questions