Read more

Beware when using ActiveSupport time and date calculation methods

Bruno Sedler
April 21, 2023Software engineer at makandra GmbH

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.

Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

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.

Posted by Bruno Sedler to makandra dev (2023-04-21 16:04)