Dates & Times

Reviewed & published by Brayan K

Ruby handles moments in time with the built-in Time class and calendar days with the Date class from the standard library, both formatted with strftime.

Part of the free Ruby course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

You'll read date parts, format with directives, parse strings, and do day and second arithmetic.

What You'll Learn in This Lesson

1️⃣ Time Basics & Reading Parts

Time.now gives the current instant; Time.new(...) builds a specific one. Pull out parts with year, month, day, hour, min, and wday (0 = Sunday). We pin the offset to UTC so the output is identical every run.

require 'date'

# Use a FIXED date/time so output is reproducible.
# The "+00:00" pins the timezone offset to UTC.
t = Time.new(2026, 6, 18, 14, 30, 0, "+00:00")

puts t.year      # 2026
puts t.month     # 6
puts t.day       # 18
puts t.hour      # 14
puts t.min       # 30
puts t.wday      # 4 (0=Sunday ... 4=Thursday)

# Time.now would give the *current* time instead.
puts t           # default text form

2️⃣ Formatting with strftime & Parsing

strftime turns a date or time into any string layout using % directives — %Y year, %m month, %d day, %A weekday name, and more. Going the other way, Date.parse reads a string back into a Date.

require 'date'

d = Date.new(2026, 6, 18)   # a Date has no time component

# strftime formats a date/time with directives:
puts d.strftime("%Y-%m-%d")          # 2026-06-18
puts d.strftime("%A, %B %-d, %Y")    # Thursday, June 18, 2026
puts d.strftime("%d/%m/%Y")          # 18/06/2026

# Parse a string back into a Date:
parsed = Date.parse("2026-12-25")
puts parsed.strftime("%A")           # Friday

# Time also supports strftime, including 24h time:
t = Time.new(2026, 6, 18, 9, 5, 0, "+00:00")
puts t.strftime("%H:%M")             # 09:05
puts t.strftime("%I:%M %p")          # 09:05 AM

3️⃣ Date & Time Arithmetic

For a Date, + and - move by whole days, and subtracting two dates gives the gap between them. For a Time, the same operators move by seconds. Helpers like next_month handle calendar quirks for you.

require 'date'

start = Date.new(2026, 6, 18)

# Date arithmetic: + and - work in DAYS.
puts (start + 7).to_s        # one week later
puts (start - 1).to_s        # yesterday

# Difference between two dates (a Rational number of days):
deadline = Date.new(2026, 7, 1)
puts (deadline - start).to_i  # days until deadline

# next_month / next_year helpers:
puts start.next_month.to_s
puts start.next_year.to_s

# Time arithmetic is in SECONDS:
t = Time.new(2026, 6, 18, 12, 0, 0, "+00:00")
later = t + 3600              # add one hour (3600 seconds)
puts later.strftime("%H:%M")

Your turn. Count the days until a birthday and find which weekday it falls on. Fill in each ___.

require 'date'

# 🎯 YOUR TURN — replace each ___ then run with: ruby party.rb
birthday = Date.new(2026, 9, 1)
today    = Date.new(2026, 6, 18)

# 1) How many days until the birthday? (subtract dates, then to_i)
days_left = (birthday - today).___
puts "#{days_left} days until the party"

# 2) What weekday does the birthday fall on?
puts birthday.strftime("___")     # 👉 directive for the full weekday name

# ✅ Expected output:
#    75 days until the party
#    Tuesday

Mini-Challenge: Event Countdown

Print a schedule that shows each event's formatted date, its weekday, and how many days away it is from a fixed "today". This combines formatting and date math. Run with ruby schedule.rb.

# 🎯 MINI-CHALLENGE: an event countdown.
# Save as schedule.rb and run with: ruby schedule.rb
#
# 1. require 'date'.
# 2. Build a hash of event name => Date (use fixed dates).
# 3. For each event, print its formatted date, weekday, and how
#    many days from a fixed "today" it is.
#
# ✅ Example output:
#    Launch: Jun 18 (Thursday), in 0 days
#    Review: Jun 25 (Thursday), in 7 days
#    Release: Jul 10 (Friday), in 22 days

# your code here

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — Dates & Times

