Skip to content

Ruby Date & Time

Ruby provides robust support for handling dates and times through its core Time class and the standard library Date and DateTime classes (found in the date library, which may need to be require’d for Date and DateTime). The Time class represents a specific moment in time, including both date and time components, down to microsecond precision on most modern systems.

On modern 64-bit systems, Ruby’s Time objects can represent a very wide range of dates, far exceeding the old 1970-2038 limitations that affected some older 32-bit systems.

You can get the current system date and time using Time.now or its alias Time.new (when called without arguments).

#!/usr/bin/env ruby
time_now = Time.now
puts "Current Time (Time.now): #{time_now.inspect}"
# Time.new is an alias for Time.now when called without arguments
time_new = Time.new
puts "Current Time (Time.new): #{time_new.inspect}"

This will produce output similar to (the exact time and timezone will vary):

Current Time (Time.now): 2023-10-27 10:30:45.123456 -0700
Current Time (Time.new): 2023-10-27 10:30:45.123456 -0700

A Time object provides methods to access its various components:

#!/usr/bin/env ruby
time = Time.now
puts "Current Time: #{time.inspect}"
puts "Year: #{time.year}" # e.g., 2023
puts "Month: #{time.month}" # 1 (January) to 12 (December)
puts "Day: #{time.day}" # 1 to 31
puts "Hour: #{time.hour}" # 0 to 23 (24-hour clock)
puts "Minute: #{time.min}" # 0 to 59
puts "Second: #{time.sec}" # 0 to 59 (can be 60 for leap second)
puts "Microsecond: #{time.usec}" # 0 to 999999
puts "Nanosecond: #{time.nsec}" # 0 to 999999999 (more precise than usec)
puts "Day of week (wday): #{time.wday}" # 0 (Sunday) to 6 (Saturday)
puts "Day of year (yday): #{time.yday}" # 1 to 365 (or 366 in a leap year)
puts "Timezone: #{time.zone}" # e.g., "PST", "UTC", "EDT" (may be nil)
puts "Is DST?: #{time.dst?}" # true if Daylight Saving Time is in effect

Creating Time Objects for Specific Dates/Times

Section titled “Creating Time Objects for Specific Dates/Times”

You can create Time objects for specific dates and times using:

  • Time.local(year, month, day, hour, min, sec, usec_with_frac) or Time.mktime(...): Creates a Time object in the system’s local timezone.
  • Time.utc(year, month, day, hour, min, sec, usec_with_frac) or Time.gm(...): Creates a Time object in Coordinated Universal Time (UTC), also known as Greenwich Mean Time (GMT).
#!/usr/bin/env ruby
# December 25, 2025, 14:30:00 local time
local_time = Time.local(2025, 12, 25, 14, 30, 0)
puts "Local Time: #{local_time.inspect}"
# July 4, 2024, 09:15:00 UTC
utc_time = Time.utc(2024, 7, 4, 9, 15, 0)
puts "UTC Time: #{utc_time.inspect}"
# You can omit parts from right to left; they default to minimum values (e.g., 1 for month/day, 0 for time components)
start_of_year = Time.local(2023) # January 1, 2023, 00:00:00 local time
puts "Start of 2023: #{start_of_year.inspect}"

Time objects can be converted to various other representations:

  • time.to_a: Returns a 10-element array: [sec, min, hour, day, month, year, wday, yday, isdst, zone_abbreviation].
  • time.to_i or time.tv_sec: Returns the number of seconds since the Unix epoch (January 1, 1970, 00:00:00 UTC).
  • time.to_f or time.tv_usec combined with tv_sec: Returns seconds since epoch as a float, including microseconds.
  • Time.at(seconds_since_epoch): Creates a Time object from the number of seconds since the epoch.
#!/usr/bin/env ruby
time = Time.now
components_array = time.to_a
puts "Time as array: #{components_array.inspect}"
# Example: [15, 30, 10, 27, 10, 2023, 5, 300, true, "PDT"]
seconds_epoch = time.to_i
puts "Seconds since epoch: #{seconds_epoch}"
reconstructed_time = Time.at(seconds_epoch)
puts "Reconstructed time from seconds: #{reconstructed_time.inspect}"

Ruby’s Time objects are timezone-aware. You can convert between timezones:

