Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Converting between Time and DateTime

23 views
Skip to first unread message

Lloyd Zusman

unread,
Nov 12, 2005, 12:54:58 PM11/12/05
to
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
l...@asfast.com
God bless you.

David A. Black

unread,
Nov 12, 2005, 1:26:07 PM11/12/05
to
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)

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


David

--
David A. Black
dbl...@wobblini.net


David A. Black

unread,
Nov 12, 2005, 1:28:32 PM11/12/05
to
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 :-)

Completely wrong. Sorry.

David A. Black

unread,
Nov 12, 2005, 1:35:11 PM11/12/05
to
Hi --

On Sun, 13 Nov 2005, Lloyd Zusman wrote:

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

Lloyd Zusman

unread,
Nov 12, 2005, 1:49:50 PM11/12/05
to

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.

Daniel Schierbeck

unread,
Nov 12, 2005, 2:22:56 PM11/12/05
to
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

Lloyd Zusman

unread,
Nov 13, 2005, 10:45:30 AM11/13/05
to
Daniel Schierbeck <daniel.s...@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?

Kirk Haines

unread,
Nov 13, 2005, 10:46:51 AM11/13/05
to
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?

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


Kirk Haines

unread,
Nov 13, 2005, 10:55:36 AM11/13/05
to
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?)

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


Kirk Haines

unread,
Nov 13, 2005, 11:03:49 AM11/13/05
to
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.

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


David A. Black

unread,
Nov 13, 2005, 11:06:46 AM11/13/05
to
Hi --

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.

Lloyd Zusman

unread,
Nov 13, 2005, 11:07:26 AM11/13/05
to
Kirk Haines <kha...@enigo.com> writes:

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


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

--

ts

unread,
Nov 13, 2005, 11:36:05 AM11/13/05
to
>>>>> "L" == Lloyd Zusman <l...@asfast.com> writes:

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


David A. Black

unread,
Nov 13, 2005, 11:36:55 AM11/13/05
to
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'.

Daniel Schierbeck

unread,
Nov 13, 2005, 11:42:28 AM11/13/05
to

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

Daniel Schierbeck

unread,
Nov 13, 2005, 12:14:48 PM11/13/05
to
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

Lloyd Zusman

unread,
Nov 13, 2005, 12:21:58 PM11/13/05
to
Daniel Schierbeck <daniel.s...@gmail.com> writes:

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

Lloyd Zusman

unread,
Nov 13, 2005, 12:22:08 PM11/13/05
to
ts <dec...@moulon.inra.fr> writes:

>>>>>> "L" == Lloyd Zusman <l...@asfast.com> writes:
>
> 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.

Lloyd Zusman

unread,
Nov 13, 2005, 12:32:02 PM11/13/05
to
"David A. Black" <dbl...@wobblini.net> writes:

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

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.

Daniel Schierbeck

unread,
Nov 13, 2005, 12:39:20 PM11/13/05
to

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

Steven Grady From:

unread,
Nov 14, 2005, 10:33:20 AM11/14/05
to
Daniel Schierbeck <daniel.s...@gmail.com> writes:

Well, as it turns out, last week I spent about an hour looking for
these conversion functions (using ri, the pickaxe book, etc.), before
realizing they weren't part of the standard library and writing them myself.
Another reason to add to the standard library is if something is so natural
that is confusing to _not_ find it there.
--
Steven
gr...@xcf.berkeley.edu
"Bobby, if you weren't my son, I'd hug you."

Adam Sanderson

unread,
Nov 14, 2005, 1:07:11 PM11/14/05
to
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

Kirk Haines

unread,
Nov 14, 2005, 1:47:03 PM11/14/05
to

The range is one difference. If you want to represent 376 AD, you can't use
Time.

Time will be faster, since DateTime uses Rational for everything. DateTime's
units are days and fractions of days. That might make a difference to you,
or it might not. If you are doing a lot of date conversion or date math, you
might find DateTime easier to use.

Hmmm. It's a good question, and I don't have as good an answer as you want,
probably.

Personally, I use Time unless I am dealing with date ranges that go beyond
what Time handles, as a general rule.


Kirk Haines


Sam Gentle

unread,
Nov 15, 2005, 1:51:16 AM11/15/05
to
On 11/15/05, Kirk Haines <kha...@enigo.com> wrote:
> On Monday 14 November 2005 11:12 am, Adam Sanderson wrote:
> > 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?
>
> The range is one difference. If you want to represent 376 AD, you can't use
> Time.
>
> Time will be faster, since DateTime uses Rational for everything. DateTime's
> units are days and fractions of days. That might make a difference to you,
> or it might not. If you are doing a lot of date conversion or date math, you
> might find DateTime easier to use.

Sounds a bit to me like the difference between Fixnum and Bignum...

Sam


Chris Pine

unread,
Nov 15, 2005, 7:44:05 AM11/15/05
to
> Sounds a bit to me like the difference between Fixnum and Bignum...

Except that those convert to the one you want automatically, and have
a common superclass (Integer), and just generally play together
nicely.

I *wish* Time and DateTime worked more like Fixnum and Bignum.

Chris


kzm

unread,
Nov 15, 2005, 7:48:35 AM11/15/05
to
hey list...

