Convert to/from DateTime and Time in Ruby

Viewed 163902

How do you convert between a DateTime and a Time object in Ruby?

7 Answers
require 'time'
require 'date'

t = Time.now
d = DateTime.now

dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)

You'll need two slightly different conversions.

To convert from Time to DateTime you can amend the Time class as follows:

require 'date'
class Time
  def to_datetime
    # Convert seconds + microseconds into a fractional number of seconds
    seconds = sec + Rational(usec, 10**6)

    # Convert a UTC offset measured in minutes to one measured in a
    # fraction of a day.
    offset = Rational(utc_offset, 60 * 60 * 24)
    DateTime.new(year, month, day, hour, min, seconds, offset)
  end
end

Similar adjustments to Date will let you convert DateTime to Time .

class Date
  def to_gm_time
    to_time(new_offset, :gm)
  end

  def to_local_time
    to_time(new_offset(DateTime.now.offset-offset), :local)
  end

  private
  def to_time(dest, method)
    #Convert a fraction of a day to a number of microseconds
    usec = (dest.sec_fraction * 60 * 60 * 24 * (10**6)).to_i
    Time.send(method, dest.year, dest.month, dest.day, dest.hour, dest.min,
              dest.sec, usec)
  end
end

Note that you have to choose between local time and GM/UTC time.

Both the above code snippets are taken from O'Reilly's Ruby Cookbook. Their code reuse policy permits this.

While making such conversions one should take into consideration the behavior of timezones while converting from one object to the other. I found some good notes and examples in this stackoverflow post.

You can use to_date, e.g.

> Event.last.starts_at
=> Wed, 13 Jan 2021 16:49:36.292979000 CET +01:00
> Event.last.starts_at.to_date
=> Wed, 13 Jan 2021
Related