Time zones and durations
Time with an offset
A Time stores an instant and an offset. The offset is part of the value, not a property of the machine, so a time written with +03:00 prints with that offset until it is converted:
ruby -e 'require "time"; puts Time.new(2026, 11, 5, 12, 0, 0, "+03:00").utc.iso8601'
2026-11-05T09:00:00Z
ruby -e 't = Time.new(2026, 11, 5, 12, 0, 0, "+03:00"); p t.utc_offset; p t.utc; p t.getlocal("-05:00")'
10800 2026-11-05 09:00:00 UTC 2026-11-05 04:00:00 -0500
utc_offset is in seconds, utc returns a copy in UTC, and getlocal returns a copy in the offset given. The instant never changes; only the clock face does.
utc and localtime
Store and exchange UTC; convert for a reader. Time.now is in the machine's zone, and .utc is the same instant in the zone a log wants:
ruby -e 'require "time"; puts Time.now.utc.iso8601'
2026-11-05T00:27:39Z
iso8601 from the time standard library is the format to write: it sorts lexically, it carries the offset, and every language parses it. A timestamp without an offset is ambiguous, and an ambiguous timestamp in a shared log is a bug waiting for the first traveller.
Durations with the monotonic clock
A duration is a different question from a date. For "how long did this take" the right clock is the monotonic one, which never jumps when the system time is adjusted:
ruby -e 'start = Process.clock_gettime(Process::CLOCK_MONOTONIC); sleep 0.2; p (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start).round(3)'
0.2
Process.clock_gettime returns seconds as a float. Subtract two readings for a duration, and use Time.now only when the answer is a date or a timestamp someone reads.
Adding and subtracting time
Adding a number to a Time adds seconds, and subtracting two times gives seconds:
ruby -e 'require "time"; t = Time.new(2026, 11, 5, 12, 0, 0, "+00:00"); p (t + 90).strftime("%H:%M:%S"); p ((t + 90) - t)'
"12:01:30"
90.0
Seconds are not days. A day is 86,400 seconds except twice a year in a zone with daylight saving, when it is 82,800 or 90,000. For calendar arithmetic use Date and its >> operator, which the next lesson covers.
What to watch for
Time.now in a test makes the result depend on the
clock. Pass the time in, or freeze it with a helper, so a failure is
reproducible.
A duration measured with Time.now can be negative
when the clock is corrected. The monotonic clock cannot go backwards,
which is why every timing helper uses it.
Next: Parsing and formatting dates
Article author: Arthur Isaev