RubyGuides
Share this post!

Ruby Time & Date Classes

In this article you will learn what time-related classes & methods are available in Ruby and how to use them.

The Time Class

To manage time in Ruby you can use the Time class.

This class represents a date (day/month/year) and a time (hours/minutes/seconds). This is stored by the Time class as the number of seconds since the Epoch, also known as Unix time.

There are a few ways to initialize a Time object. You can get an object that represents the current time using Time.new or Time.now.

You can also create a Time object using an Unix timestamp and the at method.

time = Time.at(14000000000)

You can ask a time object for any of its components. For example, you can ask what day and month a time object is representing.

t = Time.now
puts t.day
puts t.month
puts t.hour

In addition, you can also ask if this date corresponds to a certain day of the week. For example: “Is this date a Sunday?”.

These are predicate methods, meaning that they will return either true or false.

t = Time.now
puts t.monday?
puts t.sunday?
puts t.friday?

Time Zones

A Time object also has a time zone associated with it, you can check the current time zone for a Time object using the zone method.

This will give you the time zone abbreviation.

If you want the time zone offset you can use the utc_offset method. The output for this method is in seconds, but you can divide by 3600 to get it in hours.

Example:

t = Time.now

t.zone
# "CET"

t.utc_offset / 3600
# 1

You can also get the current time in UTC:

Time.now.utc

Ruby Time Formatting

The default string representation for the time & date given to you by the Ruby Time class might not be what you want.

There is a method you can use to get almost any format you need.

This method is strftime, which basically means ‘format time’.

The way it works is by passing in a string with format specifiers, these specifiers will be replaced by a value
the time object. If you have ever used the printf method the idea is very similar to that.

Let’s see some examples:

time = Time.new

time.strftime("%d/%m/%Y")        # "05/12/2015"
time.strftime("%k:%M")           # "17:48"
time.strftime("Today is %A")     # "Today is Sunday"
time.strftime("%d of %B, %Y")    # "21 of December, 2015"
time.strftime("Unix time is %s") # "Unix time is 1449336630"

As you can see, this method is very flexible. You can get the time without the date, or a nicely formatted date with the year, day & name of the current month.

You can find more info on the different formats available on the following links:

Time Difference (Addition & Subtraction)

Sometimes you don’t want the current time, but a time in the future or the past. You can do addition with time objects. Remember that the internal representation for Time is in seconds, so you can do this:

# Add ten seconds
time = Time.new + 10

In this example you get a time object that is set 10 seconds from the current time. Then you can check if that time has passed yet.

Time.new > time

If you want to get something like yesterday’s day then you will need to calculate how many seconds there are in a day.

Like this:

# seconds * minutes * hours

60 * 60 * 24
# 86400

Now with this number we can sustract that from the current date:

Time.now - 86400

If you are using Rails then you can do this:

Time.now - 1.day

The Date Class

The Date class has no concept of minutes, seconds or hours. This class stores everything internally in terms of days.

To use the Date class you need to require 'date'.

You can get the current date using Date.today. Unlike time, Date.new is not an alias for today, so keep that in mind.

Date.today # Current date
Date.new   # Returns a negative date

Date arithmetic is similar to the Time class, the difference is that you add days instead of seconds.

Date.today + 1  # Adds one day

Date doesn’t know anything about hours, seconds or minutes, so only use this class if you don’t need these.

Date Parsing

The Date.parse method will try to parse any string that looks like a date. It uses a simple heuristic algorithm that tries to detect the input format. Sometimes this will give unwanted results.

Examples:

Date.parse("10/10/2010")  # -> 2010-10-10
Date.parse("September 3") # -> 2015-09-03
Date.parse("May I have a cup of coffee, please?") # -> 1 of May

If you need something more strict you can use the Date.iso8601 method. An iso8601 date has the following format: year-month-day. An ArgumentError exception will be raised on invalid input.

You can use the Date.strptime method and a set of format specifiers to provide your own custom input format. These are the same specifiers that you can use for strftime.

Example:

Date.strptime("3 of September", "%d of %B") # 2015-09-03

The Time class can also create Ruby time objects from strings. You will need to require 'time' to enable this functionality.

Example:

require 'time'

Time.strptime("1 of December 2017", "%d of %B %Y")

Date Constants

The Date class has some constants that you may find useful. For example, there is an array with the months of the year and another with the days of the week.

Months start at index 1 so you can get a direct month number -> month name mapping.

The days start with Sunday, but you can use the rotate method to have the week start on Monday.

Date::MONTHNAMES # (index 0 = nil)
Date::DAYNAMES.rotate(1)

The DateTime Class

The DateTime class is a subclass of Date and it can store seconds in addition to dates.

Both Time and DateTime can get the same job done, with the main difference being that Time is implemented in C, so it will be faster.

ActiveSupport – Time & Date Methods

If you have used rails you are probably familiar with things like 3.days.ago.

These methods are not available in pure Ruby, they are added by the ActiveSupport component of Rails.

Here you can find some examples, notice how these methods don’t return Time or Date objects, but a custom ActiveSupport class.

1.hour.to_i  # 3600

1.day        # ActiveSupport::Duration
3.days.ago   # ActiveSupport::TimeWithZone

You can do time math with these & get things like tomorrow’s date:

Time.now + 1.day

Other Rails-exclusive time methods:

date = Time.current

date.change(hour: 20)
date.at_beginning_of_day

And for formatting:

date = Date.today

date.to_formatted_s(:short) # "16 Jul"
date.to_formatted_s(:long)  # "July 16, 2018"

The code for these methods is actually pretty simple, you should take a look. The source code for TimeWithZone is also worth taking a look at.

Summary

In this article you learned about the Time & Date classes, how to parse & format time in Ruby, and how to use the ActiveSupport time extensions.

2 comments
megyewodi says a couple of years ago

I love it

Abhimanyu Aryan (@aryan_chat) says a couple of years ago

Nice post

Comments are closed