After a good few hours of investigating a bug at work yesterday, I came across a weird Ruby feature…. The #utc method on Time objects is destructive and modifies the receiver.
$ irb
ruby-1.8.6-p383 > a = Time.now
=> Wed Apr 14 15:36:21 +0100 2010
ruby-1.8.6-p383 > a.utc
=> Wed Apr 14 14:36:21 UTC 2010
ruby-1.8.6-p383 > a
=> Wed Apr 14 14:36:21 UTC 2010
This is actually
in the Ruby docs, however who reads those? This is kind of unexpected behaviour, as in most cases in Ruby (however this is more of a Rails thing), if there are two methods the more dangerous of the two is suffixed by an exclamation mark. A good example is String#strip and String#strip!. The version without an exclamation mark doesn’t modify the original object, however the version with does:
$ irb
ruby-1.8.6-p383 > a = " hello "
=> " hello "
ruby-1.8.6-p383 > a.strip
=> "hello"
ruby-1.8.6-p383 > a
=> " hello "
ruby-1.8.6-p383 > a.strip!
=> "hello"
ruby-1.8.6-p383 > a
=> "hello"
So if you are going to use #utc, be careful and make sure it you aren’t reliant on the time offset later. You should really be using #dup or #getutc which won’t modify the receiver:
$ irb
ruby-1.8.6-p383 > b = Time.now
=> Wed Apr 14 15:36:59 +0100 2010
ruby-1.8.6-p383 > b.getutc
=> Wed Apr 14 14:36:59 UTC 2010
ruby-1.8.6-p383 > b
=> Wed Apr 14 15:36:59 +0100 2010
This is present in all current versions of Ruby, so upgrading won’t help either!