i need to unsubscribe for a while.. i am not sure it works here,
can anybody tell me please?

thanx

\n

Daniel Schierbeck

unread,
Nov 15, 2005, 8:49:36 AM11/15/05
to

What kind of change would you suggest?


Cheers,
Daniel

Kirk Haines

unread,
Nov 15, 2005, 11:05:17 AM11/15/05
to
On Tuesday 15 November 2005 6:52 am, Daniel Schierbeck wrote:

> > I *wish* Time and DateTime worked more like Fixnum and Bignum.
> >
> > Chris
>
> What kind of change would you suggest?

The analagous behavior would be for every Time method that could have a date
out of range check its inputs, and if that is going to occur, it switched
over to DateTime. However, within the library, that poses some issues.

First, it means lots of value checks on many methods, which is additional
overhead. It also means that in order for this to be relatively transparent,
implementations of a plethora of Time methods, like gm and local and others,
for DateTime. Then, though, does one take the mountain of methods unique to
Date/DateTime and make versions of them in Time? It seems like an awful lot
of code and overhead added to the system libraries for something that's
pretty easy to detect and handle oneself in cases where it is needed, IMHO.

The internal and external aspects of the two classes are so different that I
think it's dangerous to have any built-in casting from one to the other in
the standard library.

I think that there should be some convenience methods, as we have discussed,
to go to and from the three classes (Date, DateTime, and Time), though. One
should not have to reinvent that wheel.


Kirk Haines


Daniel Schierbeck

unread,
Nov 15, 2005, 12:07:20 PM11/15/05
to
I agree. Though I think the very it's odd that Time and DateTime
essentially do the same thing (they both represent a date and a time).

This hierarchy would be clearer to me

Time - e.g. 13:05:23 or 5:43 PM
Date - e.g. June 5 1978 A.C. or August 2 430 B.C.
DateTime - e.g. 5:43 PM, June 5 1978 A.C.

This would basically make a Time instance represent a time of day, and
not also a date.

dt = DateTime.now
dt.date # returns a Date object
dt.time # returns a Time object

There could also be a TimeDuration, which represent, well, a duration of
time, e.g. 134 hours, 34 minutes and 11 seconds.


just my $ 5 * 10^-2
Daniel

Ron M

unread,
Nov 16, 2005, 8:22:46 AM11/16/05
to
Daniel Schierbeck wrote:

> Chris Pine wrote:
>
>> I *wish* Time and DateTime worked more like Fixnum and Bignum.
>
> What kind of change would you suggest?

I'd like classes like DBI that use Time to (through some trick
like integer->bignum) allow dates 200 years in the future.


Today, that's not the case, and selecting fields representing
a 200-year-lease throws an error when done through DBI.


irb(main):028:0> dbh.select_all("select begin_date,end_date from leases")
ArgumentError: time out of range
from /usr/lib/ruby/site_ruby/1.8/dbi/sql.rb:60:in `gm'
from /usr/lib/ruby/site_ruby/1.8/dbi/sql.rb:60:in `as_timestamp'
from /usr/lib/ruby/site_ruby/1.8/DBD/Pg/Pg.rb:777:in `as_timestamp'
# end date is in 2204.

I'd like to see a Time with an out-of-range year automatically
produce a 'BigTime' class in exactly the same way that an out
of range integer produces a Bignum. Whether this is the same
as DateTime or not doesn't matter much to me. Being able to
use a realistic range of dates in DBI does.

Tanaka Akira

unread,
Nov 16, 2005, 10:39:24 AM11/16/05
to
In article <437B3393...@cheapcomplexdevices.com>,
Ron M <rm_r...@cheapcomplexdevices.com> writes:

> I'd like to see a Time with an out-of-range year automatically
> produce a 'BigTime' class in exactly the same way that an out
> of range integer produces a Bignum. Whether this is the same
> as DateTime or not doesn't matter much to me. Being able to
> use a realistic range of dates in DBI does.

I think it is hard to do.

Time class needs timezone information provided by OS. But
OS doesn't provides the information for out-of-range year.

So currently I hope 64bit time_t in 64bit OS will be popular.
Since Ruby supports 64bit time_t, Time class works with much
more future on such OS.
--
Tanaka Akira


Kirk Haines

unread,
Nov 16, 2005, 12:14:28 PM11/16/05
to
On Wednesday 16 November 2005 6:22 am, Ron M wrote:
> Daniel Schierbeck wrote:
> > Chris Pine wrote:
> >> I *wish* Time and DateTime worked more like Fixnum and Bignum.
> >
> > What kind of change would you suggest?
>
> I'd like classes like DBI that use Time to (through some trick
> like integer->bignum) allow dates 200 years in the future.
>
>
> Today, that's not the case, and selecting fields representing
> a 200-year-lease throws an error when done through DBI.

That's a DBI problem, though. DBI should use a class appropriate for the
input, and IMHO, should probably default to DateTime instead of Time, though
that's not really a backwards compatible change. The next best thing is for
DBI to pay attention to the inputs, and use DateTime in cases where the
inputs are out of range for Time.

I can provide you with a patch to enable that. Maybe today.


Kirk Haines


0 new messages