the Gravity of Python 2

Chris Angelico rosuav at gmail.com
Thu Jan 9 09:57:57 EST 2014


On Fri, Jan 10, 2014 at 1:14 AM, Roy Smith <roy at panix.com> wrote:
> In article <mailman.5244.1389254198.18130.python-list at python.org>,
>  Chris Angelico <rosuav at gmail.com> wrote:
>
>> What can you (Roy), with your use-case, achieve with datetime that
>> you can't achieve (at least reasonably easily) with a timestamp?

Thanks for this collection! Now we can discuss.

> As I'm mentioned several times, when you print a datetime, you get
> something that's human friendly.  When you print a timestamp (i.e. a
> float), you get a lot of digits.  I don't know about you, but I can't
> look at 1389274842 and get any feel for whether that was in the middle
> of the night or at 5 in the afternoon, near our peak traffic time.  Nor
> can I tell if it was today, yesterday, last month, or a week from next
> Tuesday.

Sure. There is a lot of value in having a class that knows how it
should be displayed. I'm not sure the current datetime repr is good
for anything more than debugging, but I agree that
"datetime.datetime(2014, 1, 9, 5, 57, 59, 929176)" is more likely to
be useful than a raw number.

> Datetimes make it easy to do things like, "find the time of the
> preceding (or following) midnight".  Or, "what month is this timestamp
> part of?"  These are operations we need to do a lot, to answer questions
> like, "How many unique users did we have on a given day?", or "Which
> monthly database archive file do I need to grab to get information about
> this historical event?"

That's true; the same operations done with timestamps look like this:

>>> ts = time.time()
>>> ts_at_midnight_utc = ts - ts%86400
>>> ts_at_midnight_utc
1389225600.0

Not nearly as obvious what's happening. And months are more
complicated still, so it's probably easiest to use strftime:

>>> time.strftime("%Y%m",time.gmtime(ts))
'201401'

which could then be used as a lookup key for a counter or whatever.
Yep, that's not as clean as simply calling a method.

> Datetimes are self-documenting.  If I'm in the python shell and have
> something called t, I can do help(t) or dir(t) to find out what
> operations it has.

Partly true, but not everything's there. For instance, if you have a
list of strings, you won't find a way to join them together in its
help() or dir(), and yet it's a fundamental and very important
operation.

> Datetimes are self-describing.  If I have a datetime or a timedelta, I
> know what I've got.  I've written more than one bug where I assumed a
> number somebody handed me was in seconds but it turned out to be in ms.
> That can never happen with a timedelta.  We do a lot of stuff in
> javascript, where times are ms, so this is a common problem for us.

Sure. Though that's no different from other cases where you need
out-of-band information to understand something, as we've just been
discussing in the threads about text handling - if you have a puddle
of bytes, you can't decode them to text without knowing what the
encoding is. [1] If your data's coming from JS, it won't be a
timedelta, it'll be a number; at some point you have to turn that into
a timedelta object, so you still have the same problem.

> Oh, and another thing I can do with a datetime that I can't do with a
> unix timestamp.  I can represent the day I was born.

Maybe you can't with the original C definition of time_t as an
unsigned integer, but the notion of a Unix timestamp can plausibly be
extended (a) to negative numbers, and (b) to non-integers. Python
definitely does the latter; its ability to do the former depends
somewhat on the underlying C library's support:

Windows:
>>> time.strftime("%Y%m",time.gmtime(-100000))
Traceback (most recent call last):
  File "<pyshell#163>", line 1, in <module>
    time.strftime("%Y%m",time.gmtime(-100000))
OSError: [Errno 22] Invalid argument

Linux:
>>> time.strftime("%Y%m",time.gmtime(-100000))
'196912'
>>> time.strftime("%Y%m",time.gmtime(-2**31))
'190112'
>>> time.strftime("%Y%m",time.gmtime(-2**31-1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: timestamp out of range for platform time_t

So what I'm seeing here is that the direct use of a time_t will cover
everything in an ugly way, but that a class wrapping it up could fix
that. And fundamentally, the only problem with datetime (which, for
the most part, is exactly that wrapper) is that it's unobvious how to
get a simple UTC timestamp.

Has the unobviousness been solved by a simple recipe? And if so,
should that tip be added to the datetime module docs somewhere?

ChrisA

[1] Yes, I said "puddle of bytes". What would you call it? Am
interested to hear!



More information about the Python-list mailing list