oddities in the datetime module

M

Max M

# -*- 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.datetime(2005, 1, 1, 0, 0)

What I find odd is that I cannot make a new datetime object from the
timetuple()
like this:
Traceback (most recent call last):
...
TypeError: function takes at most 8 arguments (9 given)(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.
datetime2(2005, 1, 1, 12, 0)
(2005, 1, 1, 0, 0, 0, 0, None)
date2(2005, 1, 1)
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
 
S

Serge Orlov

Max said:
# -*- 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:
datetime.date(2005, 1, 1)

Serge.
 
M

Max M

Serge said:
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...



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
 
S

Serge Orlov

Max said:
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.
 
T

Tim Peters

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

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,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top