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.