[Zope3-dev] datetime objects

Tim Peters tim@zope.com
Wed, 11 Dec 2002 11:19:16 -0500


[Ulrich Eck]
> i'm working on my Task Scheduler and play around with the
> datetime objects
> ..
> i found some strange behaviour with datetime/timedelta:
>
> I'm using python-2.2.2/linux
>
> 1. is this a bug ??
> ----------------------------------
> >>> from datetime import datetime
> >>> def test_datetime():
> ...   d = datetime.now()
> ...   for i in range(1000):
> ...     xd = datetime.now()
> ...     print xd - d
> ...     d = xd
> ...
> >>> test_datetime()
>
> sometimes prints (reproducable, but not
> on any linux-machine):
>
> 0:00:00.000764
> 0:00:00.000762
> -1 days, 23:59:59.995242
> 0:00:00.000872
> 0:00:00.000778

Unfortunately, times revealed by an OS can "run backwards" due to clock
adjustments.  "-1 days, 23:59:59.995242" is negative 4758 microseconds.
Whether this happens on any given box depends on lots of things, all of
which are outside of Python's control.

> --------------------------------
>
> 2. another bug ??
> >>> from datetime import datetime
> >>> d1 = datetime.now()
> >>> d2 = datetime.now()
> >>> d1 - d2
> timedelta(-1, 86395, 113112)
> >>> abs(d1 - d2)
> timedelta(0, 4, 886888)
> >>> d1
> datetime(2002, 12, 11, 16, 21, 3, 920367)
> >>> d2
> datetime(2002, 12, 11, 16, 21, 8, 807255)
> >>> d1 - d2
> timedelta(-1, 86395, 113112)
>
> the latter should be a negative timedelta of about 5 seconds !!!

It is.  timedelta fields are normalized so that

    0 <= seconds < 24*3600
    0 <= microseconds < 1000000

>>> t = timedelta(-1, 86395, 113112)
>>> t
_datetime.timedelta(-1, 86395, 113112)
>>> -t
_datetime.timedelta(0, 4, 886888)
>>>

So it's very close to negative 5 seconds.  Normalization is needed so that
the representation of a timedelta is unique; this makes comparison and
hashing efficient; if we didn't normalize them at construction time, we'd
have to normalize them dynamically every time a comparison or hash was
invoked.

> i've looked at the python-cvs sandbox and there is an implementation
> of datetime that is under development. is this implementation
> supposed to replace the current datetime module ??

There are two implementations of datetime in the sandbox:  a pure Python
implementation, and a pure C implementation.  Zope3 occassionally synchs up
with the Python implementation.  The C implementation will be part of Python
2.3, and Zope will eventually move to it.  The Python and C implementations
are as identical as possible.  In some cases they can't be.  For example,
datetime.now() uses the more-accurate gettimeofday() on Linux under the C
implementation, but that isn't available to the Python implementation.

> what needs to be done to make the current implementation working ??

timedelta is working as intended.  I'm afraid Python can't do anything about
systems that make time appear to run backwards.