Date, DateTime, Time, and Time Zones in Ruby & Ruby on Rails
To Future Me (and anyone else who finds this useful):
I can never seem to remember which Ruby and Rails date and time methods use the system time zone, which use the Rails application time zone, and which return UTC. This is my reference for keeping them straight.
The short version
Daterepresents a calendar date. It does not contain a time or time zone.- Ruby’s
Date.today,Time.now, andDateTime.nowuse the system time zone. - Rails’
Date.current,Time.current, andDateTime.currentuseTime.zonewhen one is configured. - Use
.utcwhen you explicitly need UTC. - Prefer
Timefor application timestamps. In Rails, application-zoned values are usuallyActiveSupport::TimeWithZoneobjects.
1. Calendar dates with Date
A Date contains a year, month, and day. It does not represent an instant in time and does not carry a time zone.
Date.parse("January 1 2025")
# => Wed, 01 Jan 2025
Date.new(2025, 2, 3)
# => Mon, 03 Feb 2025
# Omitting the day uses the first day of the month.
Date.new(2025, 2)
# => Sat, 01 Feb 2025
# Omitting the month and day uses January 1.
Date.new(2025)
# => Wed, 01 Jan 2025
Date.today is slightly different. It asks the system clock what today’s date is, so the result is determined using the system time zone:
Date.today
# => Wed, 01 Jan 2025
In Rails, use Date.current when “today” should be determined using the application’s configured time zone.
2. Ruby methods using the system time zone
Ruby’s core time methods do not know about Rails’ config.time_zone. They use the operating system’s local time zone.
Time.now
# => 2025-01-05 12:35:00.262441 -0600
DateTime.now
# => Sun, 05 Jan 2025 12:31:58 -0600
When DateTime.parse receives input without an explicit offset, it defaults to a fixed zero offset:
DateTime.parse("January 1 2025 10pm")
# => Wed, 01 Jan 2025 22:00:00 +0000
A zero offset is not the same thing as a named time zone with daylight-saving rules. For ordinary application timestamps, prefer Time and Rails’ ActiveSupport::TimeWithZone over DateTime.
3. Rails application time zone
Configure the application’s default time zone in application.rb:
class Application < Rails::Application
config.time_zone = "Eastern Time (US & Canada)"
end
Rails’ current methods honor Time.zone when it is configured:
Time.current
# => Sun, 05 Jan 2025 13:50:39 EST -05:00
Date.current
# => Sun, 05 Jan 2025
DateTime.current
# => Sun, 05 Jan 2025 13:50:39 -0500
Date.yesterday and Date.tomorrow are relative to Date.current, so they also follow the Rails application time zone:
Date.yesterday
# => Sat, 04 Jan 2025
Date.tomorrow
# => Mon, 06 Jan 2025
Use Time.zone.parse when a timestamp without an offset should be interpreted in the application time zone:
Time.zone.parse("January 1 2025 10pm")
# => Wed, 01 Jan 2025 22:00:00 EST -05:00
When no Rails time zone is configured, the current methods fall back to the corresponding system-time methods.
4. Working explicitly with UTC
Call .utc when you specifically need a UTC value:
Time.now.utc
# => 2025-01-05 18:35:00.262441 UTC
Time.current.utc
# => 2025-01-05 18:50:39 UTC
To get the UTC calendar date for the current instant:
Time.now.utc.to_date
# => Sun, 05 Jan 2025
5. Converting between time zones
Use in_time_zone to represent an instant in another Rails time zone:
Time.now.utc.in_time_zone("Eastern Time (US & Canada)")
# => Sun, 05 Jan 2025 13:35:00 EST -05:00
Time.zone.now returns an ActiveSupport::TimeWithZone when a Rails time zone is configured:
Time.zone = "Hawaii"
Time.zone.now
# => Sun, 05 Jan 2025 10:04:16 HST -10:00
For a temporary override, prefer Time.use_zone so the previous zone is restored after the block:
Time.use_zone("Hawaii") do
Time.current
end
# => Sun, 05 Jan 2025 10:04:16 HST -10:00
6. Formatting dates and times
Ruby’s strftime formats Date, Time, and DateTime values as strings.
time = Time.new(2025, 1, 5, 14, 16, 0)
time.strftime("%b %-d, %Y")
# => "Jan 5, 2025"
time.strftime("%A, %B %-d, %Y at %-I:%M%P")
# => "Sunday, January 5, 2025 at 2:16pm"
Weekday
- Full weekday (
Sunday):%A - Abbreviated weekday (
Sun):%a
Month
- Full month (
January):%B - Abbreviated month (
Jan):%b
Day
- Zero-padded day (
05):%d - Space-padded day (
5):%e - Unpadded day (
5):%-d
Year
- Four-digit year (
2025):%Y - Two-digit year (
25):%y
Hour
- Zero-padded 12-hour value (
02):%I - Space-padded 12-hour value (
2):%l - Unpadded 12-hour value (
2):%-I
Minutes
- Minutes (
43):%M
Meridian indicator
- Uppercase (
PM):%p - Lowercase (
pm):%P