If you’re using Ruby and working with timestamps, there is a chance that every now and then, you need a timestamp converted to UTC or back to some other time zone. In such, you probably expect to do timestamp.utc and Ruby doesn’t disappoint. You get the UTC timestamp and you probably continue with something like timestamp.utc.strftime (...) and it seems perfect.
This is till you need to use the timestamp in the local time zone… and you do:
# timestamp is in local time
puts timestamp.utc.strftime('%Y-%m-%d %H:%M') # output the UTC time
puts "Local time: #{timestamp}"
You do this, and for some reason, it does not print it in the local time – it shows it in UTC. This tripped me up for a moment because I thought timestamp should have stayed in local time.
However, you need to know that .utc changes the object itself into the UTC timezone. It does not return a new object that is in UTC, leaving the original intact. It’s almost as if they should have called it utc! because it changes original object. Someone pointed out, though, that it’s expected that it’s not utc! since that’s usually only when there are two versions of a method and one is dangerous while the other one is not.
The documentation on utc if you read it simply says: utc -> self: returns self, converted to the UTC timezone and the code sample shows that it’s UTC now. It’s easy to miss – especially since the method appears to do exactly what you want, so you don’t read the documentation closely enough.

So, what should you use instead?
If you don’t want the object to get changed and want another object that is in UTC, use getutc (or its alias getgm) – it Returns a new Time object representing time in UTC.
The new documentation is a bit clearer on this!

Take care, and pick wisely!
Feel free to connect or share the post (you can tag me as @onghu on X or on Mastodon as @onghu@ruby.social or @onghu.com on Bluesky to discuss more).