Cover by Leonard Richardson, Lucas Carlson

Safari, the world’s most comprehensive technology and business learning platform.

Find the exact information you need to solve a problem on the fly, or go deeper to master the technologies and skills you need to succeed

Start Free Trial

No credit card required

O'Reilly logo

3.9. Converting Between Time and DateTime Objects

Problem

You're working with both DateTime and Time objects, created from Ruby's two standard date/time libraries. You can't mix these objects in comparisons, iterations, or date arithmetic because they're incompatible. You want to convert all the objects into one form or another so that you can treat them all the same way.

Solution

To convert a Time object to a DateTime, you'll need some code like this:

	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

	time = Time.gm(2000, 6, 4, 10, 30, 22, 4010)
	# => Sun Jun 04 10:30:22 UTC 2000
	time.to_datetime.to_s
	# => "2000-06-04T10:30:22Z"

Converting a DateTime to a Time is similar; you just need to decide whether you want the Time object to use local time or GMT. This code adds the conversion method to Date, the superclass of DateTime, so it will work on both Date and DateTime objects.

 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, ...

Find the exact information you need to solve a problem on the fly, or go deeper to master the technologies and skills you need to succeed

Start Free Trial

No credit card required