oddities in the datetime module

Discussion in 'Python' started by Max M, Jan 14, 2005.

  1. Max M

    Max M Guest

    # -*- coding: latin-1 -*-

    """

    I am currently using the datetime package, but I find that the design is
    oddly
    asymmetric. I would like to know why. Or perhaps I have misunderstood
    how it should be used?

    I can make a datetime easily enough

    >>> datetime(2005, 1, 1)

    datetime.datetime(2005, 1, 1, 0, 0)

    What I find odd is that I cannot make a new datetime object from the
    timetuple()
    like this:

    >>> d1 = datetime(2005, 1, 1, 12, 13, 10)
    >>> d2 = datetime(*d1.timetuple())

    Traceback (most recent call last):
    ...
    TypeError: function takes at most 8 arguments (9 given)
    >>> d1.timetuple()

    (2005, 1, 1, 12, 13, 10, 5, 1, -1)

    Because if I subclass datetime, I often need to convert between my
    subclass and
    the built in datetime module. But there is no direct way to do it.

    Instead I have to do it in a somewhat more clunky way:

    >>> datetime(* (d1.timetuple()[:6] + (0, d1.tzinfo)))

    datetime.datetime(2005, 1, 1, 12, 13, 10)

    if I want to convert a date to a datetime it is easy, even though I
    still have
    to truncate the timetuple.

    >>> d = date(2005, 1, 1)
    >>> datetime(*d.timetuple()[:6])

    datetime.datetime(2005, 1, 1, 0, 0)

    The other way around is also easy.

    >>> dt = datetime(2005, 1, 1, 12, 0, 0)
    >>> date(*dt.timetuple()[:3])

    datetime.date(2005, 1, 1)

    But it's a clunky design that I have to do it that way.

    I think it would be nice if date and datetime at least had a pair of
    datetimetuple() and from_datetimetuple() methods that could be used for
    easily
    converting between datetime types. Like the ones I have made below.

    That would make them a lot more symmetric.

    >>> datetimetuple = (2005,1,1,12,0,0,0,None)
    >>> datetime2.from_datetimetuple(datetimetuple)

    datetime2(2005, 1, 1, 12, 0)

    >>> dtt = datetime2(2005,1, 1).datetimetuple()
    >>> dtt

    (2005, 1, 1, 0, 0, 0, 0, None)

    >>> d2 = date2.from_datetimetuple(dtt)
    >>> d2

    date2(2005, 1, 1)

    >>> datetime2.from_datetimetuple(d2.datetimetuple())

    datetime2(2005, 1, 1, 0, 0)

    """


    from datetime import datetime, date

    class datetime2(datetime):

    def datetimetuple(self):
    return self.timetuple()[:6] + (0, self.tzinfo)

    def from_datetimetuple(dt_tuple):
    return datetime2(*dt_tuple)
    from_datetimetuple = staticmethod(from_datetimetuple)


    class date2(date):

    def datetimetuple(self):
    return self.timetuple()[:6] + (0, None)

    def from_datetimetuple(dt_tuple):
    return date2(*dt_tuple[:3])
    from_datetimetuple = staticmethod(from_datetimetuple)




    #from datetime import datetime
    #
    #ical = Calendar()
    #print ical.ical()

    if __name__ == "__main__":

    import os.path, doctest, x
    # import and test this file
    doctest.testmod(x)


    --

    hilsen/regards Max M, Denmark

    http://www.mxm.dk/
    IT's Mad Science
     
    Max M, Jan 14, 2005
    #1
    1. Advertising

  2. Max M

    Serge Orlov Guest

    Max M wrote:
    > # -*- coding: latin-1 -*-
    >
    > """
    >
    > I am currently using the datetime package, but I find that the design
    > is oddly
    > asymmetric. I would like to know why. Or perhaps I have misunderstood
    > how it should be used?


    Yes, you did. datetime.timetuple is those who want *time module* format, you should use datetime.data, datetime.time, datetime.year
    and so on...

    [snip a lot of timetuple wrestling]
    > The other way around is also easy.
    >
    >>>> dt = datetime(2005, 1, 1, 12, 0, 0)
    >>>> date(*dt.timetuple()[:3])

    > datetime.date(2005, 1, 1)


    As they say, if the only tool you have is timetuple, everything looks like tuple <wink>

    Try this:

    >>> dt = datetime(2005, 1, 1, 12, 0, 0)
    >>> dt.date()

    datetime.date(2005, 1, 1)

    Serge.
     
    Serge Orlov, Jan 14, 2005
    #2
    1. Advertising

  3. Max M

    Max M Guest

    Serge Orlov wrote:
    > Max M wrote:


    > Yes, you did. datetime.timetuple is those who want *time module* format, you should use datetime.data, datetime.time, datetime.year
    > and so on...
    >
    > As they say, if the only tool you have is timetuple, everything looks like tuple <wink>
    > Try this:
    >
    >>>>dt = datetime(2005, 1, 1, 12, 0, 0)
    >>>>dt.date()

    >
    > datetime.date(2005, 1, 1)


    This doesn't solve it. I don't think you understand my issue.

    First of, it should be possible to easily convert between the datetime
    objects.

    And eg. the date object doesn't have a datetime() method. Which it could
    easily have. Neither does time. They could have. But I don't think that
    is the way to solve it.



    It is a problem if you make a subclass of datetime. Often you will ned
    to make datetime arithmetics with the new class.

    Like: datetime_subclass_1 + datetime_subclass_2

    The result of that is a plain datetime

    In that case you will rather want your own subclass returned. But
    subclasses of datetime returns datetime objects. Not the subclass.

    So to do an add of your own objects you must convert the output to your
    own class "manually"

    class my_datetime(datetime):

    def __add__(self, other):
    result = datetime.__add__(self, other)
    return my_datetime(result.timetuple()[:6])

    datetime(), time() etc. methods will not help with this.

    --

    hilsen/regards Max M, Denmark

    http://www.mxm.dk/
    IT's Mad Science
     
    Max M, Jan 14, 2005
    #3
  4. Max M

    Serge Orlov Guest

    Max M wrote:
    > Serge Orlov wrote:
    >> Max M wrote:

    >
    >> Yes, you did. datetime.timetuple is those who want *time module*
    >> format, you should use datetime.data, datetime.time, datetime.year
    >> and so on... As they say, if the only tool you have is timetuple, everything
    >> looks like tuple <wink> Try this:
    >>
    >>>>> dt = datetime(2005, 1, 1, 12, 0, 0)
    >>>>> dt.date()

    >>
    >> datetime.date(2005, 1, 1)

    >
    > This doesn't solve it. I don't think you understand my issue.


    I understand, but I don't think it's something that should be solved. Especially
    date(*dt.timetuple()[:3])


    > class my_datetime(datetime):
    >
    > def __add__(self, other):
    > result = datetime.__add__(self, other)
    > return my_datetime(result.timetuple()[:6])
    >


    What about:

    def __add__(self, other):
    result = datetime.__add__(self, other)
    return my_datetime.fromdatetime(result)

    Serge.
     
    Serge Orlov, Jan 14, 2005
    #4
  5. Max M

    Tim Peters Guest

    [Max M]
    > ...
    > First of, it should be possible to easily convert between the
    > datetime objects.


    Why? All the conversions people asked for when the module was being
    designed were implemented.

    > And eg. the date object doesn't have a datetime() method. Which
    > it could easily have.


    But not a *sensible* one. If you only have a date (or time), what's a
    conversion to datetime supposed to do about the "missing values"?
    Guess? No good.

    > Neither does time. They could have. But I don't think that
    > is the way to solve it.


    datetime.datetime objects have .date() and .time() methods, returning
    the obvious datetime.date and datetime.time slices of the
    datetime.datetime. The class constructor datetime.combine() goes in
    the other direction, building a datetime.datetime object by combining
    a datetime.date and a datetime.time.

    > It is a problem if you make a subclass of datetime. Often you
    > will ned to make datetime arithmetics with the new class.
    >
    > Like: datetime_subclass_1 + datetime_subclass_2
    >
    > The result of that is a plain datetime


    If your subclass doesn't override __add__, yes.

    > In that case you will rather want your own subclass returned.


    While possible, that's not necessarily so of all subclasses.

    > But subclasses of datetime returns datetime objects. Not the
    > subclass.


    That depends on whether the subclass overrides __add__, and if so, the
    code in its __add__ method.

    > So to do an add of your own objects you must convert the output
    > to your own class "manually"
    >
    > class my_datetime(datetime):
    >
    > def __add__(self, other):
    > result = datetime.__add__(self, other)
    > return my_datetime(result.timetuple()[:6])
    >
    > datetime(), time() etc. methods will not help with this.


    Well, it's unclear where you think you need help there. If that's
    what you want your subclass __add__ to do, you've already done it,
    right? It could save tedium to give your subclass a class
    constructor, e.g., from_datetime(), and then code __add__ as

    def __add__(self, other):
    return my_datetime.from_datetime(datetime.__add__(self, other))

    Whether the implementation wants to use timetuple() depends on what
    the subclass wants to do; for example, a subclass that intends to
    support a notion of time zone needs more than just that.
     
    Tim Peters, Jan 14, 2005
    #5
    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:
    767
    Christos TZOTZIOY Georgiou
    Sep 13, 2003
  2. Tim Peters
    Replies:
    0
    Views:
    604
    Tim Peters
    Sep 9, 2003
  3. mp
    Replies:
    1
    Views:
    445
    John Machin
    Jul 28, 2006
  4. Martin
    Replies:
    0
    Views:
    378
    Martin
    Dec 27, 2008
  5. Replies:
    2
    Views:
    806
    M.-A. Lemburg
    Jan 6, 2009
Loading...

Share This Page