Converting between Time and DateTime

L

Lloyd Zusman

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

David A. Black

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
 
D

David A. Black

Hi --

Hi --



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 :)

Completely wrong. Sorry.


David
 
D

David A. Black

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
 
L

Lloyd Zusman

David A. Black said:
Hi --



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

Daniel Schierbeck

Lloyd said:
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
 
L

Lloyd Zusman

Daniel Schierbeck said:
[ ... ]

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?
 
K

Kirk Haines

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.

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
 
K

Kirk Haines

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


Kirk Haines
 
K

Kirk Haines

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.

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

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
 
D

David A. Black

Hi --

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
 
L

Lloyd Zusman

Kirk Haines said:
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?
 
T

ts

L> In your methods below, I see "rescue" without a formal "begin/end"
L> block. I've never seen that construct before. I'm guessing that single
L> 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
 
D

David A. Black

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


David
 
D

Daniel Schierbeck

Lloyd said:
Daniel Schierbeck said:
[ ... ]

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
 
D

Daniel Schierbeck

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
 
L

Lloyd Zusman

Daniel Schierbeck said:
Lloyd said:
Daniel Schierbeck said:
[ ... ]

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. :)
 
L

Lloyd Zusman

ts said:
L> In your methods below, I see "rescue" without a formal "begin/end"
L> block. I've never seen that construct before. I'm guessing that single
L> 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.
 
L

Lloyd Zusman

David A. Black said:
Hi --



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

Daniel Schierbeck

Lloyd said:
Daniel Schierbeck said:
Lloyd said:
[ ... ]

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. :)

Yeah, but only if there's a strong enough sentiment in the community. No
reason to add to the standard library unless the functionality is really
needed.


Cheers,
Daniel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top