Converting between Time and DateTime

Discussion in 'Ruby' started by Lloyd Zusman, Nov 12, 2005.

  1. Lloyd Zusman

    Lloyd Zusman Guest

    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

    God bless you.
    Lloyd Zusman, Nov 12, 2005
    #1
    1. Advertising

  2. 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
    David A. Black, Nov 12, 2005
    #2
    1. Advertising

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

    --
    David A. Black
    David A. Black, Nov 12, 2005
    #3
  4. 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.


    David

    --
    David A. Black
    David A. Black, Nov 12, 2005
    #4
  5. Lloyd Zusman

    Lloyd Zusman Guest

    "David A. Black" <> writes:

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


    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.


    --
    Lloyd Zusman

    God bless you.
    Lloyd Zusman, Nov 12, 2005
    #5
  6. 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
    Daniel Schierbeck, Nov 12, 2005
    #6
  7. Lloyd Zusman

    Lloyd Zusman Guest

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

    God bless you.
    Lloyd Zusman, Nov 13, 2005
    #7
  8. Lloyd Zusman

    Kirk Haines Guest

    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, Nov 13, 2005
    #8
  9. Lloyd Zusman

    Kirk Haines Guest

    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, Nov 13, 2005
    #9
  10. Lloyd Zusman

    Kirk Haines Guest

    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
    Kirk Haines, Nov 13, 2005
    #10
  11. Hi --

    On Mon, 14 Nov 2005, Kirk Haines wrote:

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


    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

    --
    David A. Black
    David A. Black, Nov 13, 2005
    #11
  12. Lloyd Zusman

    Lloyd Zusman Guest

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


    --
    Lloyd Zusman

    God bless you.
    Lloyd Zusman, Nov 13, 2005
    #12
  13. Lloyd Zusman

    ts Guest

    >>>>> "L" == Lloyd Zusman <> 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
    ts, Nov 13, 2005
    #13
  14. 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
    David A. Black, Nov 13, 2005
    #14
  15. Lloyd Zusman wrote:
    > Daniel Schierbeck <> 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
    Daniel Schierbeck, Nov 13, 2005
    #15
  16. 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, Nov 13, 2005
    #16
  17. Lloyd Zusman

    Lloyd Zusman Guest

    Daniel Schierbeck <> writes:

    > Lloyd Zusman wrote:
    >> Daniel Schierbeck <> 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. :)


    --
    Lloyd Zusman

    God bless you.
    Lloyd Zusman, Nov 13, 2005
    #17
  18. Lloyd Zusman

    Lloyd Zusman Guest

    ts <> writes:

    >>>>>> "L" == Lloyd Zusman <> 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

    God bless you.
    Lloyd Zusman, Nov 13, 2005
    #18
  19. Lloyd Zusman

    Lloyd Zusman Guest

    "David A. Black" <> 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.


    --
    Lloyd Zusman

    God bless you.
    Lloyd Zusman, Nov 13, 2005
    #19
  20. Lloyd Zusman wrote:
    > Daniel Schierbeck <> writes:
    >
    >> Lloyd Zusman wrote:
    >>> Daniel Schierbeck <> 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. :)
    >
    >


    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
    Daniel Schierbeck, Nov 13, 2005
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christos TZOTZIOY Georgiou
    Replies:
    3
    Views:
    704
    Christos TZOTZIOY Georgiou
    Sep 13, 2003
  2. Tim Peters
    Replies:
    0
    Views:
    532
    Tim Peters
    Sep 9, 2003
  3. mp
    Replies:
    1
    Views:
    386
    John Machin
    Jul 28, 2006
  4. Martin
    Replies:
    0
    Views:
    333
    Martin
    Dec 27, 2008
  5. Replies:
    2
    Views:
    754
    M.-A. Lemburg
    Jan 6, 2009
Loading...

Share This Page