TaskRuby
NowTime.now / Date.today
Build a dateDate.new(2026, 6, 18)
Formatd.strftime("%Y-%m-%d")
ParseDate.parse("2026-12-25")
Add daysdate + 7
Days between(b - a).to_i

🎉 Lesson Complete!

Practice quiz

Which class requires `require 'date'` before you can use it?

  • Time
  • Integer
  • Date
  • String

Answer: Date. Time is built in, but Date (and DateTime) live in the standard library and need require 'date'.

What does `Date.new(2026, 6, 18) + 7` produce?

  • A Date one week later (2026-06-25)
  • A Date 7 months later
  • A Time 7 seconds later
  • An error

Answer: A Date one week later (2026-06-25). For a Date, + and - work in whole days, so +7 is one week later.

Subtracting two Date objects, e.g. `(b - a)`, returns what kind of value?

  • An Integer of days
  • A Time
  • A String
  • A Rational number of days

Answer: A Rational number of days. Date subtraction yields a Rational number of days; call .to_i for a plain integer.

Adding to a Time, e.g. `time + 3600`, moves it forward by how much?

  • 3600 days
  • 3600 seconds (one hour)
  • 3600 minutes
  • 3600 hours

Answer: 3600 seconds (one hour). Time arithmetic is in seconds, so + 3600 adds one hour.

Which strftime directive gives the full weekday name (e.g. 'Thursday')?

  • %A
  • %w
  • %d
  • %a

Answer: %A. %A is the full weekday name; %a is the abbreviated form and %d is the day of month.

What is the difference between %m and %M in strftime?

  • No difference
  • %m is minutes, %M is month
  • %m is month, %M is minutes
  • %m is military time

Answer: %m is month, %M is minutes. Lowercase %m is the month; uppercase %M is the minutes.

For `Time.new(2026, 6, 18, 14, 30, 0, '+00:00')`, what does `t.wday` return (0 = Sunday)?

  • 3
  • 4
  • 5
  • 6

Answer: 4. June 18, 2026 is a Thursday, and wday counts from 0=Sunday, so Thursday is 4.

What does `Date.parse("2026-12-25")` do?

  • Formats a date into a string
  • Returns the current date
  • Raises an error
  • Reads a string into a Date object

Answer: Reads a string into a Date object. Date.parse reads a string and returns a Date object.

Why did the lesson use fixed dates instead of Time.now?

  • Time.now is deprecated
  • So output is reproducible every run
  • Time.now needs a require
  • Fixed dates are faster

Answer: So output is reproducible every run. Time.now changes every run; fixed values keep example output identical and verifiable.

What does the directive prefix in %-d do compared with %d?

  • Adds a leading zero
  • Shows the weekday
  • Removes the leading zero
  • Uppercases the result

Answer: Removes the leading zero. A hyphen like %-d drops the zero-padding (5 instead of 05).

Continue this course

Frequently asked questions

What's the difference between Time, Date, and DateTime?

Time (built in, no require) models an instant down to fractions of a second and is timezone-aware — great for timestamps and durations. Date (require 'date') represents a calendar day with no time component, ideal for birthdays or deadlines. DateTime combines both but is largely legacy; modern Ruby code prefers Time for moments and Date for days. All three support strftime for formatting.

How does strftime work and where do the % directives come from?

strftime ('string format time') turns a date or time into a string using % directives: %Y is the 4-digit year, %m the zero-padded month, %d the zero-padded day, %A the full weekday name, %B the full month name, %H 24-hour, %I 12-hour, %M minutes, %p AM/PM. A hyphen like %-d removes zero-padding. These directives are shared with C and many other languages, so the knowledge transfers.

How do I do date arithmetic in Ruby?

For Date objects, + and - work in whole days: date + 7 is a week later, and subtracting two dates gives the number of days between them (as a Rational, so call .to_i for a plain integer). For Time objects, + and - work in seconds: time + 3600 adds an hour. There are also helpers like next_month, prev_day, and next_year for calendar-aware jumps.

Why did this lesson use fixed dates instead of Time.now?

Time.now and Date.today return the current moment, so their output changes every run — which makes examples impossible to verify. By constructing fixed values like Time.new(2026, 6, 18, 14, 30, 0, '+00:00') and pinning the UTC offset, every run produces identical output. In real programs you'd use Time.now or Date.today; for teaching and tests, deterministic fixed values are the way to go.