Ruby 2.4 DateTime#to_time & Time#to_time keeps info

Sushant Mittal

Sushant Mittal

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.

Ruby 2.3

1
2> datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z')
3 #=> #<DateTime: 2017-05-16T10:15:30+09:00 ((2457890j,4530s,0n),+32400s,2299161j)>
4> datetime.to_time
5 #=> 2017-05-16 06:45:30 +0530
6
7> time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00')
8 #=> 2017-05-16 10:15:30 +0900
9> time.to_time
10 #=> 2017-05-16 06:45:30 +0530
11

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.

Ruby 2.4

1
2> datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z')
3 #=> #<DateTime: 2017-05-16T10:15:30+09:00 ((2457890j,4530s,0n),+32400s,2299161j)>
4> datetime.to_time
5 #=> 2017-05-16 10:15:30 +0900
6
7> time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00')
8 #=> 2017-05-16 10:15:30 +0900
9> time.to_time
10 #=> 2017-05-16 10:15:30 +0900
11

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.

1> ActiveSupport.to_time_preserves_timezone = false
2
3> datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z')
4 #=> Tue, 16 May 2017 10:15:30 +0900
5> datetime.to_time
6 #=> 2017-05-16 06:45:30 +0530
7
8> time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00')
9 #=> 2017-05-16 10:15:30 +0900
10> time.to_time
11 #=> 2017-05-16 06:45:30 +0530

Here is an example of how application behaves when to_time_preserves_timezone is set to true.

1> ActiveSupport.to_time_preserves_timezone = true
2
3> datetime = DateTime.strptime('2017-05-16 10:15:30 +09:00', '%Y-%m-%d %H:%M:%S %Z')
4 #=> Tue, 16 May 2017 10:15:30 +0900
5> datetime.to_time
6 #=> 2017-05-16 10:15:30 +0900
7
8> time = Time.new(2017, 5, 16, 10, 15, 30, '+09:00')
9 #=> 2017-05-16 10:15:30 +0900
10> time.to_time
11 #=> 2017-05-16 10:15:30 +0900

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.