Rails 7 fixes timezone awareness for tsrange and tstzrange columns
source link: https://blog.saeloun.com/2022/11/17/tsrange-timezone-bug
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Postgres has a fantastic collection of column types
that makes it easy to store custom data.
One such type are Ranges which allow you to store a range of values.
For example, you can store a range of dates or a range of integers.
When it comes to storing a range of timestamps, Postgres provides the tsrange
and tstzrange
column types which store a range of timestamps with
and without timezones respectively.
Before
Let’s create a column in a Rails module to store a range of timestamps.
# First we create a migration to add the column
class AddTimestampRangeToEmployees < ActiveRecord::Migration[7.0]
def change
add_column :employees, :tenure, :tsrange, array: true
end
end
Now let’s store a range of timestamps in this column.
➜ rails c
Loading development environment (Rails 7.0.2)
irb(main):001:0> Employee.create!(tenure: 5.years.ago..DateTime.yesterday, name: "John")
=> #<Employee id: 1, tenure: ["2017-11-03 14:10:17.844978 UTC", "2022-11-03 14:10:17.844978 UTC"], name: "John">
This works as expected.
However, if we set a timezone in the application config
(and then make tsrange
timezone aware),
we get a TypeError.
# config/application.rb
config.time_zone = "Asia/Kolkata"
ActiveRecord::Base.time_zone_aware_types += [:tsrange]
Now let’s try again!
➜ rails c
Loading development environment (Rails 7.0.2)
irb(main):001:0> Employee.create!(tenure: 5.years.ago..DateTime.yesterday, name: "John")
/Users/swaathi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/core_ext/range/each.rb:19:in `ensure_iteration_allowed': can't iterate from ActiveSupport::TimeWithZone (TypeError)
/Users/swaathi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/core_ext/range/each.rb:19:in `ensure_iteration_allowed': can't iterate from ActiveSupport::TimeWithZone (TypeError)
After
Thanks to this PR, the app timezone is now retained when storing a range of timestamps. Let’s try again!
➜ rails c
Loading development environment (Rails 7.0.2)
irb(main):001:0> Employee.create!(tenure: 5.years.ago..DateTime.yesterday, name: "John")
=> #<Employee id: 1, tenure: ["2017-11-03 13:36:14.419774000 IST +05:30", "2022-11-03 13:36:14.419774000 IST +05:30"], name: "John">
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK