(datetime — datetime).seconds

231 阅读1分钟
原文链接: medium.com

(datetime — datetime).seconds

Yet another WTF in a standard library

Go to the profile of George Shuklin
George ShuklinBlockedUnblockFollowFollowing

Today I got yet another story to tell about another pitfall in the Python standard library. Most of the Python library is well-written and is obvious to use. That creates false sense of security. Reading the docs is essential, and today I have a story of big WTF for those, who does not read them. Count me in…

datetime

datetime is a good library for handling objects with date and time. Everything related to time is complicated, because we have days, years, hours, leap seconds, leap years, leap weeks (…nah, I’ve invented that …I hope). Anyway, datetime gives a sane interface to handle them. One of it’s nice features is a timedelta type, which is a return type for subtraction between two datetype objects. It says how much time is between two events. It even have a human-readable form for it:

>>> event1 = datetime.datetime(2018, 12, 4, 15, 9, 58, 1)>>> event2 = datetime.datetime(2018, 12, 19, 17, 55, 0, 2)>>> event2 - event1datetime.timedelta(15, 9902, 1)>>> str(event2 - event1)'15 days, 2:45:02.000001'

What a nice library!

Pitfall ahead

I used it in my code to calculate number of seconds between to events. I made dir() on timedelta object and found this:

['__abs__',... 'days', 'max', 'microseconds', 'min', 'resolution', 'seconds'...

Good! timedelta.seconds is the answer. I have suspicion that it can be ‘number of seconds which is less then a minute (so, days=15, hours=2, minutes=45 seconds=2 for example from above). But it was a pretty big number:

>>> (event2 - event1).seconds9902

Excellent!

… Only after few months in production and after hour of debugging of some bizarre inconsistency in my script, I found that….

(yes, READ THE DOCS!)

|  Data descriptors defined here: |  days |      Number of days. |   |  microseconds |      Number of microseconds (>= 0 and less than 1 second). |   |  seconds |      Number of seconds (>= 0 and less than 1 day).

The variable seconds have number of seconds less than day. The proper function to call (for my purposes is timedelta.total_seconds()).

So, timedelta.seconds is timedelta.total_seconds() % 86400

Good luck with debugging this.

Was I wrong? Yes. Have I made a mistake? Yes.

Do I feel WTFed? Yes, beyond recognition.