datetime +/- scalars (int, long, float)?
Would it be good to allow adding/subtracting scalars (int, long, float) to/from date/times? The scalar value would be # of seconds. So: dt = datetime() # some date/time dt + 5 # would add 5 seconds dt + 5.3 # would add 5 seconds 300000 usecs If so, attached is a patch. Neal -- Index: sandbox/datetime/datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.22 diff -w -u -r1.22 datetime.py --- sandbox/datetime/datetime.py 3 Mar 2002 06:11:54 -0000 1.22 +++ sandbox/datetime/datetime.py 3 Mar 2002 14:26:19 -0000 @@ -590,6 +590,13 @@ result.__microsecond = us result.__tzoffset = self.__tzoffset return result + elif isinstance(other, (int, long)): + return self + timedelta(0, other) + elif isinstance(other, float): + # XXX not sure if float needs it's own condition or + # XXX should work the same as int/long + ss, us = divmod(other, 1000000) + return self + timedelta(0, ss, int(us)) return NotImplemented __radd__ = __add__ @@ -598,6 +605,13 @@ "Subtract two datetimes, or a datetime and a timedelta." if isinstance(other, timedelta): return self + -other + elif isinstance(other, (int, long)): + return self + -timedelta(0, other) + elif isinstance(other, float): + # XXX not sure if float needs it's own condition or + # XXX should work the same as int/long + ss, us = divmod(other, 1000000) + return self + -timedelta(0, ss, int(us)) if isinstance(other, datetime): days1 = self.toordinal() days2 = other.toordinal()
Would it be good to allow adding/subtracting scalars (int, long, float) to/from date/times? The scalar value would be # of seconds.
So: dt = datetime() # some date/time dt + 5 # would add 5 seconds dt + 5.3 # would add 5 seconds 300000 usecs
Yes, I think so. Timedelta should also support this, I believe. Thanks for the patch! Of course, the test suite needs to be augmented too. BTW, we prefer comments and edits to the Wiki over the mailing list: http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage I've added this already. --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
Would it be good to allow adding/subtracting scalars (int, long, float) to/from date/times? The scalar value would be # of seconds.
So: dt = datetime() # some date/time dt + 5 # would add 5 seconds dt + 5.3 # would add 5 seconds 300000 usecs
Yes, I think so. Timedelta should also support this, I believe. Thanks for the patch! Of course, the test suite needs to be augmented too.
BTW, we prefer comments and edits to the Wiki over the mailing list:
http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
I've added this already.
Hope you don't mind ;-) ... You should name the type timestamp if you want to imply dt + n == dt + n seconds. datetime + n is commonly understood as dt + n *days*. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/
Hope you don't mind ;-) ...
Not at all, we're hoping to arrive at something usable and fun for all!
You should name the type timestamp if you want to imply dt + n == dt + n seconds. datetime + n is commonly understood as dt + n *days*.
Hm, I hadn't thought of that. To me seconds are the only thing that makes sense because that's what a Unix timestamp does, but I haven't read or written a lot of commercial code using date/time data. Is this just an mxDateTime convention, or is it in wider use? (URLs of docs of other languages / libraries would really help to convince me!) --Guido van Rossum (home page: http://www.python.org/~guido/)
On Mon, 4 Mar 2002, Guido van Rossum wrote:
You should name the type timestamp if you want to imply dt + n == dt + n seconds. datetime + n is commonly understood as dt + n *days*. [...] Is this just an mxDateTime convention, or is it in wider use? (URLs of docs of other languages / libraries would really help to convince me!)
I'm afraid that this really is the de-facto standard. However, lets be clear; is t=t+1 adding 1 (calendar) day or 24 hours (86400 seconds)? -Kevin -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com
[MAL]
You should name the type timestamp if you want to imply dt + n == dt + n seconds. datetime + n is commonly understood as dt + n *days*. [...]
[me]
Is this just an mxDateTime convention, or is it in wider use? (URLs of docs of other languages / libraries would really help to convince me!)
[Kevin]
I'm afraid that this really is the de-facto standard.
Then I propose to remove the feature of automatic mixing int/long/float and datetime or timedelta instances in add/subtract operations. You'll have to specify what you want using a timedelta(days, seconds) constructor. That's clearer anyway.
However, lets be clear; is t=t+1 adding 1 (calendar) day or 24 hours (86400 seconds)?
How does it differ? (We already ignore leap seconds.) --Guido van Rossum (home page: http://www.python.org/~guido/)
[Guido] Then I propose to remove the feature of automatic mixing int/long/float and datetime or timedelta instances in add/subtract operations. You'll have to specify what you want using a timedelta(days, seconds) constructor. That's clearer anyway.
I much prefer this. My own datetime object uses a syntax like this: t = t + Delta(days=1,minutes=-5,seconds=5)
However, lets be clear; is t=t+1 adding 1 (calendar) day or 24 hours (86400 seconds)?
How does it differ? (We already ignore leap seconds.)
The concept of a "day" can be somewhat ambiguous. I've seen datetime implementations that will apply DST changes when asked to adjust by days, but not when asked to adjust by seconds, hours or minutes. So, in the general case of a DST aware datetime object, t + Delta(days=1) != t + Delta(hours=24) even when ignoring leap-seconds and other micro-adjustments. So lets define adjustments by "days" for the base datetime object in terms of 86400.0 seconds. A DST aware datetime subclass can then be made that does the more complex day-based arithmetic. -Kevin -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com
[Guido] Then I propose to remove the feature of automatic mixing int/long/float and datetime or timedelta instances in add/subtract operations. You'll have to specify what you want using a timedelta(days, seconds) constructor. That's clearer anyway.
[Kevin]
I much prefer this. My own datetime object uses a syntax like this:
t = t + Delta(days=1,minutes=-5,seconds=5)
I'm considering such an extension to the timedelta() constructor too.
However, lets be clear; is t=t+1 adding 1 (calendar) day or 24 hours (86400 seconds)?
How does it differ? (We already ignore leap seconds.)
The concept of a "day" can be somewhat ambiguous. I've seen datetime implementations that will apply DST changes when asked to adjust by days, but not when asked to adjust by seconds, hours or minutes. So, in the general case of a DST aware datetime object,
t + Delta(days=1) != t + Delta(hours=24)
even when ignoring leap-seconds and other micro-adjustments. So lets define adjustments by "days" for the base datetime object in terms of 86400.0 seconds. A DST aware datetime subclass can then be made that does the more complex day-based arithmetic.
Yes. A "day" is always 24 hours. --Guido van Rossum (home page: http://www.python.org/~guido/)
[Kevin Jacobs]
.. The concept of a "day" can be somewhat ambiguous. I've seen datetime implementations that will apply DST changes when asked to adjust by days, but not when asked to adjust by seconds, hours or minutes.
[Guido]
Yes. A "day" is always 24 hours.
In real life, if it's 3pm on the day before DST begins or ends, and I count off 24 hours, "one one thousand, two one thousand, three one thousand, ... eighty six thousand four hundred one thousand", I'm going to look up and see 2pm or 4pm on my high-tech auto-adjusting clocks. If I add 24 hours to my datetime object, though, I'm going to see 3pm. The only conclusion I have at this time is that I like datetime objects better than real life <wink>.
[Guido]
Yes. A "day" is always 24 hours.
[Tim]
In real life, if it's 3pm on the day before DST begins or ends, and I count off 24 hours, "one one thousand, two one thousand, three one thousand, ... eighty six thousand four hundred one thousand", I'm going to look up and see 2pm or 4pm on my high-tech auto-adjusting clocks. If I add 24 hours to my datetime object, though, I'm going to see 3pm.
The only conclusion I have at this time is that I like datetime objects better than real life <wink>.
Depends on how you look. If you look at the hour attribute, or call the isoformat() method, or use str(), you'll see 3pm. If you ask the ctime() or timetuple() methods, it converts to local time, and you'll see 2pm or 4pm! This deserves a caution: what starts off as a time in the local timezone, may end up not being the local time zone when time is added going across a DST transition. Certain methods always convert to local time; others don't. This can be confusing. How can we fix this? Maybe we need yet another datetime type that measures "wall clock time"??? Gosh, time computations are full of surprises, even of you disregard the Julian calendar and leap seconds. :-( --Guido van Rossum (home page: http://www.python.org/~guido/)
[Guido]
Depends on how you look. If you look at the hour attribute, or call the isoformat() method, or use str(), you'll see 3pm. If you ask the ctime() or timetuple() methods, it converts to local time, and you'll see 2pm or 4pm!
I confess I never understood C's baroque timezone and DST gimmicks. I think I can understand the words, but they always surprised me when I tried to use them.
from datetime import datetime x = datetime(2000, 1, 1, tzoffset=60*12) print x 2000-01-01 00:00:00.000000+12:00
That's cool. So is this:
print x.utcctime() Fri Dec 31 12:00:00 1999
The next two had me scratching my head for an hour <-0500 wink>:
print x.ctime() Fri Dec 31 07:00:00 1999 print x.timetuple() (1999, 12, 31, 7, 0, 0, 4, 365, 0)
I'm not sure the base datetime class should be in the timezone or DST businesses at all, because there are sooooo many ways people might want to see them done. If we are in that business, though, I think I'd rather cut the number of distinct methods, and have e.g. all-purpose .ctime(arg) and .timetuple(arg) etc methods, where arg specifies whether you want to get back the time exactly as stored, converted to UTC, or converted to local time. Maybe that should even be a general tzoffset-in-minute argument, which special values outside of -1439..1439 predefined via symbolic name to mean "as stored, UTC, or local". Then 0 would be synonymous with "as stored", I guess. The natural meaning of the sign bit escapes me ...
This deserves a caution: what starts off as a time in the local timezone, may end up not being the local time zone when time is added going across a DST transition. Certain methods always convert to local time; others don't. This can be confusing. How can we fix this? Maybe we need yet another datetime type that measures "wall clock time"???
If anything, the current prototype is trying to do too much, although it's a mere fraction of what people will want.
Gosh, time computations are full of surprises, even of you disregard the Julian calendar and leap seconds. :-(
I'll lend you "Calendrical Calculations". Even *skimming* the chapters on some of the world's other calendrical delights makes our date gimmicks blind via the intensity of their clarity <blink>.
I confess I never understood C's baroque timezone and DST gimmicks. I think I can understand the words, but they always surprised me when I tried to use them.
Yesterday I finally realized what the tm_isdst flag is really for. It's so that you can represent any UTC timepoint as local time, without ambiguity. The only time when the DST flag is needed is in the one hour per year where DST and non-DST overlap: the first hour after the clock is set back an hour (at the end of the summer).
I'm not sure the base datetime class should be in the timezone or DST businesses at all, because there are sooooo many ways people might want to see them done. If we are in that business, though, I think I'd rather cut the number of distinct methods, and have e.g. all-purpose .ctime(arg) and .timetuple(arg) etc methods, where arg specifies whether you want to get back the time exactly as stored, converted to UTC, or converted to local time. Maybe that should even be a general tzoffset-in-minute argument, which special values outside of -1439..1439 predefined via symbolic name to mean "as stored, UTC, or local". Then 0 would be synonymous with "as stored", I guess. The natural meaning of the sign bit escapes me ...
...Or something like that. I'm beginning to agree that our treatment of timezones is not right. See my next message.
If anything, the current prototype is trying to do too much, although it's a mere fraction of what people will want.
:-)
I'll lend you "Calendrical Calculations". Even *skimming* the chapters on some of the world's other calendrical delights makes our date gimmicks blind via the intensity of their clarity <blink>.
No thanks. I'd rather reimplement HTTP 1.1 from scratch... --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
[Guido]
Yes. A "day" is always 24 hours.
[Tim]
In real life, if it's 3pm on the day before DST begins or ends, and I count off 24 hours, "one one thousand, two one thousand, three one thousand, ... eighty six thousand four hundred one thousand", I'm going to look up and see 2pm or 4pm on my high-tech auto-adjusting clocks. If I add 24 hours to my datetime object, though, I'm going to see 3pm.
The only conclusion I have at this time is that I like datetime objects better than real life <wink>.
Depends on how you look. If you look at the hour attribute, or call the isoformat() method, or use str(), you'll see 3pm. If you ask the ctime() or timetuple() methods, it converts to local time, and you'll see 2pm or 4pm!
You should forget about DST if you want a sane implementation. Same for leap seconds.
This deserves a caution: what starts off as a time in the local timezone, may end up not being the local time zone when time is added going across a DST transition. Certain methods always convert to local time; others don't. This can be confusing. How can we fix this? Maybe we need yet another datetime type that measures "wall clock time"???
You should be very careful not to make all of this too confusing by trying to put everything into one bag. If someone wants DST and timezone aware time differences, then this is a completely different concept than taking the difference w/r to number of days. Just to hint at another problem: you sometimes want to know the time difference of two dates in terms of years, months, days, hours, etc. that is, you are not interested in 86400 second days, but in calendar days or even months. For months you'll run into problems with non-existing days, e.g. for 2002-03-31 - 1 month.
Gosh, time computations are full of surprises, even of you disregard the Julian calendar and leap seconds. :-(
Hehe, I had the same impression when I started with mxDateTime. At first, it seemed like a simple write up, but once I got into the details, things started to become very confusing. In my implementation, I decided to use mathematical model for the representation and to leave most of the complex stuff to interface methods. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/
On Tue, 5 Mar 2002, M.-A. Lemburg wrote:
The only conclusion I have at this time is that I like datetime objects better than real life <wink>. [Guido] Depends on how you look. If you look at the hour attribute, or call
[Tim] the isoformat() method, or use str(), you'll see 3pm. If you ask the ctime() or timetuple() methods, it converts to local time, and you'll see 2pm or 4pm! [MAL] You should forget about DST if you want a sane implementation. Same for leap seconds.
My datetime objects manage these complexities by layering their implementation. Our base class stores a time since epoch and a timezone offset. It implements all the arithmetic functions based on 1day=24hours and has methods that re-normalize the timezone to a fixed offset after every modifying operation. It also has a translate(tzoffset) function that returns the an adjusted time since epoch with a different timezone offset. This way, our client applications _never_ deal with DST or timezone changes unless they request it. For calculations that require DST awareness, of which there are a surprising number, we have a datetime sub-class that adds two extra modes: 1) Fixed tzoffset (from base datetime) 2) Fixed tzoffset +/- fixed DST adjustment based on current time since epoch (folds in to case 1 after initialization) 3) Fixed tzoffset +/- dynamic DST based on stored time since epoch (dynamically updates after every mutating date operation)
If someone wants DST and timezone aware time differences, then this is a completely different concept than taking the difference w/r to number of days.
Precisely. Our implementation is sub-optimal in that it can do roughly twice as much work as necessary at times. This is because we layer the DST adjustments on top of the datetime object. The advantage to this approach is that the code is very cleanly segregated between DST agnostic code and DST pathological code.
Just to hint at another problem: you sometimes want to know the time difference of two dates in terms of years, months, days, hours, etc. that is, you are not interested in 86400 second days, but in calendar days or even months. For months you'll run into problems with non-existing days, e.g. for 2002-03-31 - 1 month.
We handle these cases with a business logic layer on top of the DST aware datetime object. It handles exceptions thrown, like BeyondEndOfMonthError, and takes the appropriate action. In the case of BeyondEndOfMonthError, the typical resolution is to set the day to the last day of the month. -Kevin -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com
[MAL] You should forget about DST if you want a sane implementation. Same for leap seconds.
[Kevin Jacobs]
My datetime objects manage these complexities by layering their implementation. Our base class stores a time since epoch and a timezone offset. It implements all the arithmetic functions based on 1day=24hours and has methods that re-normalize the timezone to a fixed offset after every modifying operation. It also has a translate(tzoffset) function that returns the an adjusted time since epoch with a different timezone offset. This way, our client applications _never_ deal with DST or timezone changes unless they request it.
You can try to hide from DST, but you can't run. It always shows its ugly head when you lift the next stone, just as you least expected it. I'm thinking of a layered implementation myself, and I think some big changes to the datetime.py prototype will be necessary. I'm thinking that for most *business* uses of date and time, we should have the same attitude towards DST that we've already decided to take towards leap seconds. If I move an appointment that's scheduled for 12 noon today and move it a week ahead, it should still show up at 12 noon, even if the DST changes in between. I think I want to introduce a new concept, closely related to local time, that I'll dub "naive time" for now. In naive time, there is no timezone and there is no DST. To compensate for DST, you have to manually change the clock, which is an action outside the system, unknown to the system, and irrelevant to the working of the system. Ditto to change time zones. Naive time is what you see on your watch or your Palm organizer (apparently not on PocketPC or Windows/CE though, which are timezone aware). A day is always 24 hours, and the clock always shows local time. When the DST jump happens, you lose or win an hour but you do your best to pretend it didn't happen, by going to bed a little earlier or by partying a little longer (or any other activity that causes memory loss :-). My Palm has no problem keeping track of appointments in different timezones: when I have a meeting in San Francisco at 11am, I enter it at 11am, and when I fly there, I move the Palm's clock three hours back. Naive time adapts to local time -- time flies (or stands still) when you're in an airplane crossing timezones. Naive time calculations are easier than local time calculations, because they don't have to worry about DST. You only have to be careful when converting between naive time and UTC (or anything else that has a concept of timezone). Which brings us to...
For calculations that require DST awareness, of which there are a surprising number, we have a datetime sub-class that adds two extra modes:
1) Fixed tzoffset (from base datetime)
2) Fixed tzoffset +/- fixed DST adjustment based on current time since epoch (folds in to case 1 after initialization)
3) Fixed tzoffset +/- dynamic DST based on stored time since epoch (dynamically updates after every mutating date operation)
I'm not sure exactly what these mean yet, but by the time I've implemented the new regime in datetime.py, I expect I will. :-) I'm very tempted to put all the smarts in conversions though: you can take a naive datetime object, interpret it in a particular timezone using a given DST ruleset (local time and UTC being two common cases) and convert it to a timestamp, which has different semantics, but can be converted back to naive time by interpreting according to some timezone.
If someone wants DST and timezone aware time differences, then this is a completely different concept than taking the difference w/r to number of days.
Precisely. Our implementation is sub-optimal in that it can do roughly twice as much work as necessary at times. This is because we layer the DST adjustments on top of the datetime object. The advantage to this approach is that the code is very cleanly segregated between DST agnostic code and DST pathological code.
And that's what I want too.
Just to hint at another problem: you sometimes want to know the time difference of two dates in terms of years, months, days, hours, etc. that is, you are not interested in 86400 second days, but in calendar days or even months. For months you'll run into problems with non-existing days, e.g. for 2002-03-31 - 1 month.
We handle these cases with a business logic layer on top of the DST aware datetime object. It handles exceptions thrown, like BeyondEndOfMonthError, and takes the appropriate action. In the case of BeyondEndOfMonthError, the typical resolution is to set the day to the last day of the month.
Good idea. This can probably be remain implemented in Python. --Guido van Rossum (home page: http://www.python.org/~guido/)
On Tue, 5 Mar 2002, Guido van Rossum wrote: (---)
I think I want to introduce a new concept, closely related to local time, that I'll dub "naive time" for now. In naive time, there is no timezone and there is no DST. To compensate for DST, you have to manually change the clock, which is an action outside the system, unknown to the system, and irrelevant to the working of the system. Ditto to change time zones.
Naive time is what you see on your watch or your Palm organizer (apparently not on PocketPC or Windows/CE though, which are timezone aware). A day is always 24 hours, and the clock always shows local time. When the DST jump happens, you lose or win an hour but you do your best to pretend it didn't happen, by going to bed a little earlier or by partying a little longer (or any other activity that causes memory loss :-).
(---)
My Palm has no problem keeping track of appointments in different timezones: when I have a meeting in San Francisco at 11am, I enter it at 11am, and when I fly there, I move the Palm's clock three hours back. Naive time adapts to local time -- time flies (or stands still) when you're in an airplane crossing timezones.
Naive time calculations are easier than local time calculations, because they don't have to worry about DST. You only have to be careful when converting between naive time and UTC (or anything else that has a concept of timezone).
(---)
I'm very tempted to put all the smarts in conversions though: you can take a naive datetime object, interpret it in a particular timezone using a given DST ruleset (local time and UTC being two common cases) and convert it to a timestamp, which has different semantics, but can be converted back to naive time by interpreting according to some timezone.
(---) Am I misunderstanding something, or is your "naive time" simply local time without the knowledge of DST or time zone ? If so, you have an excellent solution that works 99.97% of the time. Unfortunately, once you have removed the one bit of DST information, it's not always possible to get it back, without knowing _which_ 2:30 Sunday morning... /Paul
Am I misunderstanding something, or is your "naive time" simply local time without the knowledge of DST or time zone ?
Exactly.
If so, you have an excellent solution that works 99.97% of the time. Unfortunately, once you have removed the one bit of DST information, it's not always possible to get it back, without knowing _which_ 2:30 Sunday morning...
Exactly. And I don't care. In fact, I would go further, and claim that not caring about this is the whole point. If you had cared about this, you would have saved UTC timestamps. --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
[MAL] You should forget about DST if you want a sane implementation. Same for leap seconds.
I think I want to introduce a new concept, closely related to local time, that I'll dub "naive time" for now. In naive time, there is no timezone and there is no DST. To compensate for DST, you have to manually change the clock, which is an action outside the system, unknown to the system, and irrelevant to the working of the system. Ditto to change time zones.
Naive time is what you see on your watch or your Palm organizer (apparently not on PocketPC or Windows/CE though, which are timezone aware). A day is always 24 hours, and the clock always shows local time. When the DST jump happens, you lose or win an hour but you do your best to pretend it didn't happen, by going to bed a little earlier or by partying a little longer (or any other activity that causes memory loss :-).
My Palm has no problem keeping track of appointments in different timezones: when I have a meeting in San Francisco at 11am, I enter it at 11am, and when I fly there, I move the Palm's clock three hours back. Naive time adapts to local time -- time flies (or stands still) when you're in an airplane crossing timezones.
Naive time calculations are easier than local time calculations, because they don't have to worry about DST. You only have to be careful when converting between naive time and UTC (or anything else that has a concept of timezone).
Just to let you know: you are slowly narrowing in on mxDateTime ;-) (the naive type is pretty much what I have implemented as DateTime object). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/
[Guido, on "naive time"]
... Naive time calculations are easier than local time calculations, because they don't have to worry about DST. You only have to be careful when converting between naive time and UTC (or anything else that has a concept of timezone).
[MAL]
Just to let you know: you are slowly narrowing in on mxDateTime ;-) (the naive type is pretty much what I have implemented as DateTime object).
It's not *that* slowly -- this started less than a week ago <wink>. But, yes, Guido's basic class is heading more in the direction of what mxDateTime started as. By the time you had need of documenting things like Adding/Subtracting DateTime instances causes the result to inherit the calendar of the left operand. I think "naive time" got lost in the options. Guido has in mind a pure "proleptic Gregorian" gimmick. We'll see how long that lasts ...
Tim Peters wrote:
[Guido, on "naive time"]
... Naive time calculations are easier than local time calculations, because they don't have to worry about DST. You only have to be careful when converting between naive time and UTC (or anything else that has a concept of timezone).
[MAL]
Just to let you know: you are slowly narrowing in on mxDateTime ;-) (the naive type is pretty much what I have implemented as DateTime object).
It's not *that* slowly -- this started less than a week ago <wink>. But, yes, Guido's basic class is heading more in the direction of what mxDateTime started as. By the time you had need of documenting things like
Adding/Subtracting DateTime instances causes the result to inherit the calendar of the left operand.
I think "naive time" got lost in the options. Guido has in mind a pure "proleptic Gregorian" gimmick. We'll see how long that lasts ...
mxDateTime was purely Gregorian until I realized that all historic dates are in fact referenced using the Julian calendar. Note that mxDateTime doesn't try to be clever about the switch from one to the other: it simply provides both versions via methods or constructors. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/
On dinsdag, maart 5, 2002, at 08:25 , Guido van Rossum wrote:
I think I want to introduce a new concept, closely related to local time, that I'll dub "naive time" for now. In naive time, there is no timezone and there is no DST. To compensate for DST, you have to manually change the clock, which is an action outside the system, unknown to the system, and irrelevant to the working of the system. Ditto to change time zones.
This sounds like an absolutely brilliant idea! And I think that
if you keep the equivalent of the tm_isdst bit you can get all
the conversions working too. And it fits the model: I have a
naive tm_isdst bit in my head on that one night per year (if it
hasn't been lost in partying yet:-).
Hmm, and possibly you want a function discontinuity(t1, t2) that
will return 0 normally but something else (a value in seconds?
Then it could even be used for leap seconds by the real
die-hards) if there's a time discontinuity between t1 and t2.
--
- Jack Jansen
Guido van Rossum wrote:
Naive time is what you see on your watch or your Palm organizer (apparently not on PocketPC or Windows/CE though, which are timezone aware). A day is always 24 hours, and the clock always shows local time. When the DST jump happens, you lose or win an hour but you do your best to pretend it didn't happen, by going to bed a little earlier or by partying a little longer (or any other activity that causes memory loss :-).
My Palm has no problem keeping track of appointments in different timezones: when I have a meeting in San Francisco at 11am, I enter it at 11am, and when I fly there, I move the Palm's clock three hours back. Naive time adapts to local time -- time flies (or stands still) when you're in an airplane crossing timezones.
+1 After reading comp.risks for years, I've seen enough bug reports about Outlook getting this wrong. The main reason this works, though, is that it still almost always takes more than an hour to cross a timezone. ;-) -- --- Aahz (@pobox.com) Hugs and backrubs -- I break Rule 6 <*> http://www.rahul.net/aahz/ Androgynous poly kinky vanilla queer het Pythonista We must not let the evil of a few trample the freedoms of the many.
Guido van Rossum wrote:
Maybe we need yet another datetime type that measures "wall clock time"???
Gosh, time computations are full of surprises, even of you disregard the Julian calendar and leap seconds. :-(
It's good to hear you say that. Your opinion earlier -- which I wanted to agree with, but couldn't see how -- seemed to be "This is so *EASY*, why can't anybody just get it done the way I want??!" :) Elsewhere, Guido van Rossum wrote:
I'm very tempted to put all the smarts in conversions though: you can take a naive datetime object, interpret it in a particular timezone using a given DST ruleset (local time and UTC being two common cases) and convert it to a timestamp, which has different semantics, but can be converted back to naive time by interpreting according to some timezone.
Okay: Dumb objects, smart conversions. I like this a lot. If the conversions are even minimally flexible, better timezone support can be added later. Maybe even calendars. timestamp <---timezone/calendar-aware conversion---> datetime (no TZ or DST) (broken-down; with TZ; maybe not DST) Casual users would only ever see (or care about) the datetime type and its year/month/day/etc. fields. By default, the broken-down time is determined using localtime(). Sometimes timestamps are appropriate, sometimes datetimes. They serve different programming goals. Both are small in terms of storage; each supports a different sort of arithmetic. Both have fast __cmp__ operations. For simplicity, the timestamp type could just be "float" (the type returned by time.time()). Or it could be something nicer that has (naively) broken-down fields of its own. I've got pseudocode if anyone is interested. :| ## Jason Orendorff http://www.jorendorff.com/
Guido van Rossum wrote:
Gosh, time computations are full of surprises, even of you disregard the Julian calendar and leap seconds. :-(
There was a quote about God creating time in order to confuse man that I can't find it now. I did find this link: http://www.naggum.no/lugm-time.html I looks like Erik put a lot of work into it. Neil
On Mon, 4 Mar 2002, Kevin Jacobs wrote:
The concept of a "day" can be somewhat ambiguous. I've seen datetime implementations that will apply DST changes when asked to adjust by days, but not when asked to adjust by seconds, hours or minutes. So, in the general case of a DST aware datetime object,
t + Delta(days=1) != t + Delta(hours=24)
even when ignoring leap-seconds and other micro-adjustments. So lets define adjustments by "days" for the base datetime object in terms of 86400.0 seconds. A DST aware datetime subclass can then be made that does the more complex day-based arithmetic.
Or, someone implementing datetime as (julian: integer, seconds: float) might prefer to let adjustment by "days" be in terms of 1 day. A DST aware datetime subclass can then be made that does the more complex time-based arithmetic. /Paul
Guido van Rossum wrote:
Hope you don't mind ;-) ...
Not at all, we're hoping to arrive at something usable and fun for all!
You should name the type timestamp if you want to imply dt + n == dt + n seconds. datetime + n is commonly understood as dt + n *days*.
Hm, I hadn't thought of that. To me seconds are the only thing that makes sense because that's what a Unix timestamp does, but I haven't read or written a lot of commercial code using date/time data.
Is this just an mxDateTime convention, or is it in wider use? (URLs of docs of other languages / libraries would really help to convince me!)
I'm not sure how wide-spread this convention is, but the mxDateTime users pushed me to it, so there must be some general understanding in that direction out there ;-) In mxDateTime I use the following conventions: DateTime + n: add n days (each having 86400.0 seconds, so fractions are possible too) DateTimeDelta + n: add n seconds It is of course prevered to write: DateTime(...) + DateTimeDelta(...) or DateTime(...) + RelativeDateTime(...) since this is more exlicit. There are also a few constants to make this even easier: DateTime(...) + 10 * oneSecond - 20 * oneMinute -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/
Discussion over. I've removed the ability to add plain numbers to datetime and timedelta objects. I'll add the ability to create a timedelta from a floating point number of days, seconds or microseconds though. --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (11)
-
aahz@rahul.net
-
barry@zope.com
-
Guido van Rossum
-
Jack Jansen
-
Jason Orendorff
-
Kevin Jacobs
-
M.-A. Lemburg
-
Neal Norwitz
-
Neil Schemenauer
-
Paul Svensson
-
Tim Peters