Date
The Date class provides methods for working with calendar dates in Ruby. It’s part of the standard library and offers powerful date manipulation and parsing capabilities.
Overview
Ruby’s Date class represents dates without times:
- Create: Generate dates from strings, components, or today
- Parse: Convert strings into Date objects
- Manipulate: Add, subtract, and calculate date differences
- Format: Display dates in various formats
Creating date objects
Today’s Date
Date.today # => #<Date: 2026-03-13>
Date.today.to_s # => "2026-03-13"
The current-day example is the simplest place to start because it shows the shape of a Date value without any parsing or conversion steps. In calendar code, Date.today is often the point where a calculation begins, especially when you are measuring deadlines or showing today’s date back to a person.
From string
require "date"
Date.parse("2026-03-13")
# => #<Date: 2026-03-13>
Date.parse("March 13, 2026")
# => #<Date: 2026-03-13>
Parsing is the next common step because many applications receive dates as text. Date.parse accepts several familiar forms, which makes it handy at the boundary where user input or file data is turned into Ruby objects. Keeping that parsing close to the input makes the rest of the app cleaner.
From components
Date.new(2026, 3, 13)
# => #<Date: 2026-03-13>
Building a date from components is useful when the source data is already split into year, month, and day fields. It avoids extra string parsing and makes the input contract very clear. That can be a better fit for forms, APIs, and internal data structures that already carry separate fields.
From time
DateTime.now.to_date
Time.now.to_date
Converting from a time value is a good way to cross from a moment in time into a plain calendar day. That is useful when the exact clock time no longer matters and the code only needs to know which day something happened on. It keeps date logic from getting tangled with time zones.
Date components
You can extract individual components from a Date object:
date = Date.today
date.year # => 2026
date.month # => 3
date.day # => 13
date.wday # => 5 (0 = Sunday)
date.yday # => 72 (day of year)
date.leap? # => false
Once you have a Date, the component methods make it easy to inspect the calendar fields directly. That can be helpful when formatting output, choosing a branch, or comparing one day against another. The values are all plain integers or booleans, so they are easy to work with in later code.
Date calculations
Adding/subtracting days
date = Date.today
date + 1 # Tomorrow
date - 7 # One week ago
date + 30 # About one month later
Adding and subtracting days is one of the most common calendar tasks. Because the arithmetic works in whole days, the code stays easy to read and avoids the noise of hours or minutes. That is usually what you want when the business rule is about calendar movement rather than exact elapsed time.
Date Differences
date1 = Date.new(2026, 1, 1)
date2 = Date.new(2026, 3, 13)
(date2 - date1).to_i # => 71 days
Date differences are especially useful when the goal is a count of days rather than a timestamp. The result can feed a countdown, a report, or a scheduling rule without any extra conversion steps. It also keeps the logic close to the actual calendar question being asked.
Comparing Dates
past = Date.new(2020, 1, 1)
future = Date.new(2030, 1, 1)
future > past # => true
past <=> future # => -1 (past is earlier)
past == past # => true
Comparisons make Date fit naturally into sorting and validation code. When the business rule is “before” or “after,” the Ruby operators keep the intent concise and readable. That makes the date values easy to fit into ordinary conditionals or ordered collections.
Date ranges
Iterating over dates
start = Date.new(2026, 3, 10)
finish = Date.new(2026, 3, 15)
(start..finish).each do |date|
puts date
end
# 2026-03-10
# 2026-03-11
# 2026-03-12
# 2026-03-13
# 2026-03-14
# 2026-03-15
Ranges are a nice fit for date work because they let you treat a span of days like a sequence. That makes iteration straightforward, whether you are walking a reporting window or generating a list of calendar entries. The code stays compact while still showing the full period.
Checking range inclusion
range = Date.new(2026, 1, 1)..Date.new(2026, 12, 31)
range.include?(Date.new(2026, 6, 15)) # => true
range.include?(Date.new(2027, 1, 1)) # => false
Range checks are often the simplest way to ask whether a date falls inside a season, a fiscal period, or an event window. The answer is easy to read, and it keeps the business rule visible right where the comparison happens.
Date formatting
strftime
The strftime method formats dates using directives:
date = Date.today
date.strftime("%Y-%m-%d") # => "2026-03-13"
date.strftime("%d/%m/%Y") # => "13/03/2026"
date.strftime("%B %d, %Y") # => "March 13, 2026"
date.strftime("%A") # => "Friday"
Formatting is usually the final step after the date has been calculated or parsed. The strftime directives give you control over presentation without changing the value itself, which keeps display concerns separate from calendar logic. That separation makes the code easier to reuse in other contexts.
| Directive | Meaning | Example |
|---|---|---|
%Y | Year | 2026 |
%m | Month (01-12) | 03 |
%d | Day | 13 |
%A | Weekday | Friday |
%B | Month name | March |
Predefined Formats
date = Date.today
date.iso8601 # => "2026-03-13"
date.rfc2822 # => "Fri, 13 Mar 2026 00:00:00 +0000"
Predefined formats are useful when the output needs to match a known standard. They save you from building your own format string and reduce the chance of a typo. In exchange, you get a representation that other tools are likely to understand without extra work.
Date calculations
Month Navigation
date = Date.new(2026, 3, 13)
date >> 1 # => 2026-04-13 (next month)
date << 1 # => 2026-02-13 (previous month)
Month navigation is a practical example of why Date is different from plain integer arithmetic. The operators move along the calendar, so they respect month boundaries and keep the result on a valid day. That makes them a good fit for billing cycles and recurring dates.
Finding day of week
date = Date.new(2026, 3, 13)
date.monday? # => false
date.friday? # => true
date.sunday? # => false
Day-of-week helpers can keep conditional logic short when a task only applies on certain days. Instead of comparing numbers by hand, the method names make the rule easy to read. That is especially helpful in schedules or reminders that behave differently on weekdays and weekends.
Beginning/end of month
date = Date.new(2026, 3, 13)
date.beginning_of_month # => 2026-03-01
date.end_of_month # => 2026-03-31
Beginning and end helpers are convenient when the program needs a clean boundary for a month. They are often used for reports, filters, and calendar displays because they let the code refer to a whole month without constructing the endpoints manually.
Parsing dates
Flexible Parsing
require "date"
Date.parse("2026-03-13") # => 2026-03-13
Date.parse("03/13/2026") # => 2026-03-13
Date.parse("13-Mar-2026") # => 2026-03-13
Flexible parsing is handy when the input might arrive in more than one common format. It is still worth keeping that logic close to the boundary, because the rest of the app should usually work with proper Date objects rather than raw strings.
With Format
require "date"
Date.strptime("13-03-2026", "%d-%m-%Y")
# => 2026-03-13
strptime is the right choice when the input format is known ahead of time. It removes guesswork and makes the expected layout explicit, which is useful for imports, fixed reports, and any other place where the date text is controlled.
Practical Examples
Days until event
event = Date.new(2026, 12, 25)
today = Date.today
days_until = (event - today).to_i
puts "Days until Christmas: #{days_until}"
This kind of countdown is a common reason to reach for Date in application code. Once the values are calendar days, the math is simple and the message can be shown directly to the user. It is easy to keep the rule and the display in the same place.
Week Number
date = Date.new(2026, 3, 13)
date.cweek # => 11 (ISO week number)
date.cwyear # => 2026 (ISO week year)
Week numbers are useful in reports, planning tools, and any interface that groups work by ISO calendar week. They are one of those details that are easy to get wrong by hand, so having the method built in helps keep the code honest.
Day of Year
date = Date.new(2026, 3, 13)
date.yday # => 72 (day 72 of the year)
The day-of-year value is a compact way to talk about progress through the calendar. It is handy in schedules, seasonal logic, and data exports where the ordinal day matters more than the month name. Because it is just a number, it is easy to compare and sort.
Working With Calendars
Date is a strong fit for schedules, deadlines, and other values that should stay tied to the calendar rather than the clock. If you are counting days between milestones, Date keeps the code simple because it ignores hours, minutes, and time zone offsets.
When a project starts mixing dates and times, it helps to convert at the boundary and keep the rest of the logic on one side. That way, date math stays predictable and the code does not need to keep checking whether it is dealing with a point in time or a whole day.