Re: [Python-Dev] proposal: add basic time type to the standard library

We had a brief jam on date/time objects at Zope Corp. HQ today. I won't get to writing up the full proposal that came out of this, but I'd like to give at least a summary. (Th0se who were there: my thoughts have advanced a bit since this afternoon.) My plan is to create a standard timestamp object in C that can be subclassed. The internal representation will favor extraction of broken-out time fields (year etc.) in local time. It will support comparison, basic time computations, and effbot's minimal API, as well as conversions to and from the two currently most popular time representations used by the time module: posix timestamps in UTC and 9-tuples in local time. There will be a C API. Proposal for internal representation (also the basis for an efficient pickle format): year 2 bytes, big-endian, unsigned (0 .. 65535) month 1 byte day 1 byte hour 1 byte minute 1 byte second 1 byte usecond 3 bytes, big-endian tzoffset 2 bytes, big-endian, signed (in minutes, -1439 .. 1439) total 12 bytes Things this will not address (but which you may address through subclassing): - leap seconds - alternate calendars - years far in the future or BC - precision of timepoints (e.g. a separate Date type) - DST flags (DST is accounted for by the tzoffset field) Mini-FAQ - Why store a broken-out local time rather than seconds (or microseconds) relative to an epoch in UTC? There are two kinds of operations on times: accessing the broken-out fields (probably in local time), and time computations. The chosen representation favors accessing broken-out fields, which I expect to be more common than time computations. - Why a big-endian internal representation? So that comparison can be done using a single memcmp() call as long as the tzoffset fields are the same. - Why not pack the fields closer to save a few bytes? To make the pack and unpack operations more efficient; the object footprint isn't going to make much of a difference. - Why is the year unsigned? So memcmp() will do the right thing for comparing dates (in the same timezone). - What's the magic number 1439? One less than 24 * 60. Timezone offsets may be up to 24 hours. (The C99 standard does it this way.) I'll try to turn this into a proper PEP ASAP. (Stephan: do I need to CC you or are you reading python-dev?) --Guido van Rossum (home page: http://www.python.org/~guido/)

Guido> Proposal for internal representation (also the basis for an Guido> efficient pickle format): Guido> year 2 bytes, big-endian, unsigned (0 .. 65535) ... Guido> - Why is the year unsigned? So memcmp() will do the right thing Guido> for comparing dates (in the same timezone). So the earliest year it can represent is 1BC (or does year == 0 represent some other base year)? One of MAL's desires were that he could use the abstract interface /F defined and remain binary compatible with the current mxDateTime layout. Will your layout work for him? Skip

Correct.
My layout is incompatible with that of mxDateTime, but this is not supposed to be /F's abstract interface -- this is supposed to be one implementation of it, mxDateTime can be another. --Guido van Rossum (home page: http://www.python.org/~guido/)

[Guido van Rossum]
As an earlier msg said, "details, details". Any chance of setting up a Wiki for this project? I'd also suggest writing the test suite first, because I suspect that asking people to submit tests is the only effective way to tease out their hidden assumptions and requirements.
Those are of type time_t, and that's opaque (maybe of a floating or integral type, depending on platform). What's the type in Python? By "posix" timestamps I assume you mean to imply at least "no leap seconds". Note that POSIX/SUS still doesn't require that time_t "work" beyond 2038, so we have to define what happens then on platforms using stupid time_t. What about years before 1970? POSIX/SUS still leaves that undefined, and also time() values < 0, except for (time_t)-1 (which means "error" from time() -- although no possible errors are defined for time()!).
and 9-tuples in local time.
Too depressing to even consider one-by-one <wink>.
There will be a C API.
Most of the questions above were about that.
Do you intend to treat October 1582 as a magical month? Note that to the chagrin of calendar weenies, ECMAScript explicitly refused to, pretending instead that the current Gregorian calendar always was, and always will be, in effect. I'm +1 on us doing likewise. In part, the more uniform we make this abstraction, the more good it will do people who want some insane <wink> sort of date gimmick instead (if our rules are regular, they can adjust our results by injecting their favorite insanities, without having to first subtract out our insanities).
I've rarely seen docs for any time gimmick that made it *clear* whether the time zone offset needs to be added to, or subtracted from, the rest of the fields, to get the corresponding UTC point. Plain "offset" is plainly ambiguous. Authors think they're being clear using "ahead" or "behind" instead, but at least twice I've seen those used in a backwards sense too. Which direction do you have in mind? Does it matter? Maybe we should add a flag bit to say which direction is intended <wink>. Overall, I like it -- it's just the details, details, details that make this kind of thing a drag before it's real.

Tim Peters writes:
An excellent idea, of course! Here's just such a wiki: http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage I've only filled in a couple of things relating to collecting requirements. I'll start to summarize what's been decided & discussed so far tomorrow, unless someone beats me to it. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> PythonLabs at Zope Corporation

Thanks for the encouragement, Tim! I've added the initial design (such as it is) plus my answers to Tim's questions to Fred's Wiki, here: http://www.zope.org/Members/fdrake/DateTimeWiki/BasicDesign --Guido van Rossum (home page: http://www.python.org/~guido/)

I've now added a prototype implementation in Python of a datetime type to CVS: nondist/sandbox/datetime/datetime.py; see also http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage for a link directly to ViewCVS. --Guido van Rossum (home page: http://www.python.org/~guido/)

Guido> Proposal for internal representation (also the basis for an Guido> efficient pickle format): Guido> year 2 bytes, big-endian, unsigned (0 .. 65535) ... Guido> - Why is the year unsigned? So memcmp() will do the right thing Guido> for comparing dates (in the same timezone). So the earliest year it can represent is 1BC (or does year == 0 represent some other base year)? One of MAL's desires were that he could use the abstract interface /F defined and remain binary compatible with the current mxDateTime layout. Will your layout work for him? Skip

Correct.
My layout is incompatible with that of mxDateTime, but this is not supposed to be /F's abstract interface -- this is supposed to be one implementation of it, mxDateTime can be another. --Guido van Rossum (home page: http://www.python.org/~guido/)

[Guido van Rossum]
As an earlier msg said, "details, details". Any chance of setting up a Wiki for this project? I'd also suggest writing the test suite first, because I suspect that asking people to submit tests is the only effective way to tease out their hidden assumptions and requirements.
Those are of type time_t, and that's opaque (maybe of a floating or integral type, depending on platform). What's the type in Python? By "posix" timestamps I assume you mean to imply at least "no leap seconds". Note that POSIX/SUS still doesn't require that time_t "work" beyond 2038, so we have to define what happens then on platforms using stupid time_t. What about years before 1970? POSIX/SUS still leaves that undefined, and also time() values < 0, except for (time_t)-1 (which means "error" from time() -- although no possible errors are defined for time()!).
and 9-tuples in local time.
Too depressing to even consider one-by-one <wink>.
There will be a C API.
Most of the questions above were about that.
Do you intend to treat October 1582 as a magical month? Note that to the chagrin of calendar weenies, ECMAScript explicitly refused to, pretending instead that the current Gregorian calendar always was, and always will be, in effect. I'm +1 on us doing likewise. In part, the more uniform we make this abstraction, the more good it will do people who want some insane <wink> sort of date gimmick instead (if our rules are regular, they can adjust our results by injecting their favorite insanities, without having to first subtract out our insanities).
I've rarely seen docs for any time gimmick that made it *clear* whether the time zone offset needs to be added to, or subtracted from, the rest of the fields, to get the corresponding UTC point. Plain "offset" is plainly ambiguous. Authors think they're being clear using "ahead" or "behind" instead, but at least twice I've seen those used in a backwards sense too. Which direction do you have in mind? Does it matter? Maybe we should add a flag bit to say which direction is intended <wink>. Overall, I like it -- it's just the details, details, details that make this kind of thing a drag before it's real.

Tim Peters writes:
An excellent idea, of course! Here's just such a wiki: http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage I've only filled in a couple of things relating to collecting requirements. I'll start to summarize what's been decided & discussed so far tomorrow, unless someone beats me to it. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> PythonLabs at Zope Corporation

Thanks for the encouragement, Tim! I've added the initial design (such as it is) plus my answers to Tim's questions to Fred's Wiki, here: http://www.zope.org/Members/fdrake/DateTimeWiki/BasicDesign --Guido van Rossum (home page: http://www.python.org/~guido/)

I've now added a prototype implementation in Python of a datetime type to CVS: nondist/sandbox/datetime/datetime.py; see also http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage for a link directly to ViewCVS. --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (4)
-
Fred L. Drake, Jr.
-
Guido van Rossum
-
Skip Montanaro
-
Tim Peters