Skip to Content
Course content

25: Working with Dates and Times

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Dates and times are notoriously annoying in every language, and Ruby is no exception. The biggest hurdle for most people starting out isn't the logic—it's knowing which class to use. Do you want a Time object, a Date object, or a DateTime object? For most modern Ruby apps, you'll spend 90% of your time with Time (for precise moments) and Date (for calendar days). Let's build a simple "Project Deadline Tracker" to see how these behave in the wild.

Defining the target date

I want to create a script that tells me exactly how many days I have left until a project is due. My first instinct is to just grab the current date and compare it to a deadline. Let's try that.

deadline = Date.new(2024, 12, 31)
today = Date.today
puts "Deadline is in #{deadline - today} days."

If you ran this right now, Ruby would throw a NameError: uninitialized constant Date. I do this every single time I start a new script because I forget that while Time is built into the core, Date lives in the standard library. You have to explicitly ask for it.

require 'date'

deadline = Date.new(2024, 12, 31)
today = Date.today
puts "Deadline is in #{deadline - today} days."

Now it works. When you subtract one Date object from another, Ruby returns a Rational number representing the difference in days. It's clean and simple.

Handling the precision of Time

Now, what if we need to be more specific? A project isn't just due on a day; it's usually due by 5:00 PM. This is where Time comes in. Time handles hours, minutes, seconds, and time zones. Let's pivot our tracker to use Time so we can calculate the exact hours remaining.

# Let's set a specific deadline: Dec 31st, 2024, at 17:00 (5 PM)
deadline_time = Time.local(2024, 12, 31, 17, 0, 0)
now = Time.now

remaining_seconds = deadline_time - now
remaining_hours = (remaining_seconds / 3600).round(2)

puts "You have #{remaining_hours} hours left until the deadline!"

Notice a key difference here: when you subtract two Date objects, you get days. When you subtract two Time objects, you get seconds. I find it helpful to remember that Time is essentially a wrapper around a giant number of seconds since the Unix Epoch.

Making dates readable for humans

Printing "2024-12-31 17:00:00" is fine for a database, but it's ugly for a user. To fix this, we use strftime (short for "string format time"). It uses a set of placeholders—like %Y for a four-digit year or %B for the full month name—to build a custom string.

I'll update our tracker to give us a polished, professional-looking status report:

require 'date'

deadline = Time.local(2024, 12, 31, 17, 0, 0)
now = Time.now

# %A is weekday, %B is month, %d is day, %Y is year
formatted_date = deadline.strftime("%A, %B %d, %Y")
formatted_time = deadline.strftime("%I:%M %p")

puts "The project is due on #{formatted_date} at #{formatted_time}."

One quick tip: strftime is a bit of a "magic string" system. You'll likely keep a cheat sheet bookmarked for a while to remember if %m is the month or the minute (it's the month; %M is minutes). Just remember that uppercase usually means something more detailed or different than the lowercase version.




📋 Practical Task

Build a Subscription Expiry Notifier

Your task is to create a script that manages a user's subscription. Here are the requirements:

  • Create a variable representing a subscription start date (use any date from the past).
  • Assume the subscription lasts for exactly 30 days. Calculate the expiry date by adding 30 to the start date.
  • Compare the expiry date to today's date.
  • Print a message telling the user:
    • "Your subscription is still active! It expires on [Formatted Date]." (if today is before the expiry date).
    • "Your subscription expired on [Formatted Date]!" (if today is after the expiry date).
  • The [Formatted Date] should be in a friendly format, such as "January 15th, 2024" (you can use %B %d, %Y).
Rating
0 0

There are no comments for now.

to be the first to leave a comment.