Converting between Time and DateTime

What is the recommended method for converting between Time objects and
those of type DateTime?

I know that I can do this:

  dt = DateTime.new
  t = Time.mktime(dt.year, dt.mon, dt.day,
                  dt.hour, dt.min, dt.sec)

... and this:

  t = Time.now
  dt = DateTime.civil(t.year, t.mon, t.day,
                      t.hour, t.min, t.sec)

However, this seems overly verbose to me, and I end up putting one or
both of the following into my ruby programs:

  class DateTime
    def self.fromTime(t)
      return DateTime.civil(t.year, t.mon, t.day,
                            t.hour, t.min, t.sec)
    end
  end

  class Time
    def self.fromDateTime(dt)
      return Time.mktime(dt.year, dt.mon, dt.day,
                         dt.hour, dt.min, dt.sec)
    end
  end

Is there any reason for why we can't have similar methods as part of the
official DateTime and Time classes?

Or is there already some sort of mechanism for this that I have
overlooked?

Thanks in advance.

···

--
Lloyd Zusman
ljz@asfast.com
God bless you.

Hi --

What is the recommended method for converting between Time objects and
those of type DateTime?

This is probably just a stepping-stone on the way to something more
elegant... but try this:

   require 'date'
   require 'time'

   t = Time.parse(DateTime.new.sec.to_s)

(Could we get all the time/date stuff unified and loaded by default?
Is that too much overhead?)

David

···

On Sun, 13 Nov 2005, Lloyd Zusman wrote:

--
David A. Black
dblack@wobblini.net

Hi --

What is the recommended method for converting between Time objects and
those of type DateTime?

OK, let me try again.

   irb(main):068:0> t = Time.now
   => Sat Nov 12 13:33:08 EST 2005
   irb(main):069:0> d = DateTime.parse(t.iso8601)
   => #<DateTime: 52999645097/21600,-5/24,2299161>
   irb(main):070:0> d.strftime("%c")
   => "Sat Nov 12 13:33:08 2005"
   irb(main):071:0> Time.parse(d.strftime("%c"))
   => Sat Nov 12 13:33:08 EST 2005

'parse' seems to be a good bet in both directions.

David

···

On Sun, 13 Nov 2005, Lloyd Zusman wrote:

--
David A. Black
dblack@wobblini.net

Lloyd Zusman wrote:

What is the recommended method for converting between Time objects and
those of type DateTime?

I know that I can do this:

  dt = DateTime.new
  t = Time.mktime(dt.year, dt.mon, dt.day,
                  dt.hour, dt.min, dt.sec)

.. and this:

  t = Time.now
  dt = DateTime.civil(t.year, t.mon, t.day,
                      t.hour, t.min, t.sec)

However, this seems overly verbose to me, and I end up putting one or
both of the following into my ruby programs:

  class DateTime
    def self.fromTime(t)
      return DateTime.civil(t.year, t.mon, t.day,
                            t.hour, t.min, t.sec)
    end
  end

  class Time
    def self.fromDateTime(dt)
      return Time.mktime(dt.year, dt.mon, dt.day,
                         dt.hour, dt.min, dt.sec)
    end
  end

Is there any reason for why we can't have similar methods as part of the
official DateTime and Time classes?

Or is there already some sort of mechanism for this that I have
overlooked?

Thanks in advance.

I think this would be more Rubyish:

   class DateTime
     def to_time
       Time.mktime(year, mon, day, hour, min, sec)
     end
   end

   class Time
     def to_datetime
       DateTime.civil(year, mon, day, hour, min, sec)
     end
   end

I haven't tested it, but it should work.

Cheers,
Daniel

You have not overlooked anything.

In my standard set of extensions are these:

class Time
        def to_date
                Date.new(year, month, day)
                rescue NameError
                nil
        end

        def to_datetime
                DateTime.new(year, month, day, hour, min, sec)
                rescue NameError
                nil
        end
end

class DateTime
        def to_time
                Time.local(year,month,day,hour,min,sec)
        end
end

class Date
        def to_time
                Time.local(year,month,day)
        end
end

Kirk Haines

···

On Saturday 12 November 2005 10:54 am, Lloyd Zusman wrote:

Is there any reason for why we can't have similar methods as part of the
official DateTime and Time classes?

Or is there already some sort of mechanism for this that I have
overlooked?

Hi --

···

On Sun, 13 Nov 2005, David A. Black wrote:

Hi --

On Sun, 13 Nov 2005, Lloyd Zusman wrote:

What is the recommended method for converting between Time objects and
those of type DateTime?

This is probably just a stepping-stone on the way to something more
elegant... but try this:

require 'date'
require 'time'

t = Time.parse(DateTime.new.sec.to_s)

Withdrawn :slight_smile:

Completely wrong. Sorry.

David

--
David A. Black
dblack@wobblini.net

"David A. Black" <dblack@wobblini.net> writes:

Hi --

What is the recommended method for converting between Time objects and
those of type DateTime?

