ZetCode

Ruby Time and Date

last modified October 18, 2026

Ruby provides the Time class for working with points in time and the Date class for calendar dates. This guide covers creating times, accessing components, formatting with strftime, parsing strings, doing arithmetic, and working with dates. All examples use fixed inputs so the output is reproducible.

Creating times with Time.new, Time.utc and Time.at

Time.new builds a local time from components, Time.utc builds a UTC time, and Time.at converts epoch seconds. ENV['TZ'] is set to UTC so local times are reproducible.

ex1.rb
#!/usr/bin/env ruby
ENV['TZ'] = 'UTC'

# Time.new with fixed components
t = Time.new(2024, 3, 15, 10, 30, 0)
puts t.year
puts t.month
puts t.day
puts t.hour
puts t.min
puts t.sec

# Time.utc for a UTC time
u = Time.utc(2024, 3, 15, 10, 30, 0)
puts u.inspect

# Time.at from epoch seconds
e = Time.at(0).utc
puts e.inspect
puts Time.at(1_700_000_000).utc.inspect

Time.new and Time.utc take year, month, day, hour, minute, and second. Time.at(0) is the Unix epoch, and Time.at with a large integer shows the moment 1,700,000,000 seconds after the epoch.

$ ./ex1.rb
2024
3
15
10
30
0
2024-03-15 10:30:00 UTC
1970-01-01 00:00:00 UTC
2023-11-14 22:13:20 UTC

Time accessors

Time objects expose accessor methods for each component. wday counts from Sunday (0) and yday counts from January 1 (1).

ex2.rb
#!/usr/bin/env ruby
ENV['TZ'] = 'UTC'

t = Time.utc(2024, 3, 15, 10, 30, 45)

puts "year:  #{t.year}"
puts "month: #{t.month}"
puts "day:   #{t.day}"
puts "hour:  #{t.hour}"
puts "min:   #{t.min}"
puts "sec:   #{t.sec}"
puts "wday:  #{t.wday}"
puts "yday:  #{t.yday}"
puts "monday? #{t.monday?}"
puts "friday? #{t.friday?}"

Accessors such as year, month, day, hour, and sec return integers. wday returns 5 for Friday, and yday returns 75 for March 15 in a leap year. Predicate methods like friday? return booleans.

$ ./ex2.rb
year:  2024
month: 3
day:   15
hour:  10
min:   30
sec:   45
wday:  5
yday:  75
monday? false
friday? true

Formatting with strftime

strftime formats a Time using % directives. Flags such as - suppress padding.

ex3.rb
#!/usr/bin/env ruby
ENV['TZ'] = 'UTC'

t = Time.utc(2024, 3, 5, 9, 7, 3)

puts t.strftime("%Y-%m-%d %H:%M:%S")
puts t.strftime("%d/%m/%Y")
puts t.strftime("%B %-d, %Y")
puts t.strftime("%A %b %e")
puts t.strftime("%I:%M %p")
puts t.strftime("%j days into the year")
puts t.strftime("%F %T %Z")
puts t.strftime("%%Y is literal")

%Y, %m, %d, %H, %M, and %S produce the date and time fields. %-d removes the leading zero, %p gives AM/PM, and %j gives the day of the year. A literal percent sign is written as %%.

$ ./ex3.rb
2024-03-05 09:07:03
05/03/2024
March 5, 2024
Tuesday Mar  5
09:07 AM
065 days into the year
2024-03-05 09:07:03 UTC
%Y is literal

Parsing with Time.parse and Time.iso8601

The time library adds Time.parse for flexible strings and Time.iso8601 for ISO 8601 strings.

ex4.rb
#!/usr/bin/env ruby
ENV['TZ'] = 'UTC'
require 'time'

t = Time.parse("2024-03-15 10:30:00 UTC")
puts t.inspect

iso = Time.iso8601("2024-03-15T10:30:00Z")
puts iso.inspect

offset = Time.iso8601("2024-03-15T12:30:00+02:00").utc
puts offset.inspect

puts Time.parse("2024-03-15 10:30:00 UTC").iso8601
puts iso.xmlschema(3)

Time.parse reads a human-friendly date string. Time.iso8601 handles offsets such as +02:00, and utc converts the result to UTC. xmlschema and iso8601 format a time back to ISO 8601, with optional fractional digits.

$ ./ex4.rb
2024-03-15 10:30:00 UTC
2024-03-15 10:30:00 UTC
2024-03-15 10:30:00 UTC
2024-03-15T10:30:00Z
2024-03-15T10:30:00.000Z

Time arithmetic and differences

Adding or subtracting numbers from a Time works in seconds. Subtracting two Time objects returns a Float number of seconds.

ex5.rb
#!/usr/bin/env ruby
ENV['TZ'] = 'UTC'

start = Time.utc(2024, 3, 15, 10, 30, 0)

later = start + 3600
puts later.inspect

earlier = start - 90
puts earlier.inspect

finish = Time.utc(2024, 3, 17, 12, 0, 0)
diff = finish - start
puts "Difference in seconds: #{diff}"
puts "Difference in hours: #{diff / 3600}"
puts "Difference in days: #{(diff / 86_400).to_i}"
puts "Is finish later? #{finish > start}"

Adding 3600 moves the time one hour forward and subtracting 90 moves it back 90 seconds. The difference of two Times is a Float in seconds, which is divided to get hours and days.

$ ./ex5.rb
2024-03-15 11:30:00 UTC
2024-03-15 10:28:30 UTC
Difference in seconds: 178200.0
Difference in hours: 49.5
Difference in days: 2
Is finish later? true

The Date class

require 'date' provides Date, which handles calendar dates without a time of day. Date.new, Date.parse, Date#+ and Date#>> are shown with fixed inputs.

ex6.rb
#!/usr/bin/env ruby
require 'date'

d = Date.new(2024, 1, 31)
puts d.to_s
puts (d + 1).to_s
puts (d >> 1).to_s
puts (d << 2).to_s
puts Date.new(2024, 3, 1).strftime("%A, %B %-d, %Y")

parsed = Date.parse("2024-02-28")
puts parsed.to_s
puts (parsed + 2).to_s

d1 = Date.new(2024, 1, 1)
d2 = Date.new(2024, 12, 25)
puts "Days between: #{(d2 - d1).to_i}"
puts "Leap year 2024? #{Date.leap?(2024)}"

Date#+ adds days, while Date#>> adds months and clamps to the last valid day, so January 31 plus one month becomes February 29 in 2024. Subtracting two Dates gives a Rational number of days, which is converted with to_i.

$ ./ex6.rb
2024-01-31
2024-02-01
2024-02-29
2023-11-30
Friday, March 1, 2024
2024-02-28
2024-03-01
Days between: 359
Leap year 2024? true

List all Ruby tutorials.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.