Beware when using ActiveSupport time and date calculation methods

Updated . Posted . Visible to the public.

The pitfall

Rails Active Support provides some helpful methods for calculating times and dates, like Duration#ago Show archive.org snapshot or Duration#from_now Show archive.org snapshot . But beware when using those, because they wont give you Dates or Times but ActiveSupport::TimeWithZone Show archive.org snapshot instances. As the class name hints, you now have to be aware of timezones, even though you may have decided to make your application timezone unaware.

Moreover, you have to be aware that ActiveSupport::TimeWithZone does not use Rails.application.config.active_record.default_timezone, which you need to define, even if you only use your local timezone, but Rails.application.config.time_zone, which has UTC as default value.

The mitigation

Best case, you have already defined Rails.application.config.time_zone, as we recommend anyway. In this case you don't have to mind the pitfall.
In case your application is already running, and you haven't set a Rails.application.config.time_zone so far, you can always avoid using those methods. However, if your mind is set on using them or you don't want to worry about which methods you should use or not, setting Rails.application.config.time_zone is the only way to go. Before you do so, please compare timestamps for your ActiveRecord models and their representation in your database and make sure they are the same before you set a Rails.application.config.time_zone.

Example

User.find(123).created_at
# => 2023-04-19 13:24:42.90857 +0200
User.connection.select_values("SELECT CAST(updated_at as text) FROM users  WHERE id = 123")
# => ["2023-04-19 13:24:42.90857"]

If those values are not the same, you will corrupt your data by configuring a time zone.

Bruno Sedler
Last edit
Michael Leimstädtner
License
Source code in this card is licensed under the MIT License.
Posted by Bruno Sedler to makandra dev (2023-04-21 14:04)