September 19, 2017
This blog is part of our Ruby 2.4 series.
In Ruby, DateTime#to_time
and Time#to_time
methods can be used to return a
Time object.
In Ruby 2.3, these methods convert time into system timezone offset instead of preserving timezone offset of the receiver.
> datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z')
#=> #<DateTime: 2017-05-16T10:15:30+09:00 ((2457890j,4530s,0n),+32400s,2299161j)>
> datetime.to_time
#=> 2017-05-16 06:45:30 +0530
> time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00')
#=> 2017-05-16 10:15:30 +0900
> time.to_time
#=> 2017-05-16 06:45:30 +0530
As you can see, DateTime#to_time
and Time#to_time
methods return time in
system timezone offset +0530
.
Ruby 2.4 fixed DateTime#to_time and Time#to_time.
Now, DateTime#to_time
and Time#to_time
preserve receiver's timezone offset
info.
> datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z')
#=> #<DateTime: 2017-05-16T10:15:30+09:00 ((2457890j,4530s,0n),+32400s,2299161j)>
> datetime.to_time
#=> 2017-05-16 10:15:30 +0900
> time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00')
#=> 2017-05-16 10:15:30 +0900
> time.to_time
#=> 2017-05-16 10:15:30 +0900
Since this is a breaking change for Rails application upgrading to ruby 2.4,
Rails 4.2.8 built a compatibility layer by adding a
config option.
ActiveSupport.to_time_preserves_timezone
was added to control how to_time
handles timezone offsets.
Here is an example of how application behaves when to_time_preserves_timezone
is set to false
.
> ActiveSupport.to_time_preserves_timezone = false
> datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z')
#=> Tue, 16 May 2017 10:15:30 +0900
> datetime.to_time
#=> 2017-05-16 06:45:30 +0530
> time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00')
#=> 2017-05-16 10:15:30 +0900
> time.to_time
#=> 2017-05-16 06:45:30 +0530
Here is an example of how application behaves when to_time_preserves_timezone
is set to true
.
> ActiveSupport.to_time_preserves_timezone = true
> datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z')
#=> Tue, 16 May 2017 10:15:30 +0900
> datetime.to_time
#=> 2017-05-16 10:15:30 +0900
> time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00')
#=> 2017-05-16 10:15:30 +0900
> time.to_time
#=> 2017-05-16 10:15:30 +0900
If this blog was helpful, check out our full blog archive.