#!/usr/bin/env ruby
time = Time.now # Created in local timezone
puts "Original (local): #{time.inspect} (Zone: #{time.zone}, DST: #{time.dst?})"
# Convert to UTC
utc_time = time.utc
puts "UTC: #{utc_time.inspect} (Zone: #{utc_time.zone}, DST: #{utc_time.dst?})"
# Convert UTC time back to local timezone
local_again = utc_time.localtime
puts "Local again: #{local_again.inspect} (Zone: #{local_again.zone}, DST: #{local_again.dst?})"
# Get a new Time object in UTC or local zone without modifying original
new_utc_obj = time.getutc
new_local_obj = utc_time.getlocal
puts "Is original time UTC? #{time.utc?}" # false (if local time is not UTC)
puts "Is utc_time object UTC? #{utc_time.utc?}" # true
puts "UTC offset: #{time.utc_offset} seconds" # e.g., -25200 for PDT (-7 hours)

The strftime (string format time) method is powerful for custom formatting of Time objects into strings. It uses directives (percent-prefixed characters) to specify how each part of the time should be represented.

#!/usr/bin/env ruby
time = Time.now
puts "Default to_s: #{time.to_s}" # e.g., 2023-10-27 10:30:45 -0700
puts "ctime: #{time.ctime}" # e.g., Fri Oct 27 10:30:45 2023
puts "ISO 8601: #{time.iso8601}" # e.g., 2023-10-27T10:30:45-07:00
puts "Custom format (YYYY-MM-DD HH:MM:SS): #{time.strftime("%Y-%m-%d %H:%M:%S")}"
puts "Custom format (Month Day, Year): #{time.strftime("%B %d, %Y")}"
puts "Custom format (hh:mm AM/PM Zone): #{time.strftime("%I:%M %p %Z")}"
DirectiveDescription
%YYear with century (e.g., 2023)
%yYear without century (00-99)
%mMonth of the year (01-12)
%BFull month name (e.g., January)
%b or %hAbbreviated month name (e.g., Jan)
%dDay of the month (01-31)
%eDay of the month, space-padded ( 1-31)
%AFull weekday name (e.g., Sunday)
%aAbbreviated weekday name (e.g., Sun)
%wDay of the week (Sunday is 0, 0-6)
%HHour of the day, 24-hour clock (00-23)
%IHour of the day, 12-hour clock (01-12)
%MMinute of the hour (00-59)
%SSecond of the minute (00-60) (60 for leap second)
%LMillisecond of the second (000-999)
%NNanosecond of the second (000000000-999999999)
%pMeridian indicator (AM or PM)
%ZTime zone abbreviation name
%zTime zone offset from UTC (e.g., +0900, -0700)
%:zTime zone offset with colon (e.g., +09:00)
%cLocale-specific date and time (e.g., Fri Oct 27 10:30:45 2023)
%xLocale-specific date representation (e.g., 10/27/23)
%XLocale-specific time representation (e.g., 10:30:45)
%%A literal ’%’ character

You can perform arithmetic with Time objects. Adding or subtracting a numeric value treats that number as seconds.

#!/usr/bin/env ruby
now = Time.now
puts "Current time: #{now}"
one_hour_ago = now - 3600 # 3600 seconds = 1 hour
puts "One hour ago: #{one_hour_ago}"
two_days_from_now = now + (2 * 24 * 60 * 60) # Add seconds for 2 days
puts "Two days from now: #{two_days_from_now}"
difference = two_days_from_now - now # Difference between two Time objects is in seconds (float)
puts "Difference in seconds: #{difference}"
puts "Difference in days: #{difference / (24 * 60 * 60)}"

Output (example):

Current time: 2023-10-27 10:45:00 -0700
One hour ago: 2023-10-27 09:45:00 -0700
Two days from now: 2023-10-29 10:45:00 -0700
Difference in seconds: 172800.0
Difference in days: 2.0

Using Date and DateTime for Date-Specific Operations

Section titled “Using Date and DateTime for Date-Specific Operations”

For operations that are primarily date-focused (without time components) or require historical date calculations (e.g., Julian/Gregorian calendar reforms), the Date and DateTime classes from the date standard library are often more suitable. You need to require 'date' to use them.

#!/usr/bin/env ruby
require 'date'
today = Date.today
puts "Today (Date): #{today.inspect}" # e.g., #<Date: 2023-10-27 ((2460245j,0s,0n),+0s,2299161j)>
puts "Formatted Date: #{today.strftime('%A, %B %d, %Y')}"
yesterday = today - 1
puts "Yesterday: #{yesterday}"
next_month = today >> 1 # Add one month
puts "Next month: #{next_month}"
# DateTime includes time components
dt_now = DateTime.now
puts "DateTime now: #{dt_now.inspect}"

For detailed information, refer to the official Ruby documentation for Time, Date, and DateTime.