Issue #14879 has been updated by jeremyevans0 (Jeremy Evans).

Subject changed from Adding/subtracting from time can change utc_offset unexpectedly. to Time#+ and Time#- do not preserve receiver's utc_offset if ENV['TZ'] is modified after receiver is created

ioquatix (Samuel Williams) wrote:
> Jeremy, thanks for your interest.
> 
> Here is a minimal repro:
> 
> ```
> #!/usr/bin/env ruby
> 
> # https://bugs.ruby-lang.org/issues/14879
> require 'time'
> 
> ENV['TZ'] = "Pacific/Auckland"
> time = Time.parse("5pm")
> ENV['TZ'] = "UTC"
> 
> puts time
> puts time.utc_offset
> puts (time + 1).utc_offset
> puts time + 1
> ```
> 
> Thanks for the suggestion regarding `ZoneOffset`. However, that does not seem sufficient for capturing DST rules?

Correct, `Time.parse` doesn't support that.  It uses different timezones for DST rules (e.g. PST and PDT).  In your case you may want NZST and NZDT.

Your example results are due to the fact that you are changing `ENV['TZ']` after creating the `Time` instance, which affects new time instances, and `(time + 1)` creates a new `Time` instance.

Here's a modified example:

~~~ ruby
require 'time'

ENV['TZ'] = "Pacific/Auckland"
time = Time.parse("5pm")
puts time
# 2018-06-30 17:00:00 +1200
puts time.utc_offset
# 43200
puts time + 1
# 2018-06-30 17:00:01 +1200
puts (time + 1).utc_offset
# 43200

ENV['TZ'] = "UTC"
time = Time.parse("5pm")
puts time
# 2018-06-29 17:00:00 +0000
puts time.utc_offset
# 0
puts time + 1
# 2018-06-29 17:00:01 +0000
puts (time + 1).utc_offset
# 0
~~~

I think it is unreasonable to expect `Time#+` and `Time#-` to have special handling for the case where `ENV['TZ']` is modified after the `Time` instance is created, but I'll admit that it is subjective whether the methods should preserve the receiver's `utc_offset` in such cases.  I would say it shouldn't be expected, because `Time#+` and `Time#-` modifies `utc_offset` when crossing DST boundaries, and keeping the same `utc_offset` would lead to undesired behavior:

~~~ ruby
Time.now
# => 2018-06-29 15:13:22 -0700
Time.now - 86400*200
# => 2017-12-11 14:13:30 -0800
~~~

I'm updating the subject to more accurately reflect the issue.

----------------------------------------
Bug #14879: Time#+ and Time#- do not preserve receiver's utc_offset if ENV['TZ'] is modified after receiver is created
https://bugs.ruby-lang.org/issues/14879#change-72723

* Author: ioquatix (Samuel Williams)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: 
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
I have been having some problems with `Time`. When I add or subtract seconds, sometimes the utc_offset is changed unexpectedly.

```
$ ruby -e 'require "time"; puts Time.parse("5pm NZT")'            
2018-06-29 17:00:00 +1200

$ ruby -e 'require "time"; puts Time.parse("5pm NZT") + 1'
2018-06-29 17:00:01 +1200

$ TZ=UTC ruby -e 'require "time"; puts Time.parse("5pm NZT") + 1'
2018-06-29 17:00:01 +0000
```

This seems like strange behaviour. The `utc_offset` shouldn't change IMHO.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>