OK, let me try again.

  irb(main):068:0> t = Time.now
  => Sat Nov 12 13:33:08 EST 2005
  irb(main):069:0> d = DateTime.parse(t.iso8601)
  => #<DateTime: 52999645097/21600,-5/24,2299161>
  irb(main):070:0> d.strftime("%c")
  => "Sat Nov 12 13:33:08 2005"
  irb(main):071:0> Time.parse(d.strftime("%c"))
  => Sat Nov 12 13:33:08 EST 2005

'parse' seems to be a good bet in both directions.

Yes, I thought of these, but they involve converting to and from an
intermediate String object. The ones I suggested in my original message
are more direct ... although they each require six subsidiary method
calls.

If I get some extra time, I'll benchmark my versions against these
intermediate-String versions. But no matter which is faster, wouldn't
it ultimately be better if we had conversion methods built in to the
standard classes? Even if we don't unify Time with DateTime, these
extra contstructors would be a nice convenience.

···

On Sun, 13 Nov 2005, Lloyd Zusman wrote:

--
Lloyd Zusman
ljz@asfast.com
God bless you.

Daniel Schierbeck <daniel.schierbeck@gmail.com> writes:

[ ... ]

I think this would be more Rubyish:

  class DateTime
    def to_time
      Time.mktime(year, mon, day, hour, min, sec)
    end
  end

  class Time
    def to_datetime
      DateTime.civil(year, mon, day, hour, min, sec)
    end
  end

I haven't tested it, but it should work.

Thanks. Is this considered more ruby-ish because of the non-camel-case
of the method names? ... or because of the to_* methods instead of the
from* constructors? ... or both?

···

--
Lloyd Zusman
ljz@asfast.com
God bless you.

I don't know if that is practical. Time and Date/DateTime use two entirely
different mechanisms for keeping track of the passage of time. Time utilizes
seconds since the start of 1970 -- standard Unix time tracking.

Date/DateTime uses keeps tracks of days and fractions of days using Rational,
and it's start of time is about the start of the year in 4712 B.C.

They are quite different, and while one should not have to write one's own
code to convert from one to another -- all three classes should be patched to
allow each conversion from one to another -- they should stay separate.

Kirk Haines

···

On Saturday 12 November 2005 11:26 am, David A. Black wrote:

(Could we get all the time/date stuff unified and loaded by default?
Is that too much overhead?)

It works in both directions because the underlying 'parse' is the same
one. :slight_smile:

They all use the same the Date#_parse method defined in date/format.rb.

Using this is going to be much slower than just doing conversions with the
numerical values and constructor methods that the classes provide.

Kirk Haines

···

On Saturday 12 November 2005 11:35 am, David A. Black wrote:

OK, let me try again.

   irb(main):068:0> t = Time.now
   => Sat Nov 12 13:33:08 EST 2005
   irb(main):069:0> d = DateTime.parse(t.iso8601)
   => #<DateTime: 52999645097/21600,-5/24,2299161>
   irb(main):070:0> d.strftime("%c")
   => "Sat Nov 12 13:33:08 2005"
   irb(main):071:0> Time.parse(d.strftime("%c"))
   => Sat Nov 12 13:33:08 EST 2005

'parse' seems to be a good bet in both directions.

Kirk Haines <khaines@enigo.com> writes:

Is there any reason for why we can't have similar methods as part of the
official DateTime and Time classes?

Or is there already some sort of mechanism for this that I have
overlooked?

You have not overlooked anything.

Oh well ... (sigh)

And thanks.

In your methods below, I see "rescue" without a formal "begin/end"
block. I've never seen that construct before. I'm guessing that single
line statements don't need begin/end, correct?

···

On Saturday 12 November 2005 10:54 am, Lloyd Zusman wrote:

In my standard set of extensions are these:

class Time
        def to_date
                Date.new(year, month, day)
                rescue NameError
                nil
        end

        def to_datetime
                DateTime.new(year, month, day, hour, min, sec)
                rescue NameError
                nil
        end
end

class DateTime
        def to_time
                Time.local(year,month,day,hour,min,sec)
        end
end

class Date
        def to_time
                Time.local(year,month,day)
        end
end

Kirk Haines

--
Lloyd Zusman
ljz@asfast.com
God bless you.

Hi --

(Could we get all the time/date stuff unified and loaded by default?
Is that too much overhead?)

I don't know if that is practical. Time and Date/DateTime use two entirely
different mechanisms for keeping track of the passage of time. Time utilizes
seconds since the start of 1970 -- standard Unix time tracking.

Date/DateTime uses keeps tracks of days and fractions of days using Rational,
and it's start of time is about the start of the year in 4712 B.C.

They are quite different, and while one should not have to write one's own
code to convert from one to another -- all three classes should be patched to
allow each conversion from one to another -- they should stay separate.

I guess what I'm thinking of mostly is default loading. It seems a
little odd to see this:

   irb(main):002:0> Time
   => Time
   irb(main):003:0> require 'time'
   => true

and, in general, to have to know what you can do before you load
things and what you can only do after. Not so much reducing the three
classes to one, then, but streamlining the way it all works.

David

···

On Mon, 14 Nov 2005, Kirk Haines wrote:

On Saturday 12 November 2005 11:26 am, David A. Black wrote:

--
David A. Black
dblack@wobblini.net

In your methods below, I see "rescue" without a formal "begin/end"
block. I've never seen that construct before. I'm guessing that single
line statements don't need begin/end, correct?

no, no : this is a difference 1.4 and 1.6. Since 1.6 you can write

   def aa
      # any lines
   rescue XXX
      # any lines
   rescue YYY
      # any lines
   # ...
   else
      # any lines
   ensure
      # any lines
   end

this is only with 1.6.3 that it work also with singleton methods.

Single line statements are

   xxx rescue yyy

which is like

   begin
      xxx
   rescue
      yyy
   end

Guy Decoux

Hi --

···

On Mon, 14 Nov 2005, Lloyd Zusman wrote:

In your methods below, I see "rescue" without a formal "begin/end"
block. I've never seen that construct before. I'm guessing that single
line statements don't need begin/end, correct?

Method defs provide an implicit 'begin', so you can put a rescue
clause in them without adding a 'begin'.

David

--
David A. Black
dblack@wobblini.net

Lloyd Zusman wrote:

Daniel Schierbeck <daniel.schierbeck@gmail.com> writes:

[ ... ]

I think this would be more Rubyish:

  class DateTime
    def to_time
      Time.mktime(year, mon, day, hour, min, sec)
    end
  end

  class Time
    def to_datetime
      DateTime.civil(year, mon, day, hour, min, sec)
    end
  end

I haven't tested it, but it should work.

Thanks. Is this considered more ruby-ish because of the non-camel-case
of the method names? ... or because of the to_* methods instead of the
from* constructors? ... or both?

Both. It also allows you to do something like this:

   def some_time_method(time)
     time = time.to_time # now we know we have a Time object
   end

   some_time_method(DateTime.new(...))

That way you can use a DateTime object instead of a Time object and have it automatically converted. Otherwise, you'd have to do this:

   some_time_method(Time.from_datetime(DateTime.new(...)))

Cheers,
Daniel

Is there any reason to choose one over the other? At least for post
1970 dates? I've always found Time's API a little easier to use.

Anyone have thoughts on when one would want to use DateTime vs Time?
  .adam sanderson

For the record, I'm using this code:

class DateTime
   def to_time
     Time.mktime(year, month, day, hour, min, sec)
   end

   def to_datetime
     return self
   end
end

class Date
   def to_time
     Time.mktime(year, month, day)
   end

   def to_datetime
     to_time.to_datetime
   end

   def to_date
     return self
   end
end

class Time
   def to_date
     Date.new(year, month, day)
   end

   def to_datetime
     DateTime.civil(year, month, day, hour, min, sec)
   end

   def to_time
     return self
   end
end

Daniel Schierbeck <daniel.schierbeck@gmail.com> writes:

Lloyd Zusman wrote:

Daniel Schierbeck <daniel.schierbeck@gmail.com> writes:

[ ... ]

I think this would be more Rubyish:

  class DateTime
    def to_time
      Time.mktime(year, mon, day, hour, min, sec)
    end
  end

  class Time
    def to_datetime
      DateTime.civil(year, mon, day, hour, min, sec)
    end
  end

I haven't tested it, but it should work.

Thanks. Is this considered more ruby-ish because of the non-camel-case
of the method names? ... or because of the to_* methods instead of the
from* constructors? ... or both?

Both. It also allows you to do something like this:

  def some_time_method(time)
    time = time.to_time # now we know we have a Time object
  end

  some_time_method(DateTime.new(...))

That way you can use a DateTime object instead of a Time object and have
it automatically converted. Otherwise, you'd have to do this:

  some_time_method(Time.from_datetime(DateTime.new(...)))

Got it. Thanks!

So now, all we need is to have a few to_* conversion methods added to
the standard Time, DateTime, and Date classes so that we all don't have
to keep re-inventing this. :slight_smile:

···

--
Lloyd Zusman
ljz@asfast.com
God bless you.

ts <decoux@moulon.inra.fr> writes:

> In your methods below, I see "rescue" without a formal "begin/end"
> block. I've never seen that construct before. I'm guessing that single
> line statements don't need begin/end, correct?

no, no : this is a difference 1.4 and 1.6. Since 1.6 you can write

[ ... etc. ... ]

Ah ... thanks for the clarification.

···

--
Lloyd Zusman
ljz@asfast.com
God bless you.

"David A. Black" <dblack@wobblini.net> writes:

Hi --

In your methods below, I see "rescue" without a formal "begin/end"
block. I've never seen that construct before. I'm guessing that single
line statements don't need begin/end, correct?

Method defs provide an implicit 'begin', so you can put a rescue
clause in them without adding a 'begin'.

I never realized this. I guess I overlooked that part of the docs.
This will allow me to remove a few begin/end constructs from some of the
short methods I've written.

Thanks.

···

On Mon, 14 Nov 2005, Lloyd Zusman wrote:

--
Lloyd Zusman
ljz@asfast.com
God bless you.