Hey,
I'm Parker.

Ruby 2.2.0 Time#parse TZ-related regression

I was working on adding Ruby 2.2 support to Jekyll, and discovered that the test we have for the timezone option was failing, seemingly inexplicably. After some meandering through the Ruby source code and ChangeLog to determine if the TZ variable was being respected differently, I found no references explicitly to this change. When I walked through how Jekyll uses Time#parse in IRB, I discovered what looks like a pretty major change in 2.2.

In Ruby 2.1, the timezone is converted to the local time (set with the TZ environment variable) automatically:

>> require 'time'
=> true
>> ENV['TZ'] = 'Australia/Melbourne'
=> "Australia/Melbourne"
>> Time.parse("2014-12-29 20:16:32 -0400")
=> 2014-12-30 11:16:32 +1100

But in Ruby 2.2, this was not the case:

>> require 'time'
=> true
>> ENV['TZ'] = 'Australia/Melbourne'
=> "Australia/Melbourne"
>> Time.parse("2014-12-29 20:16:32 -0400")
=> 2014-12-29 20:16:32 -0400 # <== !!! Timezone remains unchanged.
>> Time.parse("2014-12-29 20:16:32 -0400").localtime
=> 2014-12-30 11:16:32 +1100

Go update your gems! Go update your applications! Append #localtime calls anywhere you use Time#parse and want your system timezone respected.

Tangent.

Nobu rejected the above issue I filed, calling this change a bug fix. OK, that seemed weird to me but I could see how this might cause unintended consequences. I asked for a link to the issue that contains the discussion and patches for this change in behaviour. Akira wrote back, saying that there wasn’t one, but that the change was inspired by another bug.

And so ensued the most disheartening experience in my Ruby existence. Issue #9794, the issue Akira referenced, is a bug report filed by a guy named Felipe Contreras. It discusses a discrepancy between Time and DateTime in the #strptime method. While Time.strptime respects timezones when parsing with "%s %z", DateTime.strptime does not. I was looking for a revision which would explain my predicament and ended up reading through the comments, many of which were in Japanese (thanks and no thanks to Google Translate that did very little to help decipher them).

One of the comments referenced Issue #7445, which is basically identical to the #9794. Hmm, weird. It turns out that Felipe filed #7445 about 2 years ago, couldn’t get his point across to Tadayoshi so Tadayoshi just marked it as Rejected and moved on. Felipe, understandably, was frustrated by this. He refiled a year and a half later as #9794 and the argument, again, ensued. It was even discussed over the mailing list. Eventually, after Matz stepped in and called it a ‘feature’, Tadayoshi wrote R45822, a patch for this behaviour. He included an unnecessarily snarky commit message:

a new feature (not a bug fix) of strptime. applies offset even if the given date is not local time (%s and %Q). This is an exceptional feature and I do NOT recommend to use this at all. Thank you git community.

Wow. Tadayoshi was rude, Felipe was rude, and the apparent disinterest in finding a common language was excruciating. Comments flew by one another, Felipe’s in English, others’ in Japanese. Tadayoshi ignored Felipe’s requests to use English. Felipe dismissed Japanese as unacceptable for an “international project”, assuming it must use the Lingua franca of English just because it crosses nation-state borders.

So it seems my problem arose from communication barriers, intense frustration over inconsistency and the apparent lack of ability to see this. And our result: a breaking change between MINOR versions of Ruby, violating SemVer. Ugh.