Skip to Content
Course content

65: Time and Date Classes

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

I've seen this bug more times than I can count, usually in a "Trial Period" or "Subscription" feature. A developer wants to set an expiration date for 30 days from now, and they write something that looks perfectly logical at first glance.

# The "Logic"
trial_start = Time.now
expiration_date = trial_start + 30

puts "Your trial expires on: #{expiration_date}"
# Expected: A date 30 days from now
# Actual: A time 30 seconds from now

The Thirty-Second Trial Period

If you run the code above, you'll notice your users are getting kicked out of your app almost immediately. The problem is a fundamental difference in how Ruby handles math for the Time class versus the Date class.

In Ruby, when you add an integer to a Time object, you aren't adding days. You're adding seconds. Since there are 86,400 seconds in a day, adding 30 just pushes the clock forward by half a minute. It's a silent failure—the code doesn't crash, it just does something you didn't intend.

Calculating Real Days

Depending on what you're building, there are two ways to fix this. If you need to stay within the Time class because you care about the exact hour and minute the trial ends, you have to do the math manually:

# 30 days * 24 hours * 60 minutes * 60 seconds
expiration_date = Time.now + (30 * 24 * 60 * 60)

But honestly? If you only care about the calendar date, you should be using the Date class. Unlike Time, adding an integer to a Date object adds days. Note that Date isn't loaded by default, so you have to require it first.

require 'date'

today = Date.today
expiration_date = today + 30 
# This actually adds 30 days. Much cleaner.

Choosing the Right Tool for the Job

I usually tell my juniors to follow a simple rule of thumb: if it's a "timestamp" (when did this log entry happen?), use Time. If it's a "calendar event" (when is the user's birthday?), use Date.

  • Time: Handles years, months, days, hours, minutes, seconds, and timezones. It's a wrapper around the system clock.
  • Date: Only handles the calendar date. It's lightweight and avoids the headache of timezone shifts when you just need to know "Is it Tuesday?"
  • DateTime: You'll see this in older tutorials. It's a hybrid of the two. In modern Ruby, Time has been improved so much that DateTime is largely redundant. I'd suggest sticking to Time and Date.

Making Dates Readable

The default string output of these classes is ugly. You'll rarely ever want to show a user something like 2023-10-27 14:30:05 -0400. To fix this, we use strftime (short for "string format time").

It uses a series of placeholders. %Y is the four-digit year, %m is the month, and %d is the day. Here is how I usually format a friendly date:

now = Time.now
puts now.strftime("Today is %A, %B %d, %Y")
# Output: Today is Friday, October 27, 2023

I highly recommend keeping a strftime cheat sheet bookmarked; nobody remembers that %B is the full month name and %b is the abbreviated version off the top of their head.




📋 Practical Task

Build a Project Deadline Countdown

Write a script that simulates a project management tool. Your script should:

  • Define a target deadline date (e.g., December 31st of the current year) using the Date class.
  • Get the current date using Date.today.
  • Calculate the number of days remaining between today and the deadline.
  • Print a message to the console saying: "There are [X] days remaining until the deadline on [Formatted Date]."
  • The formatted date should look like "December 31, 202X".
Rating
0 0

There are no comments for now.

to be the first to leave a comment.