From chris.barker at noaa.gov Tue Jul 28 22:55:02 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Tue, 28 Jul 2015 13:55:02 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... Message-ID: Moved from python-dev to the datetime SIG TL;DR: There are are two types of operations on datetimes: adding subtracting actual time units (multiples of seconds) and calendar operations: things like "this time the next day". I think the the datetime module should only support the former -- i.e. the same old timedelta we have. In that context, storing datetimes in UTC, doing all operations there, and converting back makes the most sense. But for calendar manipulations, they need to be done in a time-zone aware way. If you're really interested, I got quite carried away below.... On Mon, Jul 27, 2015 at 10:03 PM, Lennart Regebro wrote: > On Tue, Jul 28, 2015 at 12:03 AM, Tim Peters wrote: > > timedelta objects only store days, seconds, and microseconds, > > Except that they don't actually store days. They store 24 hour > periods, which, because of timezones changing, is not the same thing. > yes, it is ;-) And as you have repeated > many times now, the datetime module's arithmetic is "naive" ie, it > assumes that one day is always 24 hours. The problem with that > assumption is that it isn't true. > it's not an assumption, it's a definition. We have a serious semantic problem here -- and I _think_ it's the source of almost all the discussion in this thread -- I'm not sure what to do about it though. Tim understands this stuff, Lennart understands this stuff, I'm pretty sure I understand this stuff -- I'm not sure about everyone else on this discussion, but they probably all understand it, too -- the only thing any of us doesn't understand is what the heck anyone is talking about! Maybe use Tim's approach of "naive" -- so a naive day is exactly 24 hours period end of story -- this is the definition. But what do we call what I've been trying to refer to as "calendar" operations? A summary for (maybe) some clarity: We have this nifty model of a continuous time axis -- moving along at a steady rate from the beginning of the Universe to the end of the Universe. Modulo relativity, it works pretty well. Then we have units of time spans: in SI units it's seconds. then a bunch of other units that are clearly defined in terms of seconds: minutes (60 s) hours (60 min) days (24 hrs). And of course milliseconds and microseconds. Then we have Calendars: this is the year, month, day, etc. we are all familiar with (and the hours in that day 4:00 o'clock pm, etc) -- confusing here is that we use the same word for "day" and "hour" as part of a calendar descriptions AND also as timespan units -- but they are NOT the same thing (yes, they are related). Calendars are how we map a nice human understandable (and historically based) naem onto the theoretically time axis. Being both human-oriented and with a lot of historical baggage, calendar naming is designed to fit more or less with relationship between the earth and the sun. So we want the Solstices to fall around the same date every year, for instance, and we want 1200 hrs to be around the middle of the day. This is why it all gets ugly, because the various celestial phenomena aren't nice integers multiples of each-other (hence the need for leap years) and even constant (hence the need for leap seconds). And, of course, the earth is round, and the sun's relative position to each point on earth is different, hence the need for time zones. (then add political differences for it to get really ugly. So: I think there are more or less two types of manipulations one might need: What is currently supported by the datetime module, and I think Tim is referring to as "naive" time operations: adding, subtracting, units of time along the theoretical time axis. This is actually really simple math -- as Tim points out all the timedelta object really is is a fancy integer. Then there are what I am calling "calendar" operations -- these are operations that only make sense with a calendar (and, in fact a timezone, I think). this is operations like: "the same time two days later" -- this is not the same as moving two days (48 hrs) along the time axis -- it simply is not. It is a shame that we use the name "day" to refer to both 24 hours along the time axis and enumeration of sunrises in a month -- or, the thing we use on calendars. There has been a lot of chatter about "tomorrow" or "adding three days", as these bring up the ugly DST issues, but once you add one calendaring operation, people will want (and they should) more: next month, next year, or even uglier, next business day, etc. These are very useful things, but I argue they belong, as a unit, in a separate package -- maybe for potential inclusion in the standard library, but I don't think that's on the table now. (and doesn't dateutil support many of these?) Now on to time zones: the datetime package is useful because it not only supports time-axis arithmetic (really pretty trivial -- it's just integer arithmetic), but it supports translating from time-axis units (microseconds since some epoch) to Calendar units: year, month, day, hour, minute, seconds, microseconds (Using the (proleptic?) Gregorian Calendar -- note that different Calendars are a whole other ball of wax! This is where the magic is (or really where the ugly code is) , and where tiem zones come in. UTC time is the calendar time at one longitude on the earth. (ignoring leap seconds for the moment) it is relatively simple: continuous, etc, no DST, no changing definitions, etc. It is a useful reference system for this reason. math, and all that, are easier in this zone. By default, Python datetime objects are "naive" -- meaning they know nothing of timezones or daylight savings -- they can convert back and forth between the internal representation (time span since an epoch) and human calendar times (Gregorian, anyway). It turns out that you can use naive datetimes as UTC time -- there really is no difference, until you want to convert to a different time zone -- with UTC, you may be able to do that, with naive, you can't do that unless you specify what time zone the time is, and then it's no longer naive ;-) But how should pyton handle time zones? Given all the ugliness of DST and changing time zones, and all that, UTC is the lingua franca of time -- time zones are defined by how the are offset from UTC, and in UTC (as in naive), math is relatively easy. So the best way to handle time zones is to store and manipulate everything in UTC, and then convert to/from the calendar representation using the time zone, when the user needs (or provides). I've been trying to figure out what all the confusion, discussion has been about, and I think it's this: If you want to do a Calendar operation, like "this time tomorrow", then THAT is best done in a timezone aware way -- in particular, a DST-aware way. i.e. from 12:00 one day to 12:00 the next day will generally be 24 hours, but might be 23 or 25 hours if crossing a DST transition. But if we aren't supporting those operations, we don't need to worry about that now. -Chris > _______________________________________________ > Python-Dev mailing list > Python-Dev at python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/chris.barker%40noaa.gov > -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Tue Jul 28 22:58:15 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Tue, 28 Jul 2015 13:58:15 -0700 Subject: [Datetime-SIG] What's are the issues? Message-ID: Hi folks, Now that we have a datetime list, maybe it's time to rre-center ourselves. I know I got all caught up in the semantics an details, but I just now gave the PEP another read-through, and, well, it looks good to me. What are the issues still to be resolved? -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From felipe.nospam.ochoa at gmail.com Tue Jul 28 23:38:36 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Tue, 28 Jul 2015 16:38:36 -0500 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: Here is my best shot at categorizing the different outstanding design issues: 1. Datetime arithmetic a) datetime +/- timedelta i. Naive (no tzinfo) datetime objects ii. Aware (with tzinfo) datetime objects b) datetime - datetime i. When both are naive ii. When both have same tzinfo iii. When the two have different tzinfos 2. Inter-timezone conversion a) adding an isdst (or which) attribute b) algorithm specification I think 1ai, 2bi, and 1biii are uncontroversial at this point, and 2a we have consensus on the need but not the name On 28 July 2015 at 15:58, Chris Barker wrote: > Hi folks, > > Now that we have a datetime list, maybe it's time to rre-center ourselves. > > I know I got all caught up in the semantics an details, but I just now > gave the PEP another read-through, and, well, it looks good to me. > > What are the issues still to be resolved? > > -Chris > > > > -- > > Christopher Barker, Ph.D. > Oceanographer > > Emergency Response Division > NOAA/NOS/OR&R (206) 526-6959 voice > 7600 Sand Point Way NE (206) 526-6329 fax > Seattle, WA 98115 (206) 526-6317 main reception > > Chris.Barker at noaa.gov > > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Wed Jul 29 00:54:38 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Tue, 28 Jul 2015 15:54:38 -0700 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: On Tue, Jul 28, 2015 at 2:38 PM, Felipe Ochoa wrote: > Here is my best shot at categorizing the different outstanding design > issues: > great, thanks! My thoughts: (some obvious) NOTE: I'm assuming that timedelta is the same as it is now -- i.e. "naive", or simply representing a timespan nothing t do with calendars. 1. Datetime arithmetic > a) datetime +/- timedelta > i. Naive (no tzinfo) datetime objects > same as now > ii. Aware (with tzinfo) datetime objects > If the math is done in UTC, then there is no issue, yes? the timedelta is added or subtracted, and the result has the same tzinfo object. > b) datetime - datetime > i. When both are naive > same as now. > ii. When both have same tzinfo > Just do the math. Store as UTC makes it easy. return a timedelta. > iii. When the two have different tzinfos > Do the math in UTC, return a timedelta. > 2. Inter-timezone conversion > a) adding an isdst (or which) attribute > yup -- and I've bike-shedeed enough without getting into what to call it! > b) algorithm specification > what part of the algorithm? seems pretty straightforward to me (the algorithm, anyway) So really a lot of bike-shedding on pyton-dev ;-) -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From ethan at stoneleaf.us Wed Jul 29 01:03:39 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Tue, 28 Jul 2015 16:03:39 -0700 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: <55B80A4B.7010304@stoneleaf.us> On 07/28/2015 01:58 PM, Chris Barker wrote: > Now that we have a datetime list, maybe it's time to re-center ourselves. > > I know I got all caught up in the semantics and details, but I just now gave the PEP another read-through, and, well, it looks good to me. > > What are the issues still to be resolved? I think the biggest issue is that Lennart was trying to change the way datetimes work, which a. would be a compatibility break b. is not clear from the PEP I think a lot of confusion comes from the necessity of using timedeltas as a time measurement device, even when we aren't really using them that way -- meaning when we add a timedelta of 7 days to go from Jun 27 09:00 to Jul 4 09:00 we (usually) don't care if that is exactly 7 * 24 hours later. I think the ideal solution would be to have tz-aware datetimes able to switch their timezone as needed, but that would also be a backwards-compatibility break -- not to mention the need to be able to specify whether one wants the "calendar" operation (7am is still 7am) or the actual duration operation (7am may be 6am or 8am if a clock change occurs). On the gripping hand we already have the calendar semantics, so perhaps just a whole new type of datetime would be best? -- ~Ethan~ From alexander.belopolsky at gmail.com Wed Jul 29 02:03:01 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Tue, 28 Jul 2015 20:03:01 -0400 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: On Tue, Jul 28, 2015 at 5:38 PM, Felipe Ochoa wrote: > > Here is my best shot at categorizing the different outstanding design issues: > I would like to make sure that everyone is aware that we are not designing in a vacuum. Unlike Python 2, Python 3 already has a decent amount of timezone support. In fact, with some small exceptions, I believe Python 3 datetime has a fairly complete support for UTC and system local timezones. For the items below, I will try to briefly describe the status quo > 1. Datetime arithmetic > a) datetime +/- timedelta > i. Naive (no tzinfo) datetime objects This has been supported from the very beginning: >>> t = datetime.now() >>> t datetime.datetime(2015, 7, 28, 19, 18, 59, 699588) >>> t + timedelta(1) datetime.datetime(2015, 7, 29, 19, 18, 59, 699588) (no surprises here) > ii. Aware (with tzinfo) datetime objects This works fine with the builtin timezone instances: >>> t = datetime(2014,11,1,16,tzinfo=timezone.utc).astimezone() >>> t.strftime("%c %Z %z") 'Sat Nov 1 12:00:00 2014 EDT -0400' >>> u = t + timedelta(1) >>> u.strftime("%c %Z %z") 'Sun Nov 2 12:00:00 2014 EDT -0400' This may be a little surprising to those expecting to see DST to end, but the legal time is one method call away: >>> u.astimezone().strftime("%c %Z %z") 'Sun Nov 2 11:00:00 2014 EST -0500' > b) datetime - datetime > i. When both are naive (Trust me: this part works!) > ii. When both have same tzinfo >>> u - t datetime.timedelta(1) (Works.) > iii. When the two have different tzinfos >>> u - datetime(2014,11,1,16,tzinfo=timezone.utc) datetime.timedelta(1) (Works as well.) > 2. Inter-timezone conversion UTC to local just works. Local to UTC "kind of" works: >>> t = datetime.now() >>> u = datetime.fromtimestamp(t.timestamp(), timezone.utc) >>> u.strftime("%c %Z") 'Tue Jul 28 23:40:38 2015 UTC+00:00' > a) adding an isdst (or which) attribute > b) algorithm specification > > I think 1ai, 2bi, and 1biii are uncontroversial at this point, and 2a we have consensus on the need but not the name > From felipe.nospam.ochoa at gmail.com Wed Jul 29 02:06:44 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Tue, 28 Jul 2015 20:06:44 -0400 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: In the interest of continuing to lay the foundation for discussion, let me build on Chris's recap before giving my viewpoint on the issue: 1. Datetime arithmetic >> a) datetime +/- timedelta >> ii. Aware (with tzinfo) datetime objects > > If the math is done in UTC, then there is no issue, yes? the timedelta is > added or subtracted, and the result has the same tzinfo object. If I've understood correctly, this is one of the bigger points of contention. Specifically, the following operation is quite polarizing: `datetime(2015, 3, 7, 13, 0, tzinfo=zoneinfo('America/New_York') ) + timedelta(days=1)` It raises the following two questions: * Should `days=1` be interpreted the same as `hours=24`? * If it is interpreted the same, should the addition be "naive" (not adjusting for the jump from 1:59 to 3:00) or "aware" Current semantics call for the answers to be "yes" and "naive" > b) datetime - datetime > > ii. When both have same tzinfo > > Just do the math. Store as UTC makes it easy. return a timedelta. This is another contentious issue. What do you want `datetime(2015, 3, 8, 13, tzinfo=zoneinfo('America/New_York')) - datetime(2015, 3, 7, 13, tzinfo=zoneinfo('America/New_York'))` to be? There's a camp for `timedelta(seconds=24 * 60 * 60)` and a camp for `timedelta(seconds=23 * 60 * 60)`, though I think everyone agrees that `(dt + delta) - dt == delta` is necessary. 2. Inter-timezone conversion > > b) algorithm specification > > what part of the algorithm? seems pretty straightforward to me (the > algorithm, anyway) I'm less clear on the issue here, but Isaac seemed to disagree with the algorithm in datetime.py ( https://hg.python.org/cpython/file/v3.5.0b1/Lib/datetime.py#l1935) [ http://code.activestate.com/lists/python-dev/137300/] -------------- next part -------------- An HTML attachment was scrubbed... URL: From felipe.nospam.ochoa at gmail.com Wed Jul 29 02:15:04 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Tue, 28 Jul 2015 20:15:04 -0400 Subject: [Datetime-SIG] Datetime arithmetic proposal Message-ID: My viewpoint (specifically on point 1 from my other email): 1. We cannot break backwards-compatibility (This point has been beaten to death) 2. There are valid use-cases for wanting datetimes with and without timezone info, and for doing naive and aware math. All 3 legal combinations of the two (excluding naive dt with aware deltas :-)) have valid use-cases 3. [new point] If I'm a new user looking in the library for a solution to my problem, my use-case is likely to appear "obviously correct", and I'll be shocked if Python doesn't support it 4. [new point] The non-trivial nature of all 3 possibilities makes it advantageous to include in the standard library With that said, my proposal would be to: A. Keep the current mechanics as-is. `+` and `-` result in "naive" datetime arithmetic B. Implement `.get_offset_time(self, hours, minutes, seconds, ms)` and `.compute_duration(self, other_dt)` methods for "aware arithmetic." (I.e., congruent to 'convert to UTC, increment, convert back') C. Come up with a new name (or clearly define naive/aware arithmetic) to disambiguate the two D. Document these differences clearly Downsides: * clunkyness of doing aware arithmetic * `aware_dt + delta` can result in a nonexistent or ambiguous time * `aware_dt_1 - aware_dt_2` behaves differently depending on the underlying timezones * [ fill in the blank -- I'm sure I'm missing many more ] -Felipe -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim.peters at gmail.com Wed Jul 29 03:09:23 2015 From: tim.peters at gmail.com (Tim Peters) Date: Tue, 28 Jul 2015 20:09:23 -0500 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: [Felipe Ochoa ] > ... > I'm less clear on the issue here, but Isaac seemed to disagree with the > algorithm in datetime.py > (https://hg.python.org/cpython/file/v3.5.0b1/Lib/datetime.py#l1935) > [http://code.activestate.com/lists/python-dev/137300/] The algorithm is fine, so far as it goes (with which Isaac will agree). "So how far does it go?" ;-) It handles DST transitions correctly in all known timezones(*). But, as the docs have always pointed out, it (specifically .fromutc(), which is at the base of all relevant calculations) doesn't even try to handle transitions due to _other_ causes. The only other such cause I'm aware of is when a timezone's _base_ offset from UTC changes (not a temporary DST transition, the timezone's "standard" offset changes permanently (meaning until someone decides to change it again)). Many timezones have suffered such a fundamental redefinition at least once. There is no pattern whatsoever to when such things occur - seems it's driven purely by local politics. And for any given timezone it typically happens at most once across its lifetime to date. However, while rare, such changes do still happen, and a "wholly correct" implementation needs to cater to them too (meaning a more general .fromutc() implementation needs to be crafted, and the docs updated to match the new scheme). >From there, Isaac went on to define an approach to a more general method, which could obviously handle that kind of thing too. How practical that approach can be made remains unknown, because nobody yet (that I know of) has tried to produce corresponding code. The mathematical abstractions in his writeup appear far more general than actually needed for any timezone yet invented (excepting the absurd "RIyadh Solar" timezone experiment, which was never actually used by anyone in the real world); stronger assumptions could probably allow more efficient implementation. (*) By "timezone" I mean whatever rules a specific tzinfo instance implements. I have a wholly Python-centric view of everything ;-) From chris.barker at noaa.gov Wed Jul 29 03:28:32 2015 From: chris.barker at noaa.gov (Chris Barker - NOAA Federal) Date: Tue, 28 Jul 2015 18:28:32 -0700 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: <-4087362986376999997@unknownmsgid> 1. Datetime arithmetic >> a) datetime +/- timedelta >> ii. Aware (with tzinfo) datetime objects > > If the math is done in UTC, then there is no issue, yes? the timedelta is > added or subtracted, and the result has the same tzinfo object. If I've understood correctly, this is one of the bigger points of contention. Specifically, the following operation is quite polarizing: `datetime(2015, 3, 7, 13, 0, tzinfo=zoneinfo('America/New_York') ) + timedelta(days=1)` It raises the following two questions: * Should `days=1` be interpreted the same as `hours=24`? Yes, absolutely! * If it is interpreted the same, should the addition be "naive" (not adjusting for the jump from 1:59 to 3:00) or "aware" If it is 24 hours, then there's no question. So the question really is: should the datetime module provide what I've been calling "calendar operations" ? Yes, that would be very useful, but it's a heck of a lot more complicated than just redefine what a timedelta(days=1) means. And particularly with backward compatibility in mind, it definitely should not be done with that API. If people really are THAT prone to confusion that a day means 24 hours, then we should consider deprecating "days" as a valid unit for a timedelta. Current semantics call for the answers to be "yes" and "naive" Here are the semantics again -- there is nothing naive about subtracting and adding 24 hours. The problem here is that people are conflating a "day" meaning 24 hours and a "day" meaning a numbered entity on a calendar. The two are related, but totally different in meaning. And sorry to get pedantic here, but backwards compatibility aside, I, for one, would be very surprised if a timedelta(days=1) ever meant anything other than 24 hours depending on context! b) datetime - datetime > > ii. When both have same tzinfo > > Just do the math. Store as UTC makes it easy. return a timedelta. This is another contentious issue. What do you want `datetime(2015, 3, 8, 13, tzinfo=zoneinfo('America/New_York')) - datetime(2015, 3, 7, 13, tzinfo=zoneinfo('America/New_York'))` to be? There's a camp for `timedelta(seconds=24 * 60 * 60)` and a Assuming I've got the DST thing right here -- god no! In that time zone, those time stamps are NOT 24 hrs apart! You'd better not mess with that!!!! I'm going to indulge for a minute here: IF there was such a thing as a calendar_delta object of some sort, then you might want one with a value of one day there. But certainly not anything with a value of 24 *3600 seconds! Does anyone really want that? Note that this is s good argument for what calendar operations are so complex. -Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: From rosuav at gmail.com Wed Jul 29 03:43:56 2015 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 29 Jul 2015 11:43:56 +1000 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: <-4087362986376999997@unknownmsgid> References: <-4087362986376999997@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 11:28 AM, Chris Barker - NOAA Federal wrote: > So the question really is: should the datetime module provide what I've been > calling "calendar operations" ? > > Yes, that would be very useful, but it's a heck of a lot more complicated > than just redefine what a timedelta(days=1) means. And particularly with > backward compatibility in mind, it definitely should not be done with that > API. > > If people really are THAT prone to confusion that a day means 24 hours, then > we should consider deprecating "days" as a valid unit for a timedelta. What if the existing timedelta is left as-is, and a new calendardelta type is introduced? Instead of folding everything down to a simple microsecond count, it would retain the exact values it was given, so calendardelta(days=1) != calendardelta(seconds=86400). When you add a calendardelta to an aware datetime, it performs what you're describing as calendar arithmetic, and it will be the most plausibly sane behaviour for the exact unit used; so, for instance, adding calendardelta(days=1) would never affect the hour/minute/second shown, unless it would otherwise create an illegal time. Would that serve? ChrisA From chris.barker at noaa.gov Wed Jul 29 03:54:32 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Tue, 28 Jul 2015 18:54:32 -0700 Subject: [Datetime-SIG] Datetime arithmetic proposal In-Reply-To: References: Message-ID: On Tue, Jul 28, 2015 at 5:15 PM, Felipe Ochoa wrote: > 1. We cannot break backwards-compatibility (This point has been beaten to > death) > OK then -- then timedelta is NOT going to be fundamentally re-denied as something else altogether -- good! > 2. There are valid use-cases for wanting datetimes with and without > timezone info, and for doing naive and aware math. All 3 legal combinations > of the two (excluding naive dt with aware deltas :-)) have valid use-cases > sure -- but the datetime module does not have to support them all, and they don't all have to be supported with the same objects. semantics again -- there is no such thing as naive or aware math -- there are timespan computations and calendar manipulations.... > 3. [new point] If I'm a new user looking in the library for a solution to > my problem, my use-case is likely to appear "obviously correct", and I'll > be shocked if Python doesn't support it > True for all possible libraries :-) -- though I suppose we have a special obligation 'cause we claim that "batteries are included" > 4. [new point] The non-trivial nature of all 3 possibilities makes it > advantageous to include in the standard library > There are a lot of non-trivial, and fairly common things that are not included in the stdlib. But I'm all for including calender manipulations in the stlib -- just not for altering what timedelta means, and trying to be realistic that that's actually a big project, with lots of ugly corner cases and API decisions. And there is nothing about that in the PEP, by the way. As far as I can see, the PEP is about including ready to go, standard tzinfo object in the stdlib -- whereas when dateime was introduced, it provided a mechanism, but no implimentation. This is about providing an implementation. A. Keep the current mechanics as-is. `+` and `-` result in "naive" datetime > arithmetic > *sigh* about the wording, but yes. > B. Implement `.get_offset_time(self, hours, minutes, seconds, ms)` and > `.compute_duration(self, other_dt)` methods for "aware arithmetic." (I.e., > congruent to 'convert to UTC, increment, convert back') > what the heck would that mean? the timedeltas already do that -- what they don't do is calendar maniplutaions -- things like "this same time tomorrow" -- or tomorrow morning at 7:00am. Maybe this will help people conceptualize: timedeltas represent what is measured by a stopwatch. datetimes represent what is represented by a calendar and a watch. If you start your stopwatch at a particular date indicated by your calendar, and particular time indicated by your watch, and run it for 24 hours (one day) you can then look at your calendar and watch and see what the datetime is -- and if you crossed a DST border, it may not be the _same_ time on your watch. And if you start your stopwatch at 2:00pm one day, and look at it again at 2:pm the next day, it will say 24 hours, unless you crossed a DST boundary, in which case it will say 23 or 25 hours -- but would that surprise anyone? > C. Come up with a new name (or clearly define naive/aware arithmetic) to > disambiguate the two > sure -- I'll vote to not use the term "aware arithmetic" -- it's not really arithmetic -- "calendar operations"? and the datetimes can be naive, but the operation is neither naive nor aware -- a time span is a time span is a time span.... Another thought here that may help: you can "encode" a datetime in at least two ways: 1) timespan since an epoch: -- i.e seconds since Jan 1, 1970 00:00. This is how the datetime object keeps it internally. 2) Calendar time in some calendar and time zone: year, month, day, hour, min, sec. The "magic" of the datetime object all happens in the conversion between the two. (side note -- timedeltas have no calendar concept at all) most time math is most easily done in encoding (1) -- that's (one reason) why it's used most of the time. But if you want to do calendar manipluations, you are better off working in the calendar encoding -- "two days from now" is much easier to do there. So I think when people are thinking about "time zone aware math" what they really are thinking about is calendar encoded math. By the way, is anyone proposing to add Calendar manipulations to the stdlib? I understand that folks want that, and apparently some people got confused that better time zone support meant that -- but is anyone proposing to do it? If anyone is, then it's probably a topic for Python-ideas and an entirely different PEP. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Wed Jul 29 04:02:24 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Tue, 28 Jul 2015 19:02:24 -0700 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <-4087362986376999997@unknownmsgid> Message-ID: On Tue, Jul 28, 2015 at 6:43 PM, Chris Angelico wrote: What if the existing timedelta is left as-is, and a new calendardelta > type is introduced? Instead of folding everything down to a simple > microsecond count, it would retain the exact values it was given, sure -- that would be one way to do it -- maybe good way. But it would be a lot more complicated than just keeping days. Lots to hash out for API and functionality at the corner cases (the old what's one year after Feb 29th? kinds of questions) > When you add a > calendardelta to an aware datetime, it performs what you're describing > as calendar arithmetic, actually, no reason you couldn't do calendar manipulations on naive datetimes, too (they wouldn't get any ugly DST issues, but otherwise the same). One reason I don't like calling the arithmetic naive or not.... > adding > calendardelta(days=1) would never affect the hour/minute/second shown, > unless it would otherwise create an illegal time. exactly -- all those corner cases would need to be worked out. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Wed Jul 29 04:04:01 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Tue, 28 Jul 2015 22:04:01 -0400 Subject: [Datetime-SIG] Datetime arithmetic proposal In-Reply-To: References: Message-ID: On Tue, Jul 28, 2015 at 9:54 PM, Chris Barker wrote: > 1) timespan since an epoch: -- i.e seconds since Jan 1, 1970 00:00. This is > how the datetime object keeps it internally. No, it is not. You are probably confusing stdlib datetime with numpy.datetime64. The stdlib datetime keeps broken down year, month, day, hour, minute, second and microsecond values. From chris.barker at noaa.gov Wed Jul 29 04:11:09 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Tue, 28 Jul 2015 19:11:09 -0700 Subject: [Datetime-SIG] Datetime arithmetic proposal In-Reply-To: References: Message-ID: On Tue, Jul 28, 2015 at 7:04 PM, Alexander Belopolsky < alexander.belopolsky at gmail.com> wrote: > On Tue, Jul 28, 2015 at 9:54 PM, Chris Barker > wrote: > > 1) timespan since an epoch: -- i.e seconds since Jan 1, 1970 00:00. This > is > > how the datetime object keeps it internally. > > No, it is not. You are probably confusing stdlib datetime with > numpy.datetime64. > or who knows what else! I've been involved with far toomany datetime conversations lately! > The stdlib datetime keeps broken down year, month, day, hour, minute, > second > and microsecond values. > Thanks for the clarification -- that would make calendar manipulations easier, I suppose. And I can see why anyone would even consider storing in particular time zone format. Sorry to confuse things. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim.peters at gmail.com Wed Jul 29 04:24:17 2015 From: tim.peters at gmail.com (Tim Peters) Date: Tue, 28 Jul 2015 21:24:17 -0500 Subject: [Datetime-SIG] Datetime arithmetic proposal In-Reply-To: References: Message-ID: [Felipe Ochoa] >> ... >> B. Implement `.get_offset_time(self, hours, minutes, seconds, ms)` and >> `.compute_duration(self, other_dt)` methods for "aware arithmetic." (I.e., >> congruent to 'convert to UTC, increment, convert back') [Chris Barker ] > what the heck would that mean? the timedeltas already do that -- what they > don't do is calendar maniplutaions -- things like "this same time tomorrow" > -- or tomorrow morning at 7:00am. We've been through this before, and it's been discussed literally dozens of times on python-dev recently. So I refuse to use any "word salad" to try to describe anything anymore - nobody can hear anything anyone else says ;-) Start with a datetime object representing day 23 in some month and some year, and time 4:56. Add timedelta(hours=24) to that, or add timedelta(days=1) to that, or (there are many other possible spellings of the same thing) and you will ALWAYS get back a timedelta object representing day 24 in the same month, the same year, the same time (4:56), and with the same tzinfo member. It makes no difference which year, no difference which month, and no difference which tzinfo member you started with. You always get back "tomorrow at the same time (as shown on the local clock)". And, yes, the two _may_ be 23 hours apart, or 24 hours, or 25 hours, or even (e.g.,) 23 hours and 15 minutes apart as measured by a stopwatch, depending on the rules implemented by the tzinfo member. The tzinfo member is never consulted about anything in a datetime + timedelta operation. The tzinfo member is ignored (apart from being copied to the result datetime). The arithmetic is done exactly the same as for a naive datetime object. I think you're calling that a "calendar operation". Other people call it "naive datetime arithmetic", some call it "broken", Guido calls it a feature of his "naive time" design, some call it the "a day is always 24 hours rule", and some call it the "s day is not always 24 hours rule". That's why it's impossible to understand anyone without an excruciatingly detailed example ;-) In any case, that's what Python has always done. It won't change, not even in the imaginary "backward compatibility is irrelevant" Python 4 (because Guido still favors this design). That's for the builtin datetime module and its already-existing objects and operations. There's no backward-compatibility constraint on anything new, of course. From alexander.belopolsky at gmail.com Wed Jul 29 04:33:43 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Tue, 28 Jul 2015 22:33:43 -0400 Subject: [Datetime-SIG] Datetime arithmetic proposal In-Reply-To: References: Message-ID: On Tue, Jul 28, 2015 at 10:24 PM, Tim Peters wrote: > [Chris Barker ] >> what the heck would that mean? the timedeltas already do that -- what they >> don't do is calendar maniplutaions -- things like "this same time tomorrow" >> -- or tomorrow morning at 7:00am. > > We've been through this before, and it's been discussed literally > dozens of times on python-dev recently. So I refuse to use any "word > salad" to try to describe anything anymore - nobody can hear anything > anyone else says ;-) Maybe the following session log (ran from the root of the source distribution) will get the message across: >>> with open('Doc/includes/tzinfo-examples.py') as f: ... exec(f.read()) ... >>> t = datetime(2014,11,1,12,tzinfo=Eastern) >>> t.strftime('%c %Z %z') 'Sat Nov 1 12:00:00 2014 EDT -0400' >>> t += timedelta(1) >>> t.strftime('%c %Z %z') 'Sun Nov 2 12:00:00 2014 EST -0500' This is unmodified Python 3.4.3 running an official documentation example. From tim.peters at gmail.com Wed Jul 29 04:45:49 2015 From: tim.peters at gmail.com (Tim Peters) Date: Tue, 28 Jul 2015 21:45:49 -0500 Subject: [Datetime-SIG] Datetime arithmetic proposal In-Reply-To: References: Message-ID: [Chris Barker] >> 1) timespan since an epoch: -- i.e seconds since Jan 1, 1970 00:00. This is >> how the datetime object keeps it internally. [Alexander Belopolsky ] > No, it is not. You are probably confusing stdlib datetime with > numpy.datetime64. > The stdlib datetime keeps broken down year, month, day, hour, minute, second > and microsecond values. It's interesting (well, maybe to someone ;-) ) to note that this division into named attributes is simply for efficiency in extracting commonly accessed values. Conceptually, it's really just storing the integer number of microseconds since the start of "year number 1" of the proleptic Gregorian calendar. All those named fields can be viewed as just representing that integer in a very messy mixed-radix notation. That's not just academic. For example, if you stare at the Python code for the implementation of datetime + timedelta (datetime.__add__), you'll see that it converts the datetime _to_ a timedelta first (which is another way of representing an integer number of microseconds). Of course that conversion has to be done "by hand" since it makes no sense in the user-visible model. But, internally,datetimes, dates, times, and timedeltas are all sometimes viewed as just complicated ways of spelling "some number of microseconds". It's cute ;-) From rosuav at gmail.com Wed Jul 29 05:10:20 2015 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 29 Jul 2015 13:10:20 +1000 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <-4087362986376999997@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 12:02 PM, Chris Barker wrote: > On Tue, Jul 28, 2015 at 6:43 PM, Chris Angelico wrote: > >> What if the existing timedelta is left as-is, and a new calendardelta >> type is introduced? Instead of folding everything down to a simple >> microsecond count, it would retain the exact values it was given, > > > sure -- that would be one way to do it -- maybe good way. But it would be a > lot more complicated than just keeping days. Lots to hash out for API and > functionality at the corner cases (the old what's one year after Feb 29th? > kinds of questions) I'd say "one year after Feb 29th" is exactly the same question as "one day after 2:30AM before a DST switch", and has the same answer (add another day, or another hour). >> When you add a >> calendardelta to an aware datetime, it performs what you're describing >> as calendar arithmetic, > > actually, no reason you couldn't do calendar manipulations on naive > datetimes, too (they wouldn't get any ugly DST issues, but otherwise the > same). One reason I don't like calling the arithmetic naive or not.... Yes, but when you do them on naive datetimes, they'll be indistinguishable from the existing behaviour, and thus not a compelling argument for a new timedelta variant. I agree though - it wouldn't be an error to add a calendardelta to a naive datetime. >> adding >> calendardelta(days=1) would never affect the hour/minute/second shown, >> unless it would otherwise create an illegal time. > > > exactly -- all those corner cases would need to be worked out. Simplest definition would be what we want here. Jump forward by another unit of whatever one has disappeared. What if we're moving backward? If you subtract a year from Feb 29th 2012, do you get Feb 28th 2011 or Mar 1st 2011? But I think adding a year should produce Mar 1st 2013. ChrisA From tim.peters at gmail.com Wed Jul 29 05:13:12 2015 From: tim.peters at gmail.com (Tim Peters) Date: Tue, 28 Jul 2015 22:13:12 -0500 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <-4087362986376999997@unknownmsgid> Message-ID: [Chris Angelico ] > What if the existing timedelta is left as-is, That much isn't a "what if" - that much is a requirement ;-) > and a new calendardelta type is introduced? Instead of folding > everything down to a simple microsecond count, it would retain > the exact values it was given, > so calendardelta(days=1) != calendardelta(seconds=86400). > When you add a calendardelta to an aware datetime, it performs > what you're describing as calendar arithmetic That's what the _current_ timedelta already does (things like "same time tomorrow", "same time in 25000 weeks", and "same time plus an hour 57 days ago" are all trivially done already by datetime + timedelta operations). What Lennart is on about is that there's no direct way to spell "the other" kind of arithmetic now (operationally defined by: convert to UTC first, then do the "naive arithmetic", and finally convert back to the original timezone). But it's also straightforward to write a simple function to do that, and not every simple function has to be built in. > and it will be the most plausibly sane behaviour for the exact unit used; so, > for instance, adding calendardelta(days=1) would never affect the hour/minute/second > shown, unless it would otherwise create an illegal time. Would that serve? Note that timedelta doesn't accept any units for which there are any questions about what a "calendar operation" "should do" in Guido's "naive time" design. That's also an intentional part of the datetime design. So. e.g., you can ask a timedelta for some number of days or weeks, but _not_ for some number of months or years. "Why not years?" is because there's one case where what to do isn't 100% obvious to everyone: a year starting from a leap year's 29 Feb. "Why not a month?" has many more questionable cases. In any case, you should look at other Python date-&-time libraries (like mxDateTime and dateutil) because there are already approaches to richer "calendar options" fully thought out. From alexander.belopolsky at gmail.com Wed Jul 29 05:17:14 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Tue, 28 Jul 2015 23:17:14 -0400 Subject: [Datetime-SIG] Datetime arithmetic proposal In-Reply-To: References: Message-ID: On Tue, Jul 28, 2015 at 10:45 PM, Tim Peters wrote: > But, > internally,datetimes, dates, times, and timedeltas are all sometimes > viewed as just complicated ways of spelling "some number of > microseconds". While obvious when you look from the inside of the implementation, this is something that datetime library users will never understand. That's why over my strong objections, timedelta grew its total_seconds() method which is nothing else but x / timedeta(seconds=1). After that, I gave up and committed datetime.timestamp() as a shortcut for (x - EPOCH) / timedeta(seconds=1). From rosuav at gmail.com Wed Jul 29 07:04:36 2015 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 29 Jul 2015 15:04:36 +1000 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <-4087362986376999997@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 1:13 PM, Tim Peters wrote: > [Chris Angelico ] >> What if the existing timedelta is left as-is, > > That much isn't a "what if" - that much is a requirement ;-) Heh, sure. Vagaries of the English language sometimes result in an apparent suggestion like this :) >> and a new calendardelta type is introduced? Instead of folding >> everything down to a simple microsecond count, it would retain >> the exact values it was given, >> so calendardelta(days=1) != calendardelta(seconds=86400). >> When you add a calendardelta to an aware datetime, it performs >> what you're describing as calendar arithmetic > > That's what the _current_ timedelta already does (things like "same > time tomorrow", "same time in 25000 weeks", and "same time plus an > hour 57 days ago" are all trivially done already by datetime + > timedelta operations). Except that it isn't possible to distinguish "add 86400 seconds" from "add 1 day". It's fine for adding to a naive datetime, as they're equivalent, but they differ with aware datetimes - hence the notion of having a different way to add to them. The semantics would be that adding any unit to an aware datetime *will not change* any unit of finer resolution, unless the result would otherwise be impossible to represent. So when you add 1 day to 9AM today, you get 9AM tomorrow; but when you add 24 hours to 9AM today, you might get 10AM tomorrow, because one hour got snipped out of the intervening night. Similarly, adding 1 year to Feb 23rd 2012 will result in Feb 23rd 2013 (has added 366 days), but adding 1 year to Feb 23rd 2013 will add only 365 days; this is a concept that the current timedelta simply can't handle, as it doesn't work in any unit larger than the day. There is one edge case that I'm aware of, and that's where the simple calculation results in an invalid timestamp - either because the clock jumps forward (DST switch) or because you would land on a leap day. In each case, it's possible only when you're moving in a unit greater than the one that's being adjusted - you can't land on Feb 29th 2015 by moving X days, because it'll count days right past it, so you must have been moving months or years. When you move forward, the obvious thing is to jump forward by a distance exactly equal to the gap - one extra day to land on March 1st, or one extra hour to land at 3AM - but I'm not sure what the best solution is when moving backward. Are there any other nasty edge cases? ChrisA From guido at python.org Wed Jul 29 12:40:51 2015 From: guido at python.org (Guido van Rossum) Date: Wed, 29 Jul 2015 12:40:51 +0200 Subject: [Datetime-SIG] The BDFL's take Message-ID: [I posted this to python-ideas, but then found that this SIG was created. So let's discuss it here.] Honestly, I think some of these proposals are way too ambitious and will drown in a sea of bike-shedding. Here's what I think is reasonable: - Keep the time module; POSIX timestamps represented as floats are still very useful (and ubiquitous in other APIs), and it would take decades to deprecate. - Keep the datetime module; it has its uses (and even fans), and again, deprecating would take decades. - Add a few convenience APIs to one or both of the above for better conversion between various forms of datetime and POSIX timestamps (I think there are a few missing APIs in this area). - Design a new module with a separate API for "human time manipulation". This is where operations belong like "add 1 month" or "add 1 day" with heuristics for edge cases (e.g. months of different lengths due to calendar conventions, and the occasional short or long day due to DST). Possibly this can borrow some API and/or implementation from pytz. Possibly it could be made available as a 3rd party module on PyPI first, to get it user-tested in quick iterations (quicker than core Python releases, anyway). But that doesn't preclude also writing a PEP. This module needs to interface somehow with the datetime module (and possibly also with the time module) in ways that need some serious thinking -- that's where I expect the hard part of writing the PEP will be. (Maybe a "human timedelta" type would be useful here? Eventually this might even be added to the datetime module.) There are a few additional issues which I'm not sure are included in this discussion or not: - A unified API for accessing an up-to-date timezone database. This has been discussed in the past, and we couldn't find a solution that satisfied all requirements (the main problem being different platform expectations IIRC), but it's probably worth it trying again. - Nanosecond precision? I'm not against adding this to the datetime module, as long as backward compatibility is somehow preserved, especially for pickles (maybe nanoseconds default to zero unless explicitly requested or specified). - An "is_dst" flag for datetime objects. Again, this should default to "backwards compatible" (== "don't care", the -1 value in struct tm) so that pickles are two-way compatible with Python 3.5 and before. -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From guido at python.org Wed Jul 29 12:42:09 2015 From: guido at python.org (Guido van Rossum) Date: Wed, 29 Jul 2015 12:42:09 +0200 Subject: [Datetime-SIG] [Python-ideas] Additional datetime-like module In-Reply-To: References: <55B7E1BD.8030509@mgmiller.net> <915F863B-21CC-4682-B179-43EB861720B1@yahoo.com> Message-ID: Oops, let's move this to datetime-sig. I've reposted this there under the subject "The BDFL's take". On Wed, Jul 29, 2015 at 12:20 PM, Guido van Rossum wrote: > Honestly, I think some of these proposals are way too ambitious and will > drown in a sea of bike-shedding. > [...] > -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From guido at python.org Wed Jul 29 13:17:20 2015 From: guido at python.org (Guido van Rossum) Date: Wed, 29 Jul 2015 13:17:20 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: One more thing. The calendar module should probably be left alone, but its timegm() function should be moved to the time module. That was a very unfortunate API choice. -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From regebro at gmail.com Wed Jul 29 15:21:12 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 15:21:12 +0200 Subject: [Datetime-SIG] Calendar vs timespan calculations... Message-ID: Sorry, catching up with the posts, here, as the mailing list was created when I was asleep. So I'm cutting and pasting from the archives... Chris Barker chris.barker at noaa.gov: > [that a day is always 24 hours] it's not an assumption, it's a definition. Right, but that's like defining Pi to be three. It's not in accordance to reality, and therefore it causes a lot of problems. > What is currently supported by the datetime module, and I think Tim is > referring to as "naive" time operations: adding, subtracting, units of time > along the theoretical time axis. Well, that is supported, yes, but only for datetimes that does not have a time zone, or that has a time zone with a fixed offset. It is NOT supported for datetimes with a time zone of the type that people typically live in: One whose offset changes from time to time. In practice, pretty much all of them except UTC. That means if you want to do these operations, you have to first convert the datetime to UTC, then do the arithmetic and then convert it back. > Then there are what I am calling "calendar" operations -- these are > operations that only make sense with a calendar (and, in fact a timezone, I > think). this is operations like: "the same time two days later" -- this is > not the same as moving two days (48 hrs) along the time axis -- it simply > is not. Right. These operations *are* in fact supported, but in a limited fashion. There is no support for months or years, notably. You can add days, hours, minutes and seconds, but you have to be aware then that you can end up with datetimes that does not actually exist, or are ambiguous, ie times that happens twice. I wish it was as you assumed it was, because that would have been much easier to fix, as you say, we can have add the "calendar" operations into a separate package, and yes, that is indeed what dateutil's "relativedelta" does, amongst some other things. It might be possible to add a real time delta in a separate package as well, I haven't looked into that. > Given all the ugliness of DST and changing time zones, and all that, UTC is > the lingua franca of time -- time zones are defined by how the are offset > from UTC, and in UTC (as in naive), math is relatively easy. So the best > way to handle time zones is to store and manipulate everything in UTC, and > then convert to/from the calendar representation using the time zone, when > the user needs (or provides). Yes, that would indeed have been the simple and obvious way to implement it, but datetime stores everything in the local zone, which makes it a lot more complex, as you get things like ambiguous times and non-existent times when you do that. //Lennart From regebro at gmail.com Wed Jul 29 15:36:21 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 15:36:21 +0200 Subject: [Datetime-SIG] What's are the issues? Message-ID: Chris Barker chris.barker at noaa.gov > What are the issues still to be resolved? [with the PEP] The is_dst flags added are not implementable, as they aim to make it possible to do correct timezone conversions, and Guido and Tim have declared that they don't want that, but that they want to keep the arithmetic what they call "naive". I'll send in a patch to withdraw PEP-431 it later today, I hope. //Lennart From regebro at gmail.com Wed Jul 29 16:04:24 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 16:04:24 +0200 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: Tim Peters tim.peters at gmail.com: > But, as the docs have always pointed out, it (specifically .fromutc(), > which is at the base of all relevant calculations) doesn't even try to > handle transitions due to _other_ causes. The only other such cause > I'm aware of is when a timezone's _base_ offset from UTC changes (not > a temporary DST transition, the timezone's "standard" offset changes > permanently (meaning until someone decides to change it again)). Wait, what? This will be handled in the exact same way as DST changes, and if this is incorrect, then reasonably, so is the DST handling. What is "incorrect" here is of course a matter of opinion. I think it's incorrect because it doesn't agree with reality, you have claimed that it is correct, in "as per design". But then reasonably that goes for this case as well? The same thing happens, which is that depending on the transitions direction, you can either end up in a time that doesn't exist, or one that happens twice. //Lennart From regebro at gmail.com Wed Jul 29 16:06:10 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 16:06:10 +0200 Subject: [Datetime-SIG] The BDFL's take Message-ID: > - Design a new module with a separate API for "human time manipulation". That would be reasonable. Unfortunately, that's what datetime tries to implement already, but does so only a little bit. It's the non-human (ie correct) arithmetic that is lacking, for datetimes that have timezones. //Lennart From alexander.belopolsky at gmail.com Wed Jul 29 16:37:27 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 10:37:27 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 10:06 AM, Lennart Regebro wrote: >> - Design a new module with a separate API for "human time manipulation". > > That would be reasonable. Unfortunately, that's what datetime tries to > implement already, but does so only a little bit. It's the non-human > (ie correct) arithmetic that is lacking, for datetimes that have > timezones. Can you provide a specific example that demonstrate that something is lacking? As far as I can tell, the following is an example of a "non-human" time arithmetics: >>> t = datetime(2014, 1, 1, 17, tzinfo=timezone.utc).astimezone() >>> t.strftime('%c %Z %z') 'Wed Jan 1 12:00:00 2014 EST -0500' >>> u = t + timedelta(1) >>> u.astimezone().strftime('%c %Z %z') 'Thu Jan 2 12:00:00 2014 EST -0500' The only bit that I can see as "lacking" in this example is the ability to elide the second call to astimezone() and have a fancy tzinfo class that will take care of the DST transition. This is also possible, but by design, you get a "human" answer in this case: >>> t = datetime(2014,11,1,12,tzinfo=Eastern) >>> t.strftime('%c %Z %z') 'Sat Nov 1 12:00:00 2014 EDT -0400' >>> t += timedelta(1) >>> t.strftime('%c %Z %z') 'Sun Nov 2 12:00:00 2014 EST -0500' So I really don't understand your complaint. Both "human" and "non-human" calculations are easy with the current implementation of the datetime module. Since it does not include any "human" tzinfo implementations out of the box, many people say that "human time manipulation" is lacking. However, "human time manipulation" includes more than automatic DST transitions: it also includes adding months, years and possibly quarters and other units. To me the perfect example of the "human time manipulation" is the GNU date utility: $ date -d "last friday" Fri Jul 24 00:00:00 EDT 2015 $ date -d "next month" Sat Aug 29 10:35:46 EDT 2015 $ date -d "week ago" Wed Jul 22 10:36:47 EDT 2015 From alexander.belopolsky at gmail.com Wed Jul 29 16:43:03 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 10:43:03 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 10:37 AM, Alexander Belopolsky wrote: > an example of a "non-human" time arithmetics: > >>>> t = datetime(2014, 1, 1, 17, tzinfo=timezone.utc).astimezone() >>>> t.strftime('%c %Z %z') > 'Wed Jan 1 12:00:00 2014 EST -0500' >>>> u = t + timedelta(1) >>>> u.astimezone().strftime('%c %Z %z') > 'Thu Jan 2 12:00:00 2014 EST -0500' Sorry, I missed "1" in the month. It should have been >>> t = datetime(2014, 11, 1, 17, tzinfo=timezone.utc).astimezone() >>> t.strftime('%c %Z %z') 'Sat Nov 1 13:00:00 2014 EDT -0400' >>> u = t + timedelta(1) >>> u.astimezone().strftime('%c %Z %z') 'Sun Nov 2 12:00:00 2014 EST -0500' From regebro at gmail.com Wed Jul 29 16:49:42 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 16:49:42 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 4:37 PM, Alexander Belopolsky wrote: > On Wed, Jul 29, 2015 at 10:06 AM, Lennart Regebro wrote: >>> - Design a new module with a separate API for "human time manipulation". >> >> That would be reasonable. Unfortunately, that's what datetime tries to >> implement already, but does so only a little bit. It's the non-human >> (ie correct) arithmetic that is lacking, for datetimes that have >> timezones. > > Can you provide a specific example that demonstrate that something is > lacking? >>> from datetime import * >>> from dateutil.zoneinfo import gettz >>> est = gettz('US/Eastern') >>> dt1 = datetime(2014, 11, 2, 0, 30, tzinfo=est) >>> dt1 datetime.datetime(2014, 11, 2, 0, 30, tzinfo=tzfile('America/New_York')) >>> dt1 + timedelta(hours=1) datetime.datetime(2014, 11, 2, 1, 30, tzinfo=tzfile('America/New_York')) >>> dt1 + timedelta(hours=2) datetime.datetime(2014, 11, 2, 2, 30, tzinfo=tzfile('America/New_York')) In fact at 2am, the hour swithes back one hour, so two hours after 00:30 is 01:30. Yes, 01:30 happens twice. This means that the above calculations are incorrect. It is the "naive" or "human" implementation here, where adding one hour actually adds two. And further: >>> dt = datetime(2014, 3, 9, 0, 30, tzinfo=est) >>> dt + timedelta(hours=1) datetime.datetime(2014, 3, 9, 1, 30, tzinfo=tzfile('America/New_York')) >>> dt + timedelta(hours=2) datetime.datetime(2014, 3, 9, 2, 30, tzinfo=tzfile('America/New_York')) Oups! At 2:30 that day, the clock is shifted forward one hour. 2:30 am on the 9th of March 2014 is a time that did not exist in New York! This is "human" arithmetic, ie, the arithmetic that you would expect if you forget that timezones change. > So I really don't understand your complaint. Both "human" and "non-human" > calculations are easy with the current implementation of the datetime module. I disagree with that. To make "non-human" (ie correct) calculations I have to first convert the timezone to UTC, then do the calculations, then convert it back. Two out those three things are unnecessary, it's perfectly possible to make an implementation that doesn't need them. > Since it does not include any "human" tzinfo implementations out of the box, > many people say that "human time manipulation" is lacking. However, > "human time manipulation" includes more than automatic DST transitions: > it also includes adding months, years and possibly quarters and other units. I agree. Hence my statement that "human" manipulation is what datetime implements, but only partly. > To me the perfect example of the "human time manipulation" is the GNU > date utility: > > $ date -d "last friday" > Fri Jul 24 00:00:00 EDT 2015 > $ date -d "next month" > Sat Aug 29 10:35:46 EDT 2015 > $ date -d "week ago" > Wed Jul 22 10:36:47 EDT 2015 Yup, that would be nice. From regebro at gmail.com Wed Jul 29 16:51:21 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 16:51:21 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 4:49 PM, Lennart Regebro wrote: > Oups! At 2:30 that day, the clock is shifted forward one hour. Double oups! Obviously it is at 2:00am, not 2:30 am. From alexander.belopolsky at gmail.com Wed Jul 29 17:18:25 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 11:18:25 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 10:49 AM, Lennart Regebro wrote: > I disagree with that. To make "non-human" (ie correct) calculations I > have to first convert the timezone to UTC, then do the calculations, > then convert it back. You snipped my example and I won't repeat it for the umpteen time, but it did not involve converting the timezone to UTC at all. From alexander.belopolsky at gmail.com Wed Jul 29 17:32:55 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 11:32:55 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 10:49 AM, Lennart Regebro wrote: >>>> est = gettz('US/Eastern') >>>> dt1 = datetime(2014, 11, 2, 0, 30, tzinfo=est) >>>> dt1 > datetime.datetime(2014, 11, 2, 0, 30, tzinfo=tzfile('America/New_York')) >>>> dt1 + timedelta(hours=1) > datetime.datetime(2014, 11, 2, 1, 30, tzinfo=tzfile('America/New_York')) >>>> dt1 + timedelta(hours=2) > datetime.datetime(2014, 11, 2, 2, 30, tzinfo=tzfile('America/New_York')) > > In fact at 2am, the hour swithes back one hour, so two hours after > 00:30 is 01:30. Yes, 01:30 happens twice. This means that the above > calculations are incorrect. But it is fair. "You get nothing for nothing in New York City," yet if you had booked hockey time at the local ice rink ending 2014-11-02T02:00, you would get an hour free. A non-humane accounting program would charge you for that extra hour, but a humane one does not and I like it that way. :-) From regebro at gmail.com Wed Jul 29 17:33:35 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 17:33:35 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 5:18 PM, Alexander Belopolsky wrote: > You snipped my example and I won't repeat it for the umpteen time, but > it did not involve converting the timezone to UTC at all. You asked for examples of problem, I gave you two example of problems. You are welcome to ask me things, but I will continue to snip away everything I'm not directly answering. That was basic netikette in internet discussions during the 80's and 90's, and I have this ingrained in my spine, and I can't change it, I do it automatically without thinking. Also, with a modern email reader, you should have no problem in following the conversation even if I delete things. Snippingly yours Lennart From tim.peters at gmail.com Wed Jul 29 17:40:51 2015 From: tim.peters at gmail.com (Tim Peters) Date: Wed, 29 Jul 2015 10:40:51 -0500 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: [Tim] >> But, as the docs have always pointed out, it (specifically .fromutc(), >> which is at the base of all relevant calculations) doesn't even try to >> handle transitions due to _other_ causes. The only other such cause >> I'm aware of is when a timezone's _base_ offset from UTC changes (not >> a temporary DST transition, the timezone's "standard" offset changes >> permanently (meaning until someone decides to change it again)). [Lennart] > Wait, what? > > This will be handled in the exact same way as DST changes, and if this > is incorrect, then reasonably, so is the DST handling. Nope, that's mistaken on both counts, but it is technical. What I said is correct in all respects given the current code. Note that how time zone _conversions_ work has nothing to do with user-visible arithmetic semantics. .Timezone conversions aren't even a concept in the "naive time" model, which latter is the model single-zone datetime arithmetic follows. Conversions and arithmetic have no conceptual intersection in datetime. Completely distinct issues. I'm saying that in four different ways because I've said all four before in other messages, but never before all in a single message. If I try all possible ways of saying it, one of them is bound to get across eventually ;-) .astimezone() and .fromutc() do whatever they need to do to meet _their_ contracts. How arithmetic works is irrelevant to their contracts: they have to meet their contracts regardless of how datetime arithmetic works, or even if user-visible datetime arithmetic had not been implemented at all. The default conversion implementations are strong enough to do the best possible job in the absence of the missing "is or is not DST intended?" flag. That info is indispensable in a handful of cases, so they have to guess in those cases. If an is_dst-;like flag were added, they would no longer need to guess in those cases. However, this is only strong enough to handle DST transitions. This is basically because we can directly ask a tzinfo instance whether we are or aren't in daylight time (.dst()), but can't directly ask it whether the base UTC offset has _changed_. Indeed, we can't even directly ask a tzinfo subclass what the base offset _is_! We can only ask it what the _total_ UTC offset is (.utcoffset()) and what the current DST adjustment is (.dst()) at specific points in time. The current algorithm is very brief and efficient (although tedious to prove correct!), but bought the latter at the cost of _assuming_ the base UTC offset never changes over time. Of course that's a documented assumption. > What is "incorrect" here is of course a matter of opinion. As documented, time zone conversions mimic the destination zone's local clock in the case of DST transitions: some span of local times "vanish" when local DST starts, and some span of local times are repeated when local DST ends. It mimics the destination's local time reality. My guess is that we agree that's "correct" (I know I believe it - I'm guessing about you ;-) ). > I think it's incorrect because it doesn't agree with reality, you have claimed > that it is correct, in "as per design". Again, how the conversion routines work have nothing to do with how user-visible arithmetic works. That's because (at the conceptual design level) conversions have nothing to do with the "naive time" model; conversions take place outside that model, just as, e.g., manually adjusting a mechanical wrist watch at DST transitions occurs outside the watch's implementation of naive time. > But then reasonably that goes for this case as well? The same thing > happens, which is that depending on the transitions direction, you can > either end up in a time that doesn't exist, or one that happens twice. Which is how .fromutc() "should be" strengthened to work in cases where the _base_ UTC offset changes. The current implementation is wholly oblivious to that possibility. But it is reasonable to ask how important it is to strengthen .fromutc(). The .fromutc() docs have always said: """ Most tzinfo subclasses should be able to inherit the default fromutc() implementation without problems. It?s strong enough to handle fixed-offset time zones, and time zones accounting for both standard and daylight time, and the latter even if the DST transition times differ in different years. An example of a time zone the default fromutc() implementation may not handle correctly in all cases is one where the standard offset (from UTC) depends on the specific date and time passed, which can happen for political reasons. The default implementations of astimezone() and fromutc() may not produce the result you want if the result is one of the hours straddling the moment the standard offset changes. """ and the .astimezone() docs have always said: """ Note that the default tzinfo.fromutc() method can be overridden in a tzinfo subclass to affect the result returned by astimezone(). ''"" and the .dst() docs have always said: """ An instance tz of a tzinfo subclass that models both standard and daylight times must be consistent in this sense: tz.utcoffset(dt) - tz.dst(dt) must return the same result for every datetime dt with dt.tzinfo == tz For sane tzinfo subclasses, this expression yields the time zone?s ?standard offset?, which should not depend on the date or the time, but only on geographic location. The implementation of datetime.astimezone() relies on this, but cannot detect violations; it?s the programmer?s responsibility to ensure it. If a tzinfo subclass cannot guarantee this, it may be able to override the default implementation of tzinfo.fromutc() to work correctly with astimezone() regardless. """ Have any of the later Python date-and-time packages bothered to implement a stronger .fromutc()? I don't know. The potential problems with base-offset-changing tzinfo subclasses have always been documented, and I made .fromutc() a user-visible method precisely so that it _could_ be overridden, and the docs have always explicitly pointed that out But if nobody has bothered to create a stronger version after a dozen years ... well, everyone can draw their own conclusions ;-) From chris.barker at noaa.gov Wed Jul 29 17:42:48 2015 From: chris.barker at noaa.gov (Chris Barker - NOAA Federal) Date: Wed, 29 Jul 2015 08:42:48 -0700 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: <3572339734014533140@unknownmsgid> Sent from my iPhone Chris Barker chris.barker at noaa.gov What are the issues still to be resolved? [with the PEP] The is_dst flags added are not implementable, as they aim to make it possible to do correct timezone conversions, and Guido and Tim have declared that they don't want that, but that they want to keep the arithmetic what they call "naive Huh? Now I'm really confused. IIUC, the is_dst flag is required in order to be able to round-trip between UTC and local_time representations. In particular, so the API can support specifying a datetime in a time zone that "happens" twice without ambiguity. But this is required whether or not you want to support what I'm calling Calendar operations. Also, the PEP is about adding useful tzinfo objects to the stdlib, yes? I agree that tzinfo objects are much less useful without a is_dst flag, but that is orthogonal to how tzinfo objects work. Guido and Tim have declared that they don't want that, but that they want to keep the arithmetic what they call "naive This is why I've been harping on semantics. Apparently I've totally misunderstood Tim's points ( or you have ;-) ). As it stands today, time arithmetic such as: A_datetime + timedelta( days=1) Means: return a datetime object that represents a point on the time continuum 24 hours further on. There is no reason that has to change one bit in order to support time zones "properly". All a timezone is is a set of rules for how to map from a point on the time continuum to our human-friendly, politically and astronomically driven "calendar" representation. Doing that correctly is really useful in an of itself. You are interpreting Tim's "naive time arithmetic" differently than I have ( though his last note did confuse me, and did fit your interpretation), so I'll try to re-phrase: The datetime module does, and will always define: A_datetime + timedelta( days=1) To mean *BOTH*: "Move along the time continuum 24 hours." And "Move to the same clock time of the next calendar day" I find this hard to believe, because that can only be true for naive datetime a, or timezones with no DST and no change of definition. (I.e. UTC). And yet, the original implementation did provide a hook for a tzinfo object. Was it never intended to be useful???? BTW, as Tim pointed out (and I at least found it interesting), that datetime, while encoding the location on the time continuum in calendar units ( year, month, day, ....), when doing operations, it is essentially working in "microseconds since year 1". Which, indeed, is what you need to do to do time arithmetic rationally. I'll send in a patch to withdraw PEP-431 it later today, I hope. Sigh. Just saw the PEP update. Yes, doing calculations in UTC is the best way to go -- using an encoding that is not continuous for arithmetic would be a nightmare. Sorry to be late to the party, but I'll take your word for it that doing the to-from UTC conversion would be difficult with the current implementation. -Chris //Lennart _______________________________________________ Datetime-SIG mailing list Datetime-SIG at python.org https://mail.python.org/mailman/listinfo/datetime-sig The PSF Code of Conduct applies to this mailing list: https://www.python.org/psf/codeofconduct/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From regebro at gmail.com Wed Jul 29 17:45:32 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 17:45:32 +0200 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 5:40 PM, Tim Peters wrote: > Nope, that's mistaken on both counts, but it is technical. What I > said is correct in all respects given the current code. That the current code works as designed is not really the issue we discuss here, though. And then you start discussing conversions, which wasn't the issue, it was arithmetic. *shrugs* From alexander.belopolsky at gmail.com Wed Jul 29 17:50:46 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 11:50:46 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 11:33 AM, Lennart Regebro wrote: > On Wed, Jul 29, 2015 at 5:18 PM, Alexander Belopolsky > wrote: >> You snipped my example and I won't repeat it for the umpteen time, but >> it did not involve converting the timezone to UTC at all. > > You asked for examples of problem, I gave you two example of problems. The problems you gave, are perfectly solvable using current Python 3 standard library. For some reason you insist on solving them using third party tools that are not designed for those particular tasks. You want to know what was the local time in New York one astronomical hour after 2014-11-02T01:30-0400 - set TZ=America/New_York and do this: >>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%z") >>> u = (t+timedelta(hours=1)) >>> u.astimezone().strftime("%Y-%m-%dT%H:%M%z") '2014-11-02T01:30-0500' What do you see lacking in this solution? The only thing I see worth improving is adding support for more than one local timezone so that I could ask for >>> u.astimezone('Australia/Melbourne') without having to switch my global TZ settings. From lrekucki at gmail.com Wed Jul 29 17:53:14 2015 From: lrekucki at gmail.com (=?UTF-8?Q?=C5=81ukasz_Rekucki?=) Date: Wed, 29 Jul 2015 17:53:14 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On 29 July 2015 at 17:18, Alexander Belopolsky wrote: > On Wed, Jul 29, 2015 at 10:49 AM, Lennart Regebro wrote: >> I disagree with that. To make "non-human" (ie correct) calculations I >> have to first convert the timezone to UTC, then do the calculations, >> then convert it back. > > You snipped my example and I won't repeat it for the umpteen time, but > it did not involve converting the timezone to UTC at all. Corrected example (with 11 as month): >>> t = datetime(2014, 11, 1, 17, tzinfo=timezone.utc).astimezone() >>> t.strftime('%c %Z %z') '11/01/14 18:00:00 Central European Standard Time +0100' >>> u = t + timedelta(1) >>> u.astimezone().strftime('%c %Z %z') '11/02/14 17:00:00 Central European Standard Time +0000' The cheat here is that you call "astimezone()" without arguments, thus it will *always* convert to UTC and back internally (even if your OS timezone did not change a single bit). If you pass TZ explicitly, it doesn't work: >>> t = datetime(2014, 11, 1, 17, tzinfo=timezone.utc).astimezone() >>> t.strftime('%c %Z %z') '11/01/14 18:00:00 Central European Standard Time +0100' >>> zone = t.tzinfo >>> u = t + timedelta(1) >>> u = u.astimezone(zone) >>> u.strftime('%c %Z %z') '11/02/14 18:00:00 Central European Standard Time +0100' BR, ?ukasz Rekucki From regebro at gmail.com Wed Jul 29 18:02:07 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 18:02:07 +0200 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: <3572339734014533140@unknownmsgid> References: <3572339734014533140@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 5:42 PM, Chris Barker - NOAA Federal wrote: > Huh? Now I'm really confused. IIUC, the is_dst flag is required in order to > be able to round-trip between UTC and local_time representations. No, that's not necessary. It's necessary to disambiguate between ambiguous datetimes, but you can, like dateutils implementation, simply just pick one consistently, and you can round-trip. > In particular, so the API can support specifying a datetime in a time zone > that "happens" twice without ambiguity. Yes, but that has now been declared as not desired. We no longer want datetime to be able to do that. That's only a feature you need or even can have if you want to do real time arithmetic over DST changes. But the current functionality, and it has been pronounced that this functionality shall remain, does not allow for that disambiguation. It assumes that one day is 24 hours at all time, and that DST shall be ignored. For what is then the dst-flag? > Also, the PEP is about adding useful tzinfo objects to the stdlib, yes? Yes, that part is doable, so if somebody wants to resurrect the PEP to do that they are welcome. I won't. > This is why I've been harping on semantics. Apparently I've totally > misunderstood Tim's points ( or you have ;-) ). > > As it stands today, time arithmetic such as: > > A_datetime + timedelta( days=1) > > Means: return a datetime object that represents a point on the time > continuum 24 hours further on. No, that's not what it means. It means "return a datetime object with the same time, the next day". That's OK, by itself, unfortunately it also means that "A_datetime + timedelta(hours=24)" means the same thing, and that's a problem, since adding 24 hours can result in a datetime object that is 23 to 25 hours later. > You are interpreting Tim's "naive time arithmetic" differently than I have ( > though his last note did confuse me, and did fit your interpretation), so > I'll try to re-phrase: > > The datetime module does, and will always define: > > A_datetime + timedelta( days=1) > > To mean *BOTH*: > > "Move along the time continuum 24 hours." > And > "Move to the same clock time of the next calendar day" Exactly. > I find this hard to believe, because that can only be true for naive > datetime a, or timezones with no DST and no change of definition. (I.e. > UTC). Exactly the problem. The assumption/definition of one day always being 24 hours breaks reality, in much the same way as assuming pi is 3. And (as Pratchett fans are aware, doing so opens holes to parallel universes). > Sorry to be late to the party, but I'll take your word for it that doing the > to-from UTC conversion would be difficult with the current implementation. Well, doing it in a way that agrees with time outside of datetimes pi=3 definition is, yes. Otherwise it's reasonably easy, and dateutil has done it. pytz did implement correct arithmetic, but only by implementing a function called "normalize()" which corrects for datetime's mistakes. //Lennart From alexander.belopolsky at gmail.com Wed Jul 29 18:04:18 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 12:04:18 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 11:53 AM, ?ukasz Rekucki wrote: > The cheat here is that you call "astimezone()" without arguments, thus > it will *always* convert to UTC and back internally (even if your OS > timezone did not change a single bit). This is not a "cheat." This is a documented and the recommended way to accomplish this task. > If you pass TZ explicitly, it doesn't work. Sure and there are an infinite number of other ways to make a mistake in date/time calculations. From regebro at gmail.com Wed Jul 29 18:08:58 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 18:08:58 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 5:50 PM, Alexander Belopolsky wrote: > The problems you gave, are perfectly solvable using current Python 3 standard > library. No, it isn't, as the Python 3 standard library does not contain real-life timezone implementations. > For some reason you insist on solving them using third party > tools that are not designed for those particular tasks. The third party tool is designed to handle real-life timezone implementations, and implements them precisely the way the datetime designers intented. It does exactly what Tim says it should do. > You want to know what was the local time in New York one astronomical hour > after 2014-11-02T01:30-0400 - set TZ=America/New_York and do this: > >>>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%z") >>>> u = (t+timedelta(hours=1)) >>>> u.astimezone().strftime("%Y-%m-%dT%H:%M%z") > '2014-11-02T01:30-0500' >>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%z") ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M%z' Nope, didn't work. Did you mean uppercase Z? >>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%Z") ValueError: time data '2014-11-02T01:30-0400' does not match format '%Y-%m-%dT%H:%M%Z' Probably, but it still didn't work. > What do you see lacking in this solution? Please test your examples before you paste them, I have no idea what you are trying to do. From regebro at gmail.com Wed Jul 29 18:11:11 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 18:11:11 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 5:50 PM, Alexander Belopolsky wrote: > What do you see lacking in this solution? Btw: I pasted examples of the problems. That you can work around those in various ways do not change the fact that those problems remain. Do you have question about those examples? //Lennart From felipe.nospam.ochoa at gmail.com Wed Jul 29 18:20:19 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Wed, 29 Jul 2015 12:20:19 -0400 Subject: [Datetime-SIG] is_dst flag Message-ID: In the hopes of separating the discussion into the various sub-issues, here's what I think is the status on the is_dst flag. (Guido) From '[Datetime-SIG] The BDFL's take' > - An "is_dst" flag for datetime objects. Again, this should default to > "backwards compatible" (== "don't care", the -1 value in struct tm) so that > pickles are two-way compatible with Python 3.5 and before. The key thing here is that the flag is **on the datetime object**, (in addition, timezone objects can keep track of whatever they internally need). This flag is only necessary for local times with a timezone that can occur twice. The typical use-case is, e.g., 1.30am on the day that clocks turn back for DST in the US. `datetime(2002, 10, 27, 1, 30, 0, tzinfo=zoneinfo('America/New_York')` is ambiguous, and the point of the is_dst flag is to determine which of the two possible moments the datetime refers to. Note that the ambiguity is only a factor when converting to another timezone (or a unix timestamp). Sidenote: Per earlier discussion, this flag should probably have a different name to clarify that it only applies in ambiguous cases, and is not just a DST problem (For another example, see the pytz docs and search for Warsaw). -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Wed Jul 29 18:23:07 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 12:23:07 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 12:08 PM, Lennart Regebro wrote: >>>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%z") > ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M%z' > > Nope, didn't work. Sorry, but it does work for me: $ TZ=America/New_York python3 Python 3.4.3 (default, Jul 20 2015, 12:59:38) [GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from datetime import * >>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%z") which version of Python are you using? From felipe.nospam.ochoa at gmail.com Wed Jul 29 18:31:15 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Wed, 29 Jul 2015 12:31:15 -0400 Subject: [Datetime-SIG] Timezone database Message-ID: [Branching from The BDFL's take] There are a few additional issues which I'm not sure are included in this > discussion or not: > - A unified API for accessing an up-to-date timezone database. This has > been discussed in the past, and we couldn't find a solution that satisfied > all requirements (the main problem being different platform expectations > IIRC), but it's probably worth it trying again. The current solution proposed in the PEP is to have platforms with /usr/share/zoneinfo use that as long as they want. For other platforms Python would ship with a built-in copy (roughly speaking) of the database. There would then be separate tzdata-update package on pypi that can be `pip install`ed to update the timezone database whenever the user feels the need to do so (because /usr/share/zoneinfo is no longer receiving updates or because it doesn't exist) What are the unsatisfied requirements of this design? -------------- next part -------------- An HTML attachment was scrubbed... URL: From felipe.nospam.ochoa at gmail.com Wed Jul 29 18:31:47 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Wed, 29 Jul 2015 12:31:47 -0400 Subject: [Datetime-SIG] The BDFL's take Message-ID: [Guido] > - Design a new module with a separate API for "human time manipulation". > This is where operations belong like "add 1 month" or "add 1 day" with > heuristics for edge cases (e.g. months of different lengths due to calendar > conventions, and the occasional short or long day due to DST). Possibly > this can borrow some API and/or implementation from pytz. Possibly it could > be made available as a 3rd party module on PyPI first, to get it > user-tested in quick iterations (quicker than core Python releases, > anyway). But that doesn't preclude also writing a PEP. This module needs to > interface somehow with the datetime module (and possibly also with the time > module) in ways that need some serious thinking -- that's where I expect > the hard part of writing the PEP will be. (Maybe a "human timedelta" type > would be useful here? Eventually this might even be added to the datetime > module.) > I think dateutil already captures a lot of this behavior, but have not personally used it before. > - Nanosecond precision? I'm not against adding this to the datetime > module, as long as backward compatibility is somehow preserved, especially > for pickles (maybe nanoseconds default to zero unless explicitly requested > or specified). > -- > --Guido van Rossum (python.org/~guido) > > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > The PSF Code of Conduct applies to this mailing list: > https://www.python.org/psf/codeofconduct/ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Wed Jul 29 18:32:29 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 12:32:29 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 12:11 PM, Lennart Regebro wrote: > On Wed, Jul 29, 2015 at 5:50 PM, Alexander Belopolsky > wrote: >> What do you see lacking in this solution? > > Btw: I pasted examples of the problems. That you can work around those > in various ways do not change the fact that those problems remain. Do > you have question about those examples? When you insist on hammering nails with a pillow - don't be surprised when you don't get the desired results. And don't blame it on the pillow either - it does what it is designed to do. I am offering you a hammer and show how to use it: Problem: Find local time in New York one astronomical hour after "2014-11-02T01:30-0400". Solution: >>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%z") >>> u = (t+timedelta(hours=1)) >>> u.astimezone().strftime("%Y-%m-%dT%H:%M%z") '2014-11-02T01:30-0500' What do you want to improve here? From tim.peters at gmail.com Wed Jul 29 18:25:12 2015 From: tim.peters at gmail.com (Tim Peters) Date: Wed, 29 Jul 2015 11:25:12 -0500 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: [TIm] >> Nope, that's mistaken on both counts, but it is technical. What I >> said is correct in all respects given the current code. [:Lennart] > That the current code works as designed is not really the issue we > discuss here, though. > > And then you start discussing conversions, which wasn't the issue, it > was arithmetic. Lennart, you replied to a quote from me which was specifically and only talking about timezone conversions. Here it is, the only part you quoted: > But, as the docs have always pointed out, it (specifically .fromutc(), > which is at the base of all relevant calculations) doesn't even try to > handle transitions due to _other_ causes. The only other such cause > I'm aware of is when a timezone's _base_ offset from UTC changes (not > a temporary DST transition, the timezone's "standard" offset changes > permanently (meaning until someone decides to change it again)). Now you chide me with "And then you start discussing conversions, which wasn't the issue, it was arithmetic"?! The quote you were replying to was _entirely_ about conversions, and nothing whatsoever about arithmetic. Silly me - I thought you were asking about DST conversions and base-offset-changing conversions. And just because that was the topic you were commenting on ;-) Here's you. talking about conversion when the base UTC offset changes: > This will be handled in the exact same way as DST changes, and if > this is incorrect, then reasonably, so is the DST handling. > What is "incorrect" here is of course a matter of opinion. That's wholly consistent with the belief that you were staying on the original topic (conversion). Then you continued, I _guess_ talking about arithmetic, because you weren't explicit and it really had nothing to do with the paragraph just ended: > I think it's incorrect because it doesn't agree with reality, you have > claimed that it is correct, in "as per design". You weren't explicit about what "it" and "it's" referred to. I charitably tried to assume you weren't trying to change the current topic (which _was_ conversions, and obviously so)., so replied at length about how arithmetic and conversions were distinct issues. Finally, > But then reasonably that goes for this case as well? The same thing > happens, which is that depending on the transitions direction, you can > either end up in a time that doesn't exist, or one that happens twice. Which seemed to be bouncing back to the original topic. Or not. Since you seem to believe _I_ was changing the topic, my best guess now is that, without saying anything explicit about it, in your _head_ you weren't thinking about conversions at all, but instead about what happens when doing _arithmetic_ at times near timezone transition points. If so, I plead guilty to a failure of telepathy ;-) But the quote you responded to at first wasn't about arithmetic. It was about conversions. In its original context that was dead obvious. But even stripped of context, it still explicitly talks about .fromutc(). A conversion method. Not arithmetic. From regebro at gmail.com Wed Jul 29 18:34:19 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 18:34:19 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 6:23 PM, Alexander Belopolsky wrote: > On Wed, Jul 29, 2015 at 12:08 PM, Lennart Regebro wrote: >>>>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%z") >> ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M%z' >> >> Nope, didn't work. > > Sorry, but it does work for me: > > $ TZ=America/New_York python3 > Python 3.4.3 (default, Jul 20 2015, 12:59:38) > [GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin > Type "help", "copyright", "credits" or "license" for more information. >>>> from datetime import * >>>> t = datetime.strptime("2014-11-02T01:30-0400", "%Y-%m-%dT%H:%M%z") > > which version of Python are you using? Sorry, I thought I was on Python3, but I wasn't. My fault entirely! Anyway, you can't seriously consider that I have to set the TZ environment variable as a viable solution, can you? And in this case the original date and time you have aren't even set to the right timezone. It's set to a fixed offset of UTC-4. In my example I use America/New_York the whole time. //Lennart From guido at python.org Wed Jul 29 18:36:01 2015 From: guido at python.org (Guido van Rossum) Date: Wed, 29 Jul 2015 18:36:01 +0200 Subject: [Datetime-SIG] Timezone database In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 6:31 PM, Felipe Ochoa wrote: > [Branching from The BDFL's take] > > There are a few additional issues which I'm not sure are included in this >> discussion or not: >> - A unified API for accessing an up-to-date timezone database. This has >> been discussed in the past, and we couldn't find a solution that satisfied >> all requirements (the main problem being different platform expectations >> IIRC), but it's probably worth it trying again. > > > The current solution proposed in the PEP is to have platforms > with /usr/share/zoneinfo use that as long as they want. For other platforms > Python would ship with a built-in copy (roughly speaking) of the database. > There would then be separate tzdata-update package on pypi that can be `pip > install`ed to update the timezone database whenever the user feels the need > to do so (because /usr/share/zoneinfo is no longer receiving updates or > because it doesn't exist) > > What are the unsatisfied requirements of this design? > It looks like Windows (where a lot of Python users actually are -- just not those who are most active in Open Source) is left out in the cold here. I'm sure Windows by now has a timezone info database of its own that is kept up-to-date whenever you install Microsoft updates, and Python should use that in preference over a Python-specific database which is only updated when the user updates Python (which may be never). -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From regebro at gmail.com Wed Jul 29 18:41:58 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 18:41:58 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 6:32 PM, Alexander Belopolsky wrote: > When you insist on hammering nails with a pillow - don't be surprised when > you don't get the desired results. And don't blame it on the pillow either - > it does what it is designed to do. All you are saying now, probably completely unintentionally, is that dateutils timezone implementation is useless. > Problem: Find local time in New York one astronomical hour after > "2014-11-02T01:30-0400". That's not the problem. The problem is "I want to add one hour to a time zone aware datetime". The solution with the current implementation is to convert it to UTC, add one hour and convert it back. I think that's a very poor solution. > What do you want to improve here? I think adding one hour to a timezone aware date time should result in a date time that is one hour later. Your solution does not do that, and involves converting between two timezones, one that is irrelevant for the question, and the other that you have to set as an environment variable. I have no idea why you think that is constructive, and therefore I have tried to ignore it, but that just result in you reposting it over and over, so that clearly didn't work. //Lennart From alexander.belopolsky at gmail.com Wed Jul 29 18:43:07 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 12:43:07 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 12:34 PM, Lennart Regebro wrote: > Anyway, you can't seriously consider that I have to set the TZ > environment variable as a viable solution, can you? It worked for most people so far given that the standards bodies are in now rush updating the standards that assume one global timezone per process. Note that python exposes time.tzset() method so that you can switch timzones without restarting the interpreter. However, this problem has nothing to do with the datetime API. If we find a way to access the timezone database by better means than POSIX system calls, we can easily extend astimezone method so that >>> u.astimezone('Australia/Melbourne') works when TZ=America/New_York or anything else. From lrekucki at gmail.com Wed Jul 29 18:45:03 2015 From: lrekucki at gmail.com (=?UTF-8?Q?=C5=81ukasz_Rekucki?=) Date: Wed, 29 Jul 2015 18:45:03 +0200 Subject: [Datetime-SIG] Timezone database In-Reply-To: References: Message-ID: On 29 July 2015 at 18:36, Guido van Rossum wrote: > On Wed, Jul 29, 2015 at 6:31 PM, Felipe Ochoa > wrote: >> >> [Branching from The BDFL's take] >> >>> There are a few additional issues which I'm not sure are included in this >>> discussion or not: >>> - A unified API for accessing an up-to-date timezone database. This has >>> been discussed in the past, and we couldn't find a solution that satisfied >>> all requirements (the main problem being different platform expectations >>> IIRC), but it's probably worth it trying again. >> >> >> The current solution proposed in the PEP is to have platforms with >> /usr/share/zoneinfo use that as long as they want. For other platforms >> Python would ship with a built-in copy (roughly speaking) of the database. >> There would then be separate tzdata-update package on pypi that can be `pip >> install`ed to update the timezone database whenever the user feels the need >> to do so (because /usr/share/zoneinfo is no longer receiving updates or >> because it doesn't exist) >> >> What are the unsatisfied requirements of this design? > > > It looks like Windows (where a lot of Python users actually are -- just not > those who are most active in Open Source) is left out in the cold here. I'm > sure Windows by now has a timezone info database of its own that is kept > up-to-date whenever you install Microsoft updates, and Python should use > that in preference over a Python-specific database which is only updated > when the user updates Python (which may be never). The problem with Windows is that is has its own naming of timezones. There are mapping between the two[1], but then you need to make sure the mapping is up-to-date (which I think doesn't change very often). [1]: http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html -- ?ukasz Rekucki From regebro at gmail.com Wed Jul 29 18:45:42 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 18:45:42 +0200 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 6:43 PM, Alexander Belopolsky wrote: > It worked for most people so far given that the standards bodies are in now rush > updating the standards that assume one global timezone per process. Let me be clear that having only one timezone per process most definitely is not an acceptable solution. //Lennart From alexander.belopolsky at gmail.com Wed Jul 29 18:46:23 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 12:46:23 -0400 Subject: [Datetime-SIG] The BDFL's take In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 12:41 PM, Lennart Regebro wrote: >> Problem: Find local time in New York one astronomical hour after >> "2014-11-02T01:30-0400". > > That's not the problem. The problem is "I want to add one hour to a > time zone aware datetime". I disagree. It is what you say is not a problem. "I want to add one hour to a time zone aware datetime" is a part of a (possibly wrong) solution. From regebro at gmail.com Wed Jul 29 18:49:14 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 18:49:14 +0200 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 6:25 PM, Tim Peters wrote: > Lennart, you replied to a quote from me which was specifically and > only talking about timezone conversions. Here it is, the only part > you quoted: > >> But, as the docs have always pointed out, it (specifically .fromutc(), >> which is at the base of all relevant calculations) doesn't even try to >> handle transitions due to _other_ causes. The only other such cause >> I'm aware of is when a timezone's _base_ offset from UTC changes (not >> a temporary DST transition, the timezone's "standard" offset changes >> permanently (meaning until someone decides to change it again)). Are you saying that conversions between time zones are wrong!? > Silly me - I > thought you were asking about DST conversions A don't view a DST change as a conversion, perhaps that's the communication issue here. > Here's you. talking about conversion when the base UTC offset changes: > >> This will be handled in the exact same way as DST changes, and if >> this is incorrect, then reasonably, so is the DST handling. >> What is "incorrect" here is of course a matter of opinion. No, that's not a conversion, that ooccurs within the same time zone. //Lennart From tim.peters at gmail.com Wed Jul 29 19:00:59 2015 From: tim.peters at gmail.com (Tim Peters) Date: Wed, 29 Jul 2015 12:00:59 -0500 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: Have to hit-and-run here (out of time for this for a while): [Chris Barker] >> Huh? Now I'm really confused. IIUC, the is_dst flag is required in order to >> be able to round-trip between UTC and local_time representations. [Lennart Regebro] > No, that's not necessary. It's necessary to disambiguate between > ambiguous datetimes, but you can, like dateutils implementation, > simply just pick one consistently, and you can round-trip. is_dst remains necessary to distinguish between ambiguous local times, just as Chris states: >> In particular, so the API can support specifying a datetime in a time zone >> that "happens" twice without ambiguity. > Yes, but that has now been declared as not desired. News to me ;-) > We no longer want datetime to be able to do that. Of course we do.; Well, some people do ;-) > That's only a feature you need or even can have if you want to do > real time arithmetic over DST changes. Not so. It can easily (albeit rarely) arise in cases of pure timezone conversions. Conversions have nothing to do with arithmetic. If I convert a time in zone X to a time in zone Y that lands in an ambiguous span in zone Y, without the conversion _also_ setting an is_dst flag in the destination, it's impossible to reliably convert the time in zone Y back to zone X again. Note that it's quite possible the time we started with was not ambiguous in X's zone, so without is_dst to tell us which zone-Y time was intended, the conversion back to zone X may be dead wrong (from X's POV). Note that ambiguities are also possible in timezones where the _base_ ("standard") UTC offset changes over time. The default conversion methods currently ignore such possibilities. There have already been many other messages suggesting that, because of this, "is_dst" may be a poor name for the bit of information required, [and skipping the rest for now because I'm more than out of time now ;-)\ From regebro at gmail.com Wed Jul 29 19:05:41 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 19:05:41 +0200 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 7:00 PM, Tim Peters wrote: > is_dst remains necessary to distinguish between ambiguous local times, > just as Chris states: But with the current implementations, those do not exist. datetime explicitly and intentionally assume that 1 day always is 24 hours. Hence, in the datetime universe, local times can not be ambiguous, > Not so. It can easily (albeit rarely) arise in cases of pure timezone > conversions. Conversions have nothing to do with arithmetic. If I > convert a time in zone X to a time in zone Y that lands in an > ambiguous span in zone Y, without the conversion _also_ setting an > is_dst flag in the destination, it's impossible to reliably convert > the time in zone Y back to zone X again. No, you just consistently pick one of the two times in both conversions to and from and it will roundtrip just fine. //Lennart From regebro at gmail.com Wed Jul 29 19:09:15 2015 From: regebro at gmail.com (Lennart Regebro) Date: Wed, 29 Jul 2015 19:09:15 +0200 Subject: [Datetime-SIG] Actually, I'm out. Message-ID: I spent two half days on this already, and I don't believe that people don't understand the issue by now, since I've repeated it five million times. And repeating it over and over just makes me depressed. I'm out. I'll solve this issue my own way, by myself. Regards Lennart From chris.barker at noaa.gov Wed Jul 29 19:21:20 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Wed, 29 Jul 2015 10:21:20 -0700 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 10:05 AM, Lennart Regebro wrote: > On Wed, Jul 29, 2015 at 7:00 PM, Tim Peters wrote: > > is_dst remains necessary to distinguish between ambiguous local times, > > just as Chris states: > > But with the current implementations, those do not exist. datetime > explicitly and intentionally assume that 1 day always is 24 hours. > Hence, in the datetime universe, local times can not be ambiguous, of course they can (and we really ned antoher word -- again, using "day" to mean two totally different things). but anyway -- sorry I used teh term "round trip" that isn't quite what I meant. What I meant was: "know what location on the time continuum a particular calendar time represents" (note that this is more or less convert to UTC) that can be ambiguous in a DST transition without an is_dst flag. So if you want to handle time zones with DST (and go both ways), you need an is_dst flag. and that has nothign to do with artihmetic or calendar operations -- but yes, it's is about conversion. But really does anyone really want to do the ugliness of trying to do time calculation completely in a time-zone, discontinuous, ugly as hell encoding???? I think not -- which mean you can't do squat without converting to-from a clean representation i.e. UTC. So I say step one is to fully support time zones and the ability to do "real" time arithmetic and conversion to-from UTC. Then it's another task to support calendar operations. Or does something think we really need to be able to compute "this time tomorrow", but not "24 hours from now"? -Chris > > > Not so. It can easily (albeit rarely) arise in cases of pure timezone > > conversions. Conversions have nothing to do with arithmetic. If I > > convert a time in zone X to a time in zone Y that lands in an > > ambiguous span in zone Y, without the conversion _also_ setting an > > is_dst flag in the destination, it's impossible to reliably convert > > the time in zone Y back to zone X again. > > No, you just consistently pick one of the two times in both > conversions to and from and it will roundtrip just fine. > > //Lennart > -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Wed Jul 29 19:23:45 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 13:23:45 -0400 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 1:05 PM, Lennart Regebro wrote: >> Not so. It can easily (albeit rarely) arise in cases of pure timezone >> conversions. Conversions have nothing to do with arithmetic. If I >> convert a time in zone X to a time in zone Y that lands in an >> ambiguous span in zone Y, without the conversion _also_ setting an >> is_dst flag in the destination, it's impossible to reliably convert >> the time in zone Y back to zone X again. > > No, you just consistently pick one of the two times in both > conversions to and from and it will roundtrip just fine. This may work when both conversions have an ambiguity, but in the real life this does not happen. Assume the time difference between X and Y in 12 hours, and naturally Y does not have a DST transition in the middle of the day. Let's start the conversion: "01:30 X/DST" -> "13:30 Y" -> "01:30 X/DST" So far so good. We ignore DST in the first transition, get unambiguous time in the Y zone and get the original X time in the second transition. However, we we start with "01:30 X/STD", we must get "01:30 X/STD" -> "13:30 Y" by the first rule and have no choice but follow with "13:30 Y" -> "01:30 X/DST" and the round-trip mutates STD to DST. The only way to solve it is to take into account the "STD" marker in the first transition and map "01:30 X/STD" -> "14:30 Y" -> "01:30 X/STD", but you cannot take into account the "STD" marker if it is not there to begin with. From guido at python.org Wed Jul 29 19:27:25 2015 From: guido at python.org (Guido van Rossum) Date: Wed, 29 Jul 2015 19:27:25 +0200 Subject: [Datetime-SIG] Actually, I'm out. In-Reply-To: References: Message-ID: Surely some people understand some of the issues. I've seen a lot of communication failures, many exacerbated by people trying to post quickly (hoping against reason to stay on top of the thread :-). I've sent Lennart a message off-line asking him to reconsider. In the mean time maybe we can all take a breath and sleep on things. I believe there is a way out, but we first need to stop the bleeding. On Wed, Jul 29, 2015 at 7:09 PM, Lennart Regebro wrote: > I spent two half days on this already, and I don't believe that people > don't understand the issue by now, since I've repeated it five million > times. And repeating it over and over just makes me depressed. > > I'm out. > > I'll solve this issue my own way, by myself. > > Regards > Lennart > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > The PSF Code of Conduct applies to this mailing list: > https://www.python.org/psf/codeofconduct/ > -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From lrekucki at gmail.com Wed Jul 29 19:34:36 2015 From: lrekucki at gmail.com (=?UTF-8?Q?=C5=81ukasz_Rekucki?=) Date: Wed, 29 Jul 2015 19:34:36 +0200 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On 29 July 2015 at 19:23, Alexander Belopolsky wrote: > On Wed, Jul 29, 2015 at 1:05 PM, Lennart Regebro wrote: >>> Not so. It can easily (albeit rarely) arise in cases of pure timezone >>> conversions. Conversions have nothing to do with arithmetic. If I >>> convert a time in zone X to a time in zone Y that lands in an >>> ambiguous span in zone Y, without the conversion _also_ setting an >>> is_dst flag in the destination, it's impossible to reliably convert >>> the time in zone Y back to zone X again. >> >> No, you just consistently pick one of the two times in both >> conversions to and from and it will roundtrip just fine. > > This may work when both conversions have an ambiguity, but in the real > life this does not happen. > > Assume the time difference between X and Y in 12 hours, and naturally > Y does not have a DST transition in the middle of the day. > > Let's start the conversion: > > "01:30 X/DST" -> "13:30 Y" -> "01:30 X/DST" > > So far so good. We ignore DST in the first transition, get > unambiguous time in the Y zone and get the original X time in the > second transition. > > However, we we start with "01:30 X/STD", we must get > > "01:30 X/STD" -> "13:30 Y" I think I'm lost at this point. Assume Y = UTC (fulfills all your assumptions for some -12 zone). Why would 01:30 X/DST and 01:30 X/STD convert to the same point in time ? -- ?ukasz Rekucki From alexander.belopolsky at gmail.com Wed Jul 29 19:37:52 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 13:37:52 -0400 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 1:21 PM, Chris Barker wrote: > But really does anyone really want to do the ugliness of trying to do time > calculation completely in a time-zone, discontinuous, ugly as hell > encoding???? Yes, if both the input and the output of your program contain temporal data in the same timezone. For example, "Find a day with the largest trading volume on the New York Stock Exchange in 2014." The exchange publishes its data in New York local time and you know that trading hours are from 09:30 to 16:00 with a few exceptions that are again published in the local time. The database is huge, so you select the data by day, split it into chunks by 5 minutes, add up the volumes for each day and find maximum. Easy. No need to know when the DST transitions were in New York in 2014. Got the same database from Paris? No need to change your code. Now try to do the same in UTC. I think my program will finish before you stop arguing what "a day" is. From felipe.nospam.ochoa at gmail.com Wed Jul 29 19:39:40 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Wed, 29 Jul 2015 13:39:40 -0400 Subject: [Datetime-SIG] Actually, I'm out. In-Reply-To: References: Message-ID: > > maybe we can all take a breath and sleep on things. > This may be a bug in the timezone conversion, but over here on America/New_York, it's not even 2pm :-) Are you proposing adding a siesta module? -------------- next part -------------- An HTML attachment was scrubbed... URL: From lrekucki at gmail.com Wed Jul 29 19:42:03 2015 From: lrekucki at gmail.com (=?UTF-8?Q?=C5=81ukasz_Rekucki?=) Date: Wed, 29 Jul 2015 19:42:03 +0200 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On 29 July 2015 at 19:37, Alexander Belopolsky wrote: > On Wed, Jul 29, 2015 at 1:21 PM, Chris Barker wrote: >> But really does anyone really want to do the ugliness of trying to do time >> calculation completely in a time-zone, discontinuous, ugly as hell >> encoding???? > > Yes, if both the input and the output of your program contain temporal > data in the same timezone. > > For example, "Find a day with the largest trading volume on the New > York Stock Exchange in 2014." > > The exchange publishes its data in New York local time and you know > that trading hours are from 09:30 to 16:00 with a few exceptions that > are again published in the local time. The database is huge, so you > select the data by day, split it into chunks by 5 minutes, add up the > volumes for each day > and find maximum. Easy. No need to know when the DST transitions > were in New York in 2014. Got the same database from Paris? No need > to change your code. Now try to do the same in UTC. I think my > program will finish before you stop arguing what "a day" is. That's because your program does not need to be time zone aware *at all* (it works on Local Datetime). Everyone already agrees that this work. That doesn't mean that there are no other use cases. -- ?ukasz Rekucki From alexander.belopolsky at gmail.com Wed Jul 29 19:42:09 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 13:42:09 -0400 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 1:34 PM, ?ukasz Rekucki wrote: >> However, we we start with "01:30 X/STD", we must get >> >> "01:30 X/STD" -> "13:30 Y" > > I think I'm lost at this point. Assume Y = UTC (fulfills all your > assumptions for some -12 zone). Why would 01:30 X/DST and 01:30 X/STD > convert to the same point in time ? Because you decided to ignore the is_dst flag. There is currently no way to distinguish between one naive time(1, 30) instance and another. From tim.peters at gmail.com Wed Jul 29 19:47:08 2015 From: tim.peters at gmail.com (Tim Peters) Date: Wed, 29 Jul 2015 12:47:08 -0500 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: Message-ID: [Lennart] > Are you saying that conversions between time zones are wrong!? I already explained everything conversions are known to do correctly, known not to do correctly, and the existing mechanisms available if anyone cares enough to repair the latter cases. >> Silly me - I thought you were asking about DST conversions > A don't view a DST change as a conversion, perhaps that's the > communication issue here. Perhaps instead of typing the suggestive-but-literal-nonsense "about DST conversions" before I should have typed something like "about the complications DST transitions can create for timezone conversions" (which was part of the topic of the message at the start of all this). DST is relevant to conversions when the source and/or destination times are "close enough" to DST transition points in their respective time zones. The current implementation mimics local clock behavior in the _destination_ zone in such cases. The current implementation has no way to know which time in the _source_ zone was intended in cases of times that are ambiguous in the source zone. >> Here's you. talking about conversion when the base UTC offset changes: >>> This will be handled in the exact same way as DST changes, and if >>> this is incorrect, then reasonably, so is the DST handling. >>> What is "incorrect" here is of course a matter of opinion. > No, that's not a conversion, that ooccurs within the same time zone. I agree, See above. I used the literally senseless "DST conversion" as a shorthand for a wall of text I didn't think should still be necessary ;-) As you said, exactly the same kinds of "missing time" and "repeated time" irregularities can occur regardless of the cause of the irregularities. It seems clear now you had only arithmetic in mind, while I had only conversions in mind, but the irregularities are potential issues for any way whatsoever of producing a datetime (whether as the result of arithmetic, the result of a conversion operation, the result of parsing a string, the result of combining separate date and time objects into a single datetime object, ...). All possible causes of irregularities (including DST transitions) are potential headaches for all possible ways (including conversions & arithmetic) of creating a datetime object. Local DST transitions and local transitions due to the base UTC offset changing create exactly the same kinds of headaches. In the current implementation of conversions, irregularities in the local clock are reliably tracked in the destination zone only when the irregularity is caused by a destination zone DST transition (see earlier msg for details about why that's the case). And before anyone feels compelled to point it out for the 10 thousandth time ;-), yes, single-zone arithmetic was intentionally designed to ignore all possible sources of irregularities. From alexander.belopolsky at gmail.com Wed Jul 29 19:49:51 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 13:49:51 -0400 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 1:42 PM, ?ukasz Rekucki wrote: > That's because your program does not need to be time zone aware *at > all* (it works on Local Datetime). Everyone already agrees that this > work. Almost. Suppose, instead of a day, I am looking for an hour with the highest volume and I work for a French bank. When I report my results, I want to include the timezone information so that there is no confusion. There is currently no straightforward way to start with a naive datetime(2014, 11, 3, 12, 0) and produce "2014-11-03T12:00-0500 EST" From alexander.belopolsky at gmail.com Wed Jul 29 20:00:55 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 14:00:55 -0400 Subject: [Datetime-SIG] [Python-Dev] Status on PEP-431 Timezones In-Reply-To: <20150729150406.B9653250EA9@webabinitio.net> References: <20150727141316.GA25179@ando.pearwood.info> <55B64C61.20701@mrabarnett.plus.com> <874mkoengd.fsf@uwakimon.sk.tsukuba.ac.jp> <20150729150406.B9653250EA9@webabinitio.net> Message-ID: On Wed, Jul 29, 2015 at 11:04 AM, R. David Murray wrote: > What *I* want aware datetimes to do is give me the correct timezone > label when I format them, given the date and time information they hold. > The naive arithmetic is perfect, the conversion between timezones is > fine, the only thing missing from my point of view is a timezone > database such that if I tell a datetime it is in zone X, it will print > the correct offset and/or timezone label when I format it as a string. +1 See https://mail.python.org/pipermail/datetime-sig/2015-July/000071.html for an essentially the same use case. Redirecting to datetime-sig. From tim.peters at gmail.com Wed Jul 29 20:26:57 2015 From: tim.peters at gmail.com (Tim Peters) Date: Wed, 29 Jul 2015 13:26:57 -0500 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: [Tim] >> is_dst remains necessary to distinguish between ambiguous local times, >> just as Chris states: [Lennart] > But with the current implementations, those do not exist. Of course they exist. That's a plain fact about how most timezones work. > datetime explicitly and intentionally assume that 1 day always is 24 hours. The "naive time" model assumes that, but not everything in datetime follows the "naive time" model. For example, just a short time ago I explained to you, at considerable length, that zone conversions are (intentionally) viewed as operations _outside_ the "naive time" model. Like manually changing a mechanical wrist watch when DST changes. The watch follows "naive time" before and after you change it, not _while_ you're changing it. > Hence, in the datetime universe, local times can not be ambiguous, Repeating a counterfactual won't increase its truth value ;-)( Ambiguous times exist on a mechanical wrist watch too. >> Not so. It can easily (albeit rarely) arise in cases of pure timezone >> conversions. Conversions have nothing to do with arithmetic. If I >> convert a time in zone X to a time in zone Y that lands in an >> ambiguous span in zone Y, without the conversion _also_ setting an >> is_dst flag in the destination, it's impossible to reliably convert >> the time in zone Y back to zone X again. > No, you just consistently pick one of the two times in both > conversions to and from and it will roundtrip just fine. Nope, not even if we insist that X can only be UTC. For example, when US Eastern Daylight ends, 5:30 and 6:30 UTC _both_ convert to 1:30 EST. But 1:30 EST can convert back to only one of those. If you "consistently pick", say, the earliest, then 5:30 UTC is what you get. Then the result of round-tripping 6:30 UTC to-and-back-from US Eastern is dead wrong (5:30 UTC is not 6:30 UTC, not even in "naive time" ;-) ). If you "consistently pick" 6:30 UTC instead, then round-tripping starting from 5:30 UTC is dead wrong. But I'm unclear why an example should be necessary. "Ambiguous time" _means_ there's a time spelling in one zone that has _at least_ two spellings in another zone. In any such case, it should be obvious on the face of it that round-tripping starting _from_ the zone with more than one spelling can't possibly always work, unless additional info is recorded to say _which_ spelling we started with. If there's also _at most_ two equivalent spellings, then "a flag" (1 more bit) is both necessary and sufficient. From skip.montanaro at gmail.com Wed Jul 29 20:41:48 2015 From: skip.montanaro at gmail.com (Skip Montanaro) Date: Wed, 29 Jul 2015 13:41:48 -0500 Subject: [Datetime-SIG] Datetime - my issues Message-ID: On Wed, Jul 29, 2015 at 12:49 PM, Alexander Belopolsky wrote: > There is currently no straightforward way to start with a naive > datetime(2014, 11, 3, 12, 0) > and produce > "2014-11-03T12:00-0500 EST" I'm almost certainly not answering the question you're inferring (why is there no straightforward way ...), so I've changed the subject. I will describe my modest experience in this area. They are really only as a user of datetime and pytz. I've made almost no attempt to expand on the existing APIs, just one or two helper functions. (Caveat: I still live in a Python 2.x world.) I perform naive-to-aware conversions routinely in my code (also in the financial services space, where we need to deal with exchange times in North American, European, Australian and Asian timezones). Every once in a blue moon I need a naive timezone (possibly normalized to a different time zone first) from a tz-aware one, but that is a rare occurrence. I think as time goes on we will (or at least should) see less and less reliance on naive datetimes. Fortunately, I and my systems are generally fast asleep at those ambiguous times Tim and Lennart were discussing. For historical and interface reasons, the system I work with uses a mixture of epoch seconds, naive datetime objects, and tz-aware datetime objects, depending on the original source of the time data. Going forward, I hope to reduce the reliance of the sytem on first two time representations, and increase use of tz-aware datetime objects. In the past year I've had the same sort of epiphany regarding timezones as I had when I started drinking the Unicode kool aid 15 or so years ago. (And then I went to work for a company which still thinks the entire world runs on ASCII and has a bunch of C++ code to prove it...) Despite having to convert naive (and implicitly Chicago-based) datetime objects into tz-aware objects, I still find myself looking back at existing code to perform the conversions, as (for whatever reason) the method names aren't terribly suggestive to me, and I sometimes get the names wrong. The platform I use provides some stock objects: >>> LOCAL_TZ >>> EPOCH datetime.datetime(1969, 12, 31, 18, 0) Despite not having a LOCAL_EPOCH object by default, it's easy enough to create: >>> LOCAL_EPOCH = LOCAL_TZ.localize(EPOCH) >>> LOCAL_EPOCH datetime.datetime(1969, 12, 31, 18, 0, tzinfo=) Still, when it comes time for me to use the LOCAL_TZ object, I find the method names "localize" (generate a tz-aware datetime object from a naive one) and "normalize" (convert between timezones) unintuitive. Getting the string you want (or very close to it, why would you want HHMM offset and timezone name?) is similarly straightforward, using a tz-aware datetime object: >>> now = Clock.local_datetime() >>> now datetime.datetime(2015, 7, 29, 13, 15, 23, 650153, tzinfo=) >>> now.isoformat() '2015-07-29T13:15:23.650153-05:00' I do find the slightly slavish adherence to the old Unix time(3) function implication that "times don't have fractions of a second" a bit clumsy: >>> now datetime.datetime(2015, 7, 29, 13, 15, 23, 650153, tzinfo=) >>> now.timetuple() time.struct_time(tm_year=2015, tm_mon=7, tm_mday=29, tm_hour=13, tm_min=15, tm_sec=23, tm_wday=2, tm_yday=210, tm_isdst=1) What happened to my microseconds??? That forces me to write little helper functions like this: def to_timestamp(dt): """Convert a datetime object into seconds since the Unix epoch.""" return time.mktime(dt.timetuple()) + dt.microsecond/1e6 Going forward, I think it would be cleaner if datetime.timetuple() returned a tuple with microseconds, and the relevant old-style functions in the time module were smart enough to know when to ignore them. I also occasionally want timedelta objects in seconds, so have this: def as_seconds(delta): """Convert a timedelta object into seconds (float).""" return delta.days*24*60*60 + delta.seconds + delta.microseconds/1e6 Despite the overflow possibilities (I doubt I will still be working when that happens), I think it would be nice to have a few convenience functions like this, in the to-be-named-later datetime utils module. I'm less thrilled with some heuristic function which allows you to take a datetime object and add or subtract some number of months, as I can't see a good way to get that right. Finally, at some point I read somewhere that using dtobject.astimezone(newzone) was preferable to using zone.normalize(dtobject). My code is now littered with both spellings, but I have no recollection of why one would be preferred over the other (except that pytz is clearly not part of the standard library). Corollary: It seems to me like the astimezone call ought to work: >>> now = datetime.datetime.now() autoloading datetime >>> import pytz >>> chi = pytz.timezone("America/Chicago") >>> now.astimezone(chi) ValueError astimezone() cannot be applied to a naive datetime [||1] >>> chi.localize(now) datetime.datetime(2015, 7, 29, 13, 39, 23, 139107, tzinfo=) but maybe that's just a case of explicit-is-better-than-implicit... Skip From chris.barker at noaa.gov Wed Jul 29 21:39:58 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Wed, 29 Jul 2015 12:39:58 -0700 Subject: [Datetime-SIG] What's are the issues? In-Reply-To: References: <3572339734014533140@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 10:42 AM, ?ukasz Rekucki wrote: > On 29 July 2015 at 19:37, Alexander Belopolsky > wrote: > > For example, "Find a day with the largest trading volume on the New > > York Stock Exchange in 2014." > > > The exchange publishes its data in New York local time and you know > > that trading hours are from 09:30 to 16:00 with a few exceptions that > > are again published in the local time. > > The database is huge, so you > > select the data by day, split it into chunks by 5 minutes, add up the > > volumes for each day > > and find maximum. Easy. No need to know when the DST transitions > > were in New York in 2014. Got the same database from Paris? No need > > to change your code. > That's because your program does not need to be time zone aware *at > all* (it works on Local Datetime). Everyone already agrees that this > work. exactly -- this is where and why naive datetimes are, in fact very, very useful. And see Skip's message -- I guess I haven't drunk the cool aid, but I agree that going full-on timezone aware would make this kind of thing harder. For me, I think of naive datetimes as meaning "I know all the data i"m working with right now is in the same timezone (and I don't care about DST)" So no -- this is not an example of wanting to do time arithmetic in the messy, DST aware, non-contiguous realm... But I don't think anyone is proposing removing naive datetimes anyway. Now try to do the same in UTC. I think my > > program will finish before you stop arguing what "a day" is. > actually -- it would hardly make it any harder, if we had "proper" time zone support: You'd load your data into datetime objects, letting it know that it's in the US Eastern Time zone. then do all the same things -- datetime would deal with it for you. For Paris, you *would* have to tell your script what timezone it's in. But again, if that isn't in the dataset, then naive is what you want. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From felipe.nospam.ochoa at gmail.com Wed Jul 29 22:56:57 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Wed, 29 Jul 2015 16:56:57 -0400 Subject: [Datetime-SIG] Timezone database In-Reply-To: References: Message-ID: > > It looks like Windows (where a lot of Python users actually are -- just not >> those who are most active in Open Source) is left out in the cold here. > > sure Windows by now has a timezone info database of its own that is kept >> up-to-date whenever you install Microsoft updates, and Python should use >> that in preference over a Python-specific database which is only updated >> when the user updates Python (which may be never). > > Can't we somehow hook into the Java auto-updater? *wink* The problem with Windows is that is has its own naming of timezones. > There are mapping between the two[1], but then you need to make sure > the mapping is up-to-date (which I think doesn't change very often). > Thanks for the pointer to the mapping. I also found the proposal document helpful in understanding the differences between Windows and Olson time zones. One design decision that I think has been made but is worth confirming: Do we want users to specify time zones using the Olson names? I think it's evident why we have to use consistent names across platforms, but it might be worth using the 'official' unicode timezone identifiers , which are guaranteed to be stable. -------------- next part -------------- An HTML attachment was scrubbed... URL: From felipe.nospam.ochoa at gmail.com Wed Jul 29 23:31:20 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Wed, 29 Jul 2015 17:31:20 -0400 Subject: [Datetime-SIG] Clearing up terminology Message-ID: Jon Skeet has created what I think would be a very useful guide for people on this list to read. He provides some great (precisely defined) terminology we should adopt to move away from "naive" and "aware." Hopefully this will ease some of the communication difficulties we're experiencing. http://nodatime.org/1.2.x/userguide/concepts.html TL;DR: here's a glossary of terms: * local vs global: "The key difference is that people all around the world will agree on a global value simultaneously, whereas they may all see different local values for the same global value, due to time zones." Local values are what Guido has labeled "naive" -- in the sense that they don't have a datetime. * Instant: a point on the non-relativistic time line. Isomorphic to "the number of seconds since the unix epoch". It doesn't make sense to talk about time zones with instants * Calendar system: a means of breaking up the time line into "units such as years, months, days, hours, minutes, and so on" * Time zone: "a mapping from UTC instants to offsets" * Offset: "simply the difference between UTC and local time." * ZonedDatetime: An instant + a time zone * OffsetDatetime: An instant + an offset (which is not the same as a ZonedDatetime!) * LocalDatetime: A date/time in the usual "naive" sense: a combination of year, month, day, hour, minute, second, millisecond (soon to be nano?) * Duration: The difference between two instants. "A fixed number of ticks". What has also been called "stopwatch deltas". Skeet says, "it's the same length of time wherever it's applied. Duration is used for arithmetic on Instant and DateTime values." * Period: "a set of values associated with different calendar-based periods: years, months, weeks, days, hours, minutes and so on. Some of these periods represent different lengths of time depending on what they're applied to." -------------- next part -------------- An HTML attachment was scrubbed... URL: From lrekucki at gmail.com Thu Jul 30 00:23:32 2015 From: lrekucki at gmail.com (=?UTF-8?Q?=C5=81ukasz_Rekucki?=) Date: Thu, 30 Jul 2015 00:23:32 +0200 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: On 29 July 2015 at 23:31, Felipe Ochoa wrote: > Jon Skeet has created what I think would be a very useful guide for people > on this list to read. He provides some great (precisely defined) terminology > we should adopt to move away from "naive" and "aware." Hopefully this will > ease some of the communication difficulties we're experiencing. > > http://nodatime.org/1.2.x/userguide/concepts.html > > > > TL;DR: here's a glossary of terms: > > * local vs global: "The key difference is that people all around the world > will agree on a global value simultaneously, whereas they may all see > different local values for the same global value, due to time zones." Local > values are what Guido has labeled "naive" -- in the sense that they don't > have a datetime. > > * Instant: a point on the non-relativistic time line. Isomorphic to "the > number of seconds since the unix epoch". It doesn't make sense to talk about > time zones with instants > > * Calendar system: a means of breaking up the time line into "units such as > years, months, days, hours, minutes, and so on" > > * Time zone: "a mapping from UTC instants to offsets" > > * Offset: "simply the difference between UTC and local time." > > * ZonedDatetime: An instant + a time zone > > * OffsetDatetime: An instant + an offset (which is not the same as a > ZonedDatetime!) > > * LocalDatetime: A date/time in the usual "naive" sense: a combination of > year, month, day, hour, minute, second, millisecond (soon to be nano?) > > * Duration: The difference between two instants. "A fixed number of ticks". > What has also been called "stopwatch deltas". Skeet says, "it's the same > length of time wherever it's applied. Duration is used for arithmetic on > Instant and DateTime values." > > * Period: "a set of values associated with different calendar-based periods: > years, months, weeks, days, hours, minutes and so on. Some of these periods > represent different lengths of time depending on what they're applied to." > Just for the record, NodaTime is a C# port of JodaTime[1] which was the base for "java.time" module I mentioned earlier in the python-dev discussion, so the shared terminology is not a coicidence ;) It's worth noting that, in this libraries, adding a "Duration" to a "ZonedDateTime" always moves it on the timeline by a fixed amount (Noda time seems to call it "time line arithmetic"). This is what PEP-431 advertises for, but which was considered against the design of datetime. [1]: http://www.joda.org/joda-time/ [2]: http://nodatime.org/1.3.x/userguide/arithmetic.html -- ?ukasz Rekucki From tritium-list at sdamon.com Thu Jul 30 00:29:34 2015 From: tritium-list at sdamon.com (Alexander Walters) Date: Wed, 29 Jul 2015 18:29:34 -0400 Subject: [Datetime-SIG] Timezone database In-Reply-To: References: Message-ID: <55B953CE.3010006@sdamon.com> For reference, the windows timezone database has been pretty well documented for at least 8 years, and Microsoft has been good about updating it (fanatical even, but that's an anecdote for another day). As for the issue of the MS database using different names than Olsan... I don't see much value in trying to match the names across platforms, or at least, not much value in blocking the functionality for that reason; add the functionality and see what pops up on pypi that solves the naming issue. http://blogs.msdn.com/b/bclteam/archive/2007/06/07/exploring-windows-time-zones-with-system-timezoneinfo-josh-free.aspx From ischwabacher at wisc.edu Thu Jul 30 00:04:28 2015 From: ischwabacher at wisc.edu (ISAAC J SCHWABACHER) Date: Wed, 29 Jul 2015 22:04:28 +0000 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: For perspective, here's what we *could* have been dealing with if Guido and Tim had been less Dutch: http://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html (My favorite snippet so far: I don't know about you, but this sort of thing gives me the semantic heebie-jeebies. It's like having a "number" type which has a sequence of digits - but you have to ask another property whether those digits are hex or decimal, and the answer can sometimes be "Well, what do you think?" ) ijs ________________________________ From: Datetime-SIG on behalf of Felipe Ochoa Sent: Wednesday, July 29, 2015 16:31 To: datetime-sig Subject: [Datetime-SIG] Clearing up terminology Jon Skeet has created what I think would be a very useful guide for people on this list to read. He provides some great (precisely defined) terminology we should adopt to move away from "naive" and "aware." Hopefully this will ease some of the communication difficulties we're experiencing. http://nodatime.org/1.2.x/userguide/concepts.html TL;DR: here's a glossary of terms: * local vs global: "The key difference is that people all around the world will agree on a global value simultaneously, whereas they may all see different local values for the same global value, due to time zones." Local values are what Guido has labeled "naive" -- in the sense that they don't have a datetime. * Instant: a point on the non-relativistic time line. Isomorphic to "the number of seconds since the unix epoch". It doesn't make sense to talk about time zones with instants * Calendar system: a means of breaking up the time line into "units such as years, months, days, hours, minutes, and so on" * Time zone: "a mapping from UTC instants to offsets" * Offset: "simply the difference between UTC and local time." * ZonedDatetime: An instant + a time zone * OffsetDatetime: An instant + an offset (which is not the same as a ZonedDatetime!) * LocalDatetime: A date/time in the usual "naive" sense: a combination of year, month, day, hour, minute, second, millisecond (soon to be nano?) * Duration: The difference between two instants. "A fixed number of ticks". What has also been called "stopwatch deltas". Skeet says, "it's the same length of time wherever it's applied. Duration is used for arithmetic on Instant and DateTime values." * Period: "a set of values associated with different calendar-based periods: years, months, weeks, days, hours, minutes and so on. Some of these periods represent different lengths of time depending on what they're applied to." -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Thu Jul 30 02:14:43 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Wed, 29 Jul 2015 17:14:43 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 2:31 PM, Felipe Ochoa wrote: > Jon Skeet has created what I think would be a very useful guide for people > on this list to read. > > http://nodatime.org/1.2.x/userguide/concepts.html > > > > TL;DR: here's a glossary of terms: > YES! thank you! I'm not sure I like all the choices here, but it seems complete and makes the distinctions that need to be made. Please let's all start using these terms. A few comments. > * local vs global: "The key difference is that people all around the world > will agree on a global value simultaneously, whereas they may all see > different local values for the same global value, due to time zones." Local > values are what Guido has labeled "naive" -- in the sense that they don't > have a datetime. > Is this a typo? should be "don't have a time zone"? By the way, that means" can't map to UTC, which, by extension, means, "can't map to any other timezone" * Instant: a point on the non-relativistic time line. Isomorphic to "the > number of seconds since the unix epoch". It doesn't make sense to talk > about time zones with instants > > * Calendar system: a means of breaking up the time line into "units such as > years, months, days, hours, minutes, and so on" > > * Time zone: "a mapping from UTC instants to offsets" > note that the actual mapping may (does) change over history, and has odd things like DST. > * Offset: "simply the difference between UTC and local time." > > * ZonedDatetime: An instant + a time zone > > * OffsetDatetime: An instant + an offset (which is not the same as a > ZonedDatetime!) > > * LocalDatetime: A date/time in the usual "naive" sense: a combination of > year, month, day, hour, minute, second, millisecond (soon to be nano?) > > * Duration: The difference between two instants. "A fixed number of > ticks". What has also been called "stopwatch deltas". Skeet says, "it's the > same length of time wherever it's applied. Duration is used for arithmetic > on Instant and DateTime values." > > * Period: "a set of values associated with different calendar-based > periods: years, months, weeks, days, hours, minutes and so on. Some of > these periods represent different lengths of time depending on what they're > applied to." > OK -- so, as I read it, the PEP calls for adding pre-defined ?Time Zone objects -- this is a great idea, sorely needed, despite the maintenance headache. It also calls for adding an is_dst flag,so that datetime can completely support unambiguous transformations both ways to-from UTC. This seems like an obviously good idea to me, aside from potential implementation difficulty and I'm not sure if there are backward compatibility issues. So is there any more to be hashed out in the PEP (it seem where to get the time zone data on Windows is one unresolved issue). Then there seem to be the big hang-up: people want a way to define Periods (as defined above) and want to be able to do datetime math with them. I"m still really confused as to why folks seemed to think "time zone aware" somehow meant using Peiods rather than Durations for arithmetic, but there you go. Clearly this is very useful thing to have, but it's NEW feature, and not covered in the PEP. So -- if someone want to go forward with this, we probably need a new PEP. In any case, I think that adding the timezone stuff in the current PEP is a great step forward, and we shouldn't hang that up because we are waiting to hash out yet more functionality. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Thu Jul 30 02:27:03 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 20:27:03 -0400 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 5:31 PM, Felipe Ochoa wrote: > * Time zone: "a mapping from UTC instants to offsets" > > * Offset: "simply the difference between UTC and local time." > > * ZonedDatetime: An instant + a time zone > > * OffsetDatetime: An instant + an offset (which is not the same as a > ZonedDatetime!) > > * LocalDatetime: A date/time in the usual "naive" sense: a combination of > year, month, day, hour, minute, second, millisecond (soon to be nano?) Given this terminology and the following UNIX date utility invocation, $ TZ=Australia/Melbourne date +"%c%z" Thu 30 Jul 2015 10:21:18 AM EST+1000 what is (a) Australia/Melbourne, (b) EST? From chris.barker at noaa.gov Thu Jul 30 02:31:03 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Wed, 29 Jul 2015 17:31:03 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: Sorry this is old, but: Chris Barker chris.barker at noaa.gov: > > [that a day is always 24 hours] it's not an assumption, it's a > definition. > > Right, but that's like defining Pi to be three. It's not in accordance > to reality, and therefore it causes a lot of problems. No it's not -- not at all. "day" has two definitions, one is 24 hours, and one is incrementing the date on a calendar (or something like that). Both definitions are equally valid, we jsut need to be clear about which one we are using. period. what I suppose is less clear is which definition is being used by the timedetla object. I argue that the 24 hr definition is what is used there, because, well, that's exactly how it is used internally: In [3]: datetime.timedelta(days=1) Out[3]: datetime.timedelta(1) In [4]: datetime.timedelta(seconds=24*60*60) Out[4]: datetime.timedelta(1) Perhaps the original intent was that "days" means calendar days, and for naive datetimes, it turns out to be the same thing, but that is not what the implementation does, and given that it supports seconds and microseconds, but not months or years, the API is pretty clearly designed for timespans, not calendar definitions. But maybe this will all get cleared up with the Glossary Recently posted. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Thu Jul 30 02:34:49 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Wed, 29 Jul 2015 17:34:49 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 5:27 PM, Alexander Belopolsky < alexander.belopolsky at gmail.com> wrote: > Offset: "simply the difference between UTC and local time. > * Time zone: "a mapping from UTC instants to offsets" > > Given this terminology and the following UNIX date utility invocation, > > $ TZ=Australia/Melbourne date +"%c%z" > Thu 30 Jul 2015 10:21:18 AM EST+1000 > > what is (a) Australia/Melbourne, (b) EST? > Ah yes, great fun -- what the heck do you call them? I would say "Australia/Melbourne" is a TimeZone. EST is a offset -- "Eastern Standard Time" -- i.e. an offset of 5 hours from UTC, and "Standard Time", so does not change with DST rules, so not a full TimeZone. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Thu Jul 30 02:55:28 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 20:55:28 -0400 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: On Wed, Jul 29, 2015 at 8:34 PM, Chris Barker wrote: >> $ TZ=Australia/Melbourne date +"%c%z" >> Thu 30 Jul 2015 10:21:18 AM EST+1000 >> >> what is (a) Australia/Melbourne, (b) EST? > > > Ah yes, great fun -- what the heck do you call them? > > I would say "Australia/Melbourne" is a TimeZone. > > EST is a offset -- "Eastern Standard Time" -- i.e. an offset of 5 hours from > UTC, and "Standard Time", so does not change with DST rules, so not a full > TimeZone. Fair enough: "EST is a offset", what is +1000 then? Let's not keep the suspense. I ran the date command above on a Linux machine. On a Mac similar command makes more sense: $ TZ=Australia/Melbourne date +"%c %Z%z" Thu Jul 30 10:46:45 2015 AEST+1000 The point, however is that "EST" does not mean -0500 for everyone. From chris.barker at noaa.gov Thu Jul 30 03:16:10 2015 From: chris.barker at noaa.gov (Chris Barker - NOAA Federal) Date: Wed, 29 Jul 2015 18:16:10 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: <-6120061269507718094@unknownmsgid> > Fair enough: "EST is a offset", what is +1000 then? Also an offset -- but one without a name -- In the general case, a given offset may have more than one name. EST is one name for a +5 offset. (Or is it minus 5?) but there are other times on other timezones where the offset is 5. > $ TZ=Australia/Melbourne date +"%c %Z%z" > Thu Jul 30 10:46:45 2015 AEST+1000 > > The point, however is that "EST" does not mean -0500 for everyone. Showing my US centrism here! If we're getting into naming schemes here, it clearly gets ugly -- honestly I have no idea whether AEST is an name for an offset or a timezone. So when I said there can be more than one name for a given offset, there can also be more than one offset for a given name. Personally, I'm not really interested in the names, and the naming issue is orthogonal to the rest of this discussion. But I presume the Olson database has a naming scheme... -CHB From chris.barker at noaa.gov Thu Jul 30 03:19:57 2015 From: chris.barker at noaa.gov (Chris Barker - NOAA Federal) Date: Wed, 29 Jul 2015 18:19:57 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: <-6120061269507718094@unknownmsgid> References: <-6120061269507718094@unknownmsgid> Message-ID: <5125954986095740442@unknownmsgid> By the way, sorry tone so inattentive as not to notice the +1000 next to that EST! Muddied the waters s bit... CHB Sent from my iPhone On Jul 29, 2015, at 6:16 PM, Chris Barker - NOAA Federal wrote: >> Fair enough: "EST is a offset", what is +1000 then? > > Also an offset -- but one without a name -- In the general case, a > given offset may have more than one name. > > EST is one name for a +5 offset. (Or is it minus 5?) but there are > other times on other timezones where the offset is 5. > >> $ TZ=Australia/Melbourne date +"%c %Z%z" >> Thu Jul 30 10:46:45 2015 AEST+1000 >> >> The point, however is that "EST" does not mean -0500 for everyone. > > Showing my US centrism here! > > If we're getting into naming schemes here, it clearly gets ugly -- > honestly I have no idea whether AEST is an name for an offset or a > timezone. So when I said there can be more than one name for a given > offset, there can also be more than one offset for a given name. > > Personally, I'm not really interested in the names, and the naming > issue is orthogonal to the rest of this discussion. > > But I presume the Olson database has a naming scheme... > > -CHB From tim.peters at gmail.com Thu Jul 30 03:35:38 2015 From: tim.peters at gmail.com (Tim Peters) Date: Wed, 29 Jul 2015 20:35:38 -0500 Subject: [Datetime-SIG] "Use cases" (was Re: [Python-Dev] Status on PEP-431 Timezones) Message-ID: [moved from python-dev] [Lennart Regebro ] >>> I have yet to see a use case for that. [Tim] >> Of course you have. When you address them, you usually dismiss them >> as "calendar operations" (IIRC). [Lennart] > Those are not usecases for this broken behaviour. Ever get the feeling we use languages that share many words but few meanings? I do ;-) I can tell you what "use case" means to me: task T is a use case for gimmick G if and only if G can be used straightforwardly to accomplish T. That's all. By my meaning, you have been shown use cases. > I agree there is a usecase for where you want to add one day to an 8am > datetime, and get 8am the next day. Calling them "date operations" or > "calendar operations" is not dismissing them. In context, "you usually dismiss them" meant you refuse to accept them as being use cases (dismiss them for that purpose). Which you do. I had no intent to imply that you, e.g., held such apps in contempt (which is a possible meaning of "dismiss"), and apologize if it came across that way. > I got into this whole mess because I implemented calendars. That use > case is the main usecase for those operations. By my definition, I certainly agree that mucking with calendars is a use case for calendar operations (even without knowing precisely what "calendar operations" means). > But that usecase is easily handled in several ways. By my definition, the number of ;_possible_ straightforward ways to accomplish T is irrelevant to whether T is a use case. It's a use case for all straightforward ways of accomplishing T. > Already today in how datetime works, you have two solutions: The first > is to use a time zone naive datetime. That's not a solution at all to the specific kinds of apps I (& others) sketched before. Those apps _also_ need to keep track of local times in multiple time zones, and _also_ need to convert times among those time zones. Their datetime objects need to have fully capable tzinfo members. They also need to compute simple kinds of "calendar operations". > This is what most people who want to ignore time > zones should use. The other is to separate the datetime into date and > time objects and add a day to the date object. Same objection. There was never a claim that _all_ applications are "use cases" for the status quo; the claim was that you were given _some_ applications that were use cases. > But most importantly, there are better ways to solve this that > datetime today doesn't support at all: "There's a better way to solve it" also has no bearing, in my definition of "use case", on whether a particular T _is_ a "use case" for G. There are typically many distinct ways to accomplish a given T; T is typically a use case for many gimmicks. > 1. You can use something like dateutil.rrule for repeating events. > (works today, but requires a third-party module). I agree the apps in question are use cases for some dateutil gimmicks. > 2. timedelta could not incorrectly pretend that one day is always 24 > hours, but actually handle days separately, and always increase the > days when a day is given. (This would however mean we no longer can > support fractional days). This one is too sketchy for me to guess. If the claim is just that _some_ kind of timedelta variant could be created that would handle the specific apps in question if arithmetic worked differently _and_ the implementations of datetime arithmetic were changed to do something quite different from the new default when given an instance of that timedelta variant, then sure. Whether that would be a "better way" is clear as mud without fleshing out a world of details. > 3. There could be a datetelta() object that makes operations on dates, > leaving hours, minuts, seconds and microseconds alone, or something > like Lubridates Perod and Delta objects, where a Period() essentially > operates on wall time, and a Duration() operates on real time. Don't know anything about those, so no comment. In any case, a full-featured "calendar operations" module would (IMO) be a welcome addition. In effect, the builtin datetime-timedelta arithmetic makes some kinds of "calendar operations" dead easy, but they're limited to moving. in naive time, by (in conceptual terms) linear combinations of days, weeks, and (rarely) hours. > So that's not the usecase I'm asking for. I am specifically asking for > a usecase where I want an object that is timezone aware, but ignores > the timezone for everything other than conversion to other timezones. And, e.g., you've never seen the description of the cross-timezone meeting-scheduling app? It wasn't brought up by me, but I have summarized it for you before. It needs fully aware datetime objects (both to mirror local clocks, and to convert between timezones), and it needs simple "same local time a week from now" operations. All very easily done with the status quo (the only "hard part" is getting the right tzinfo objects to begin with), and so is unquestionably - by my definition - a use case for doing naive arithmetic on aware datetimes. Not only "a" use case, but a good one. I can't imagine a simpler way (for the user) to accomplish what that app needs. > Because that's what datetime implements. That's what I want a usecase > for. And you've been given some. I expect you'll disagree, but if you do I'll let it end with your response. > "I want the same time next day" is not such a usecase. With just that much In isolation, no, I agree it isn't a _good_ use case for doing naive arithmetic on an aware datetime object. But since it _does_ solve the problem, by my definition I'm afraid it does count as _a_ use case. If, for reasons neither stated nor denied, that same app not only needs 'same time next day" but also needs "and then I need to convert same time next day to some other timezone (e.g., I'm in a hacker network and my payload won't be ready until same time next day, and then I have to coordinate releasing the payload with my criminal partners in China). then that's a fine use case. Yes, I realize there are other ways that can done. Doesn't change that it's _a_ use case as is. >> But it doesn't matter whether you _call_ them "calendar operations", >> or anything else. What they're called doesn't change any of the >> high-order bits: they are use cases, they already work, they have >> worked that way for a dozen years (an eternity in "computer time"), >> they were always intended to work that way, and the docs have always >> said they work that way. > They only work like that because people have adapted to how datetime > does things. If datetime had done this properly from the start, it > would have worked even better. Of course people use whatever is most convenient to get the task at hand done. When people are already getting correct results for _their_ purposes, using obvious (to them) code, in what way(s) would changing the arithmetic make those apps work better? I mean, of course, the same apps that are already working fine. > ... > I stopped arguying for changing datetime two days ago. I've also > mentioned that several times. Yet the argument never ends ;-) Seriously, I hope you find a way to get interested in this again. You have a wealth of experience that's valuable here! >> using that thing in non-trivial ways without a >> justification so compelling that I can't recall a case of it ever >> happening. > Well, I've seen several of those on Stackoverflow. Happy to look at specific examples. In truth, I _do_ recall some, but not since Python 1.0.0 was released. Example: waaaaaaaaaay back when, ints used (an illusion of) infinitely wide 2's-complement internally, but longs used (an illusion of) infinitely wide 1's-complement internally. Both were intended and documented. One consequence: if you had a negative integer K and shifted it right, the value of the result could differ depending on whether type(K) was int or long. This made nightmares for my code at the time, because I needed to mix signed ints and signed longs frequently. Guido changed it (so that all integer types used the 2's-complement scheme). But despite that Python had only 2(*) users at the time, he was still cautious and apologetic about it. (*) Maybe 3. I used an old script to compute this, but the exact value got lost due to the "different representations, with visible consequences, for negative integers of different types" design flaw ;-) From alexander.belopolsky at gmail.com Thu Jul 30 04:10:56 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Wed, 29 Jul 2015 22:10:56 -0400 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: <-6120061269507718094@unknownmsgid> References: <-6120061269507718094@unknownmsgid> Message-ID: On Wed, Jul 29, 2015 at 9:16 PM, Chris Barker - NOAA Federal wrote: >> Fair enough: "EST is a offset", what is +1000 then? > > Also an offset -- but one without a name -- In the general case, a > given offset may have more than one name. > > EST is one name for a +5 offset. (Or is it minus 5?) but there are > other times on other timezones where the offset is 5. In the UNIX/Olson world, EST, AEST, EDT etc. are all "time zones" that have a particularly simple set of rules: $ zdump -v EST EST Fri Dec 13 20:45:52 1901 UTC = Fri Dec 13 15:45:52 1901 EST isdst=0 EST Sat Dec 14 20:45:52 1901 UTC = Sat Dec 14 15:45:52 1901 EST isdst=0 EST Mon Jan 18 03:14:07 2038 UTC = Sun Jan 17 22:14:07 2038 EST isdst=0 EST Tue Jan 19 03:14:07 2038 UTC = Mon Jan 18 22:14:07 2038 EST isdst=0 (For Australia/Melbourne, the output is 286 lines.) Another way to tell that "EST" is a "time zone" is because it is valid as a TZ environment variable value: $ TZ=EST date Wed Jul 29 20:46:59 EST 2015 This matches the Python's tzinfo concept: a base class for both datetime.timezone and pytz.timezone classes. This means that unlike NodaTime, Python does not have different classes for "ZonedDatetime" and "OffsetDatetime". Instead, we have a single datetime class and different possibilities for tzinfo member. As far as I understand, NodaTime to Python dictionary would have the following translations: LocalDatetime: datetime with tzinfo=None (naive datetime) OffsetDatetime: datetime with tzinfo=datetime.timezone(offset, name) ZonedDatetime: datetime with tzinfo=pytz.timezone(name) Given that all three concepts are implemented in a single datetime.datetime class in Python, I am not sure how helpful NodaTime terminology will be for our purposes. (BTW, historically, early versions of Python datetime had a separate datetime subclass called datetimetz (IIRC), but the final design got rid of this unnecessary complexity.) From tim.peters at gmail.com Thu Jul 30 05:33:03 2015 From: tim.peters at gmail.com (Tim Peters) Date: Wed, 29 Jul 2015 22:33:03 -0500 Subject: [Datetime-SIG] Datetime - my issues In-Reply-To: References: Message-ID: [Skip Montanaro ] > .... > ... For historical and > interface reasons, the system I work with uses a mixture of epoch > seconds, naive datetime objects, and tz-aware datetime objects, Then for God's sake, be sure nobody in the office carries loaded guns - the temptation would be overpowering ;-) > ,... > Despite having to convert naive (and implicitly Chicago-based) > datetime objects into tz-aware objects, I still find myself looking > back at existing code to perform the conversions, as (for whatever > reason) the method names aren't terribly suggestive to me, and I > sometimes get the names wrong. Is there anyone who _doesn't_ share that experience? There's also a mixture of relatively new and relatively ancient names in use. > ... > Getting the string you want (or very close to it, why would you want > HHMM offset and timezone name?) Because it is, in general, a many-to-many relationship (multiple names for a single offset, multiple offsets for a single name). For someone who only uses a relatively tiny subset of the possible canned timezones, though, collisions are unlikely, and I bet they'd rather just see the names. Except for those who'd rather just see the offsets. So that's why - ask for a new environment variable to control it? ;-) > is similarly straightforward, using a tz-aware datetime object: > >>> now = Clock.local_datetime() > >>> now > datetime.datetime(2015, 7, 29, 13, 15, 23, 650153, tzinfo= ' America/Chicago' CDT-1 day, 19:00:00 DST>) > >>> now.isoformat() > '2015-07-29T13:15:23.650153-05:00' > > I do find the slightly slavish adherence to the old Unix time(3) > function implication that "times don't have fractions of a second" a > bit clumsy: That's interesting to me, but mainly because I'm surprised your financial services applications care about fractional seconds! Do you, perhaps, track real-time transactions in heavily traded markets? > ... >>>> now > datetime.datetime(2015, 7, 29, 13, 15, 23, 650153, tzinfo= 'America/Chicago' CDT-1 day, 19:00:00 DST>) >>>> now.timetuple() > time.struct_time(tm_year=2015, tm_mon=7, tm_mday=29, tm_hour=13, > tm_min=15, tm_sec=23, tm_wday=2, tm_yday=210, tm_isdst=1) > > What happened to my microseconds??? You're using methods designed for interoperability with the C language's ubiquitous "struct tm": http://pubs.opengroup.org/onlinepubs/007908775/xsh/time.h.html The meanings, and even the names of the fields, are identical between Python and C. A struct tm doesn't know microseconds from doughnuts. That's why microseconds are missing here. It's perhaps unfortunate that, when some functionality in C's standard library was already available in some Python module, datetime generally declined to implement a work-a-like of its own, more natural for use with datetime's view of things. > That forces me to write little helper functions like this: > > def to_timestamp(dt): > """Convert a datetime object into seconds since the Unix epoch.""" > return time.mktime(dt.timetuple()) + dt.microsecond/1e6 Python 3.3 (which you don't use) added a timestamp() method to datetime objects. > Going forward, I think it would be cleaner if datetime.timetuple() > returned a tuple with microseconds, and the relevant old-style > functions in the time module were smart enough to know when to ignore > them. Death to legacy code. Come the revolution, even the letter C will be removed from the alphabet ;-) > I also occasionally want timedelta objects in seconds, so have this: > > def as_seconds(delta): > """Convert a timedelta object into seconds (float).""" > return delta.days*24*60*60 + delta.seconds + delta.microseconds/1e6 Python 3.2 (which you don't use) added a total_seconds() method to timedetla objects, returning the same thing as your function. > Despite the overflow possibilities (I doubt I will still be working > when that happens), I think it would be nice to have a few convenience > functions like this, in the to-be-named-later datetime utils > module. As above, the timestamp and timedelta seconds functionalities were already added, via new methods. > I'm less thrilled with some heuristic function which allows > you to take a datetime object and add or subtract some number of > months, as I can't see a good way to get that right. Nevertheless, there can be a _defined_ way, and even choice among multiple defined ways. While there is apparently no limit to the perversity of bureaucrats making up "business rules", the set of idiocies they can inflict on the world is almost certainly no worse than countably infinite, so Python long ints suffice to model them ;-) > Finally, at some point I read somewhere that using > dtobject.astimezone(newzone) was preferable to using > zone.normalize(dtobject). My code is now littered with both spellings, > but I have no recollection of why one would be preferred over the > other (except that pytz is clearly not part of the standard library). Can't help there. I generally write my own tzinfo subclasses, because I only work for myself now, and like amusing timezone names ;-) From the massive discussion so far, it sounds like pytz does as much work to try to "fix" Python's datetime arithmetic as to supply a mountain of standardized zoneinfo objects. Since Python's datetime arithmetic is fine by me already, I don't need the extra complications of changing what already works (in my eyes). > Corollary: It seems to me like the astimezone call ought to work: > > >>> now = datetime.datetime.now() > autoloading datetime > >>> import pytz > >>> chi = pytz.timezone("America/Chicago") > >>> now.astimezone(chi) > ValueError astimezone() cannot be applied to a naive datetime > [||1] > >>> chi.localize(now) > datetime.datetime(2015, 7, 29, 13, 39, 23, 139107, tzinfo= 'America/Chicago' CDT-1 day, 19:00:00 DST>) > > but maybe that's just a case of explicit-is-better-than-implicit... Really a case of in-the-face-of-ambiguity-refuse-the-temptation-to-guess. now() returns a naive datetime, so astimezone() has no idea what you _think_ its timezone "really is". But note that you can pass a tzinfo argument to now() to _tell_ now() which timezone you want. Then .now(tz) acts like return tz.fromutc(datetime.utcnow().replace(tzinfo=tz)). That is, it returns an aware datetime for the timezone you passed in, recording current time in that timezone. So try just now = datetime.datetime.now(chi) instead? Or if you know darned well your system clock is using the `chi` timezone, even now = datetime.datetime.now().replace(tzinfo=chi) However, without being intimately familiar with all the details of pytz's "try to fix the arithmetic" gimmicks (just reading its docs doesn't reveal much about that), I can't guess whether pytz operations will be happy with datetimes created in those ways. Python's own operations will be delighted with them :-) From lrekucki at gmail.com Thu Jul 30 07:16:11 2015 From: lrekucki at gmail.com (=?UTF-8?Q?=C5=81ukasz_Rekucki?=) Date: Thu, 30 Jul 2015 07:16:11 +0200 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: On 30 July 2015 at 02:14, Chris Barker wrote: > On Wed, Jul 29, 2015 at 2:31 PM, Felipe Ochoa >> >> * local vs global: "The key difference is that people all around the world >> will agree on a global value simultaneously, whereas they may all see >> different local values for the same global value, due to time zones." Local >> values are what Guido has labeled "naive" -- in the sense that they don't >> have a datetime. > > > Is this a typo? should be "don't have a time zone"? By the way, that means" > can't map to UTC, which, by extension, means, "can't map to any other > timezone" Yes, LocalDateTime does not have a timezone and thus does *not* define an instant on a timeline. You can't convert it to anything without providing extra information. >> >> * Time zone: "a mapping from UTC instants to offsets" > > > note that the actual mapping may (does) change over history, and has odd > things like DST. Yes, that's already covered in this definition. You can also say that a Timezone is a function from an Instant to offset. An example such function would look like this: def tz_us_cookie_time(instant): if instant.year() > 2016: return -5000 if 4 < instant.month() < 11 else -6000 else: return tz_us_boring_time(instant) As the number of rules is always finite, you can also make it a mapping. > > This seems like an obviously good idea to me, aside from potential > implementation difficulty and I'm not sure if there are backward > compatibility issues. > The backwards incompatibility is that PEP also want that ZonedDateTime [== datetime(tzinfo=tz("America/Chicago"))] does the sane thing and follows what NodaTime, JodaTime, etc. does - which is "Time line arithmetic". > So is there any more to be hashed out in the PEP (it seem where to get the > time zone data on Windows is one unresolved issue). > > Then there seem to be the big hang-up: people want a way to define Periods > (as defined above) and want to be able to do datetime math with them. I"m > still really confused as to why folks seemed to think "time zone aware" > somehow meant using Peiods rather than Durations for arithmetic, but there > you go. Clearly this is very useful thing to have, but it's NEW feature, and > not covered in the PEP. No, people want to keep adding Durations (timedelta) to ZonedDataTime and expect it to work in "time zone aware" manner. In particular adding 24h duration should add exactly 24h, *always*. This is *NOT* how Python's datetime currently works. From guido at python.org Thu Jul 30 10:54:52 2015 From: guido at python.org (Guido van Rossum) Date: Thu, 30 Jul 2015 10:54:52 +0200 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: Thanks to Felipe Ocha for posting the nodatime link -- it's very useful. (I first misread it as "no datetime". :-) On Thu, Jul 30, 2015 at 4:10 AM, Alexander Belopolsky < alexander.belopolsky at gmail.com> wrote: > [...] > Another way to tell that "EST" is a "time zone" is because it is valid > as a TZ environment variable value: > [...] > Can we be more precise here and distinguish between a "time zone" (which is a function from UTC to offsets) and the various *names* for time zones? It seems that there are multiple names for some (many) time zones, and some names also designate multiple timezones (maybe those are known as "short names"?). Presumably a good tz database has both the mappings between names and functions, and the functions themselves (in some DSL involving offsets and DST rules, of course). Also note that the functions themselves may change over time: when a local political body changes the rules. This is then reflected in an update of the tz database. There's a third mapping (which doesn't concern us much here) which also varies over time (and I don't know if the Olsen database has it): the mapping from geographical area to time zone. > As far as I understand, NodaTime to Python dictionary would have the > following translations: > > LocalDatetime: datetime with tzinfo=None (naive datetime) > I have a slight concern here. In my own brain-universe there is a difference between a *local* datetime and a *naive* datetime. A local datetime has an implicit timezone (the one used by the system wall clock, or perhaps the TZ env var). A naive datetime, as intended in the original design, has *no* timezone. What's the difference? A local datetime has a well-defined mapping to UTC, but a naive datetime's meaning is up to the app that manipulates it. An example might be a world-wide publicity event that happens at noon local time on a give date, or the broadcast time of a pre-recorded TV show (in the US, shows are often aired at a well-known time slot, e.g. "prime time", 8pm in each time zone). I also never meant the term "naive" to be used for the existing arithmetic rules for tz-aware datetime objects -- I always meant "naive" to refer to tz-less datetime objects. I would prefer something like "classic arithmetic" for tz-aware datetime objects. We can then introduce two new terms for different forms of arithmetic: "human arithmetic" for the form that can do things like "+ 2 months" in a way that (mostly) matches human expectations, and "strict arithmetic" for the form that Lennart needs (essentially move a specific number of seconds along UTC). FWIW (not much, we're stuck with it now), my intention with classic arithmetic was to approximate human arithmetic, but only for cases that didn't require messy heuristics such as "Feb 29, 2016 plus one year" or "Jan 31, 1956 minus 9 months". I also (naively :-) assumed that people interested in strict arithmetic would just keep using the POSIX timestamps used by the time module. > OffsetDatetime: datetime with tzinfo=datetime.timezone(offset, name) > ZonedDatetime: datetime with tzinfo=pytz.timezone(name) > > Given that all three concepts are implemented in a single > datetime.datetime class in Python, I am not sure how helpful NodaTime > terminology will be for our purposes. > They are still useful when discussing various use cases and scenarios. I bet several heated arguments of the past days would have been cut short more easily if these concepts had been explained earlier. Also, the distinction in terminology helps explain the difference between (e.g.) US EST and US/Eastern. > (BTW, historically, early versions of Python datetime had a separate > datetime subclass called datetimetz (IIRC), but the final design got > rid of this unnecessary complexity.) > I don't believe that was ever released, but it's possible we contemplated that and even implemented it in an early pure-Python prototype. -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From guido at python.org Thu Jul 30 11:13:22 2015 From: guido at python.org (Guido van Rossum) Date: Thu, 30 Jul 2015 11:13:22 +0200 Subject: [Datetime-SIG] Datetime - my issues In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 5:33 AM, Tim Peters wrote: > [...] > > You're using methods designed for interoperability with the C > language's ubiquitous "struct tm": > > http://pubs.opengroup.org/onlinepubs/007908775/xsh/time.h.html > > The meanings, and even the names of the fields, are identical between > Python and C. Actually the meanings of some fields are different -- C's tm_mon is 0-11, while Python's is 1-12; also, C's tm_year is "year - 1900" while Python's is the full 4-digit year (IIRC we had to change the latter in order to ward off Y2K issues). > A struct tm doesn't know microseconds from doughnuts. > That's why microseconds are missing here. But we could still add it. By now the similarity to C for various APIs is just there to help C programmers quickly get their bearings in Python, not a hard philosophical line in the sand. -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From guido at python.org Thu Jul 30 11:25:16 2015 From: guido at python.org (Guido van Rossum) Date: Thu, 30 Jul 2015 11:25:16 +0200 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 2:31 AM, Chris Barker wrote: > > Perhaps the original intent was that "days" means calendar days, and for > naive datetimes, it turns out to be the same thing, but that is not what > the implementation does, and given that it supports seconds and > microseconds, but not months or years, the API is pretty clearly designed > for timespans, not calendar definitions. > I can assure you that the implementation carefully matches the original intent. Even if I wouldn't design it that way today (which honestly I haven't decided whether I would or not) I don't want to change anything about the observable behavior[1] that would give a different outcome, no matter how much more "correct" you believe a different outcome would be. The deprecation time would have be measured in decades. The road to improvement that I encourage everyone to explore: add an is_dst flag (with a different name) and create new timedelta-ish classes that implement "human" arithmetic (similar to what pytz offers) and "strict" arithmetic (similar to [NJ]odaTime, IIUC). Separately, standardized access in the stdlib to a tz database (see another thread). [1] The *implementation* may change, but not in a way that changes observable behavior, except for the addition of new attributes, parameters and/or methods. -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From lrekucki at gmail.com Thu Jul 30 11:45:47 2015 From: lrekucki at gmail.com (=?UTF-8?Q?=C5=81ukasz_Rekucki?=) Date: Thu, 30 Jul 2015 11:45:47 +0200 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: On 30 July 2015 at 10:54, Guido van Rossum wrote: > Thanks to Felipe Ocha for posting the nodatime link -- it's very useful. (I > first misread it as "no datetime". :-) > > On Thu, Jul 30, 2015 at 4:10 AM, Alexander Belopolsky > wrote: >> >> [...] >> Another way to tell that "EST" is a "time zone" is because it is valid >> as a TZ environment variable value: >> [...] > > > Can we be more precise here and distinguish between a "time zone" (which is > a function from UTC to offsets) and the various *names* for time zones? It > seems that there are multiple names for some (many) time zones, and some > names also designate multiple timezones (maybe those are known as "short > names"?). Presumably a good tz database has both the mappings between names > and functions, and the functions themselves (in some DSL involving offsets > and DST rules, of course). +1 >> >> As far as I understand, NodaTime to Python dictionary would have the >> following translations: >> >> LocalDatetime: datetime with tzinfo=None (naive datetime) > > > I have a slight concern here. In my own brain-universe there is a difference > between a *local* datetime and a *naive* datetime. A local datetime has an > implicit timezone (the one used by the system wall clock, or perhaps the TZ > env var). A naive datetime, as intended in the original design, has *no* > timezone. If the timezone is implicit, then it's not kept together with the object. Which means that the difference is purely in the behavior of such object, e.g. converting to UTC: naive datetime requires passing a timezone explicitly, while your local datetime just call get_system_timezone() and uses that. I would say if you have both a *naive* datetime and "*zoned* datetime, the use of this kind of datetime with implicit timezone is rather limited because you can just use a *zoned* variant with get_system_timezone() as its TZ _explicitly_. > > I also never meant the term "naive" to be used for the existing arithmetic > rules for tz-aware datetime objects -- I always meant "naive" to refer to > tz-less datetime objects. I would prefer something like "classic arithmetic" > for tz-aware datetime objects. > > We can then introduce two new terms for different forms of arithmetic: > "human arithmetic" for the form that can do things like "+ 2 months" in a > way that (mostly) matches human expectations, and "strict arithmetic" for > the form that Lennart needs (essentially move a specific number of seconds > along UTC). How about *time line* arithmetic ? It's also in Noda docs and avoids discussing what is more "human". But "strict" sounds good too. Is there some wiki-space where this could be put to so that people don't have too search the archives? (I'm willing to do the work and gather the info from this thread into it). -- ?ukasz Rekucki From guido at python.org Thu Jul 30 16:05:15 2015 From: guido at python.org (Guido van Rossum) Date: Thu, 30 Jul 2015 16:05:15 +0200 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: [Alexander Belopolsky] > >> As far as I understand, NodaTime to Python dictionary would have the > >> following translations: > >> > >> LocalDatetime: datetime with tzinfo=None (naive datetime) > [Guido van Rossum] > > I have a slight concern here. In my own brain-universe there is a > difference > > between a *local* datetime and a *naive* datetime. A local datetime has > an > > implicit timezone (the one used by the system wall clock, or perhaps the > TZ > > env var). A naive datetime, as intended in the original design, has *no* > > timezone. > [?ukasz Rekucki] > If the timezone is implicit, then it's not kept together with the > object. Which means that the difference is purely in the behavior of > such object, e.g. converting to UTC: naive datetime requires passing a > timezone explicitly, while your local datetime just call > get_system_timezone() and uses that. I would say if you have both a > *naive* datetime and "*zoned* datetime, the use of this kind of > datetime with implicit timezone is rather limited because you can just > use a *zoned* variant with get_system_timezone() as its TZ > _explicitly_. > That's all fine, but my point remains, that the tz-less datetime object does *not* always mean local time. The definition I quoted from Alexander conflated the two, incorrectly IMO. [Guido] > > I also never meant the term "naive" to be used for the existing > arithmetic > > rules for tz-aware datetime objects -- I always meant "naive" to refer to > > tz-less datetime objects. I would prefer something like "classic > arithmetic" > > for tz-aware datetime objects. > > > > We can then introduce two new terms for different forms of arithmetic: > > "human arithmetic" for the form that can do things like "+ 2 months" in a > > way that (mostly) matches human expectations, and "strict arithmetic" for > > the form that Lennart needs (essentially move a specific number of > seconds > > along UTC). > > How about *time line* arithmetic ? It's also in Noda docs and avoids > discussing what is more "human". But "strict" sounds good too. > If that's what Noda uses, that's fine with me (the fewer vocabularies the better). > Is there some wiki-space where this could be put to so that people > don't have too search the archives? (I'm willing to do the work and > gather the info from this thread into it). Wikis are self-serve. Create one! -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From ischwabacher at wisc.edu Thu Jul 30 16:48:05 2015 From: ischwabacher at wisc.edu (ISAAC J SCHWABACHER) Date: Thu, 30 Jul 2015 14:48:05 +0000 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: > From: Datetime-SIG on behalf of Alexander Belopolsky > Sent: Wednesday, July 29, 2015 19:27 > To: Felipe Ochoa > Cc: datetime-sig > Subject: Re: [Datetime-SIG] Clearing up terminology > > On Wed, Jul 29, 2015 at 5:31 PM, Felipe Ochoa > wrote: > > * Time zone: "a mapping from UTC instants to offsets" > > > > * Offset: "simply the difference between UTC and local time." > > > > * ZonedDatetime: An instant + a time zone > > > > * OffsetDatetime: An instant + an offset (which is not the same as a > > ZonedDatetime!) > > > > * LocalDatetime: A date/time in the usual "naive" sense: a combination of > > year, month, day, hour, minute, second, millisecond (soon to be nano?) > > Given this terminology and the following UNIX date utility invocation, > > $ TZ=Australia/Melbourne date +"%c%z" > Thu 30 Jul 2015 10:21:18 AM EST+1000 > > what is (a) Australia/Melbourne, (b) EST? Australia/Melbourne is a time zone, +1000 is an offset, and EST is an accident waiting to happen. ijs From alexander.belopolsky at gmail.com Thu Jul 30 17:04:17 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 11:04:17 -0400 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: On Thu, Jul 30, 2015 at 10:05 AM, Guido van Rossum wrote: > [Alexander Belopolsky] > >> >> As far as I understand, NodaTime to Python dictionary would have the >> >> following translations: >> >> >> >> LocalDatetime: datetime with tzinfo=None (naive datetime) >> > >> > That's all fine, but my point remains, that the tz-less datetime object > does *not* always mean local time. The definition I quoted from Alexander > conflated the two, incorrectly IMO. > I agree with that, but it is my understanding that Noda's LocalDatetime concept most closely matches our "naive datetime" concept. According to Noda documentation, LocalDatetime is "A date and time in a particular calendar system. A LocalDateTime value does not represent an instant on the time line, because it has no associated time zone: "November 12th 2009 7pm, ISO calendar" occurred at different instants for different people around the world." [1] Since it "has no associated time zone," it "does *not* always mean local time" even thought it has "Local" in the name. [1]: http://nodatime.org/1.2.x/api/html/T_NodaTime_LocalDateTime.htm -------------- next part -------------- An HTML attachment was scrubbed... URL: From ischwabacher at wisc.edu Thu Jul 30 17:26:53 2015 From: ischwabacher at wisc.edu (ISAAC J SCHWABACHER) Date: Thu, 30 Jul 2015 15:26:53 +0000 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: > From: Datetime-SIG on behalf of Chris Barker > Sent: Wednesday, July 29, 2015 19:14 > To: Felipe Ochoa > Cc: datetime-sig > Subject: Re: [Datetime-SIG] Clearing up terminology > > Then there seem to be the big hang-up: people want a way to define Periods (as defined above) and want to be able to do datetime math with them. I"m still really confused as to why folks seemed to think "time zone aware" somehow meant using Peiods rather than Durations for arithmetic, but there you go. Clearly this is very useful thing to have, but it's NEW feature, and not covered in the PEP. I think you're missing something here. This *isn't* the current behavior-- adding a 24 hour timedelta (a Duration) to an aware datetime (a ZonedDateTime) *doesn't* produce an aware datetime corresponding to the Instant 24 hours after the Instant corresponding to the first datetime; rather, it produces an aware datetime equal to the first but with its days field incremented by one. This result corresponds to an Instant that may be 23 or 25 hours (or some weirder number, in exceptional cases) after the first Instant. Which is to say, currently, datetime.timedelta behaves neither as a Period nor as a Duration. In order to use it as a Duration, you need to convert to UTC before doing arithmetic and convert back after. *That* is what has people up in arms. ijs From tim.peters at gmail.com Thu Jul 30 18:03:40 2015 From: tim.peters at gmail.com (Tim Peters) Date: Thu, 30 Jul 2015 11:03:40 -0500 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: [Guido] > ... > I also never meant the term "naive" to be used for the existing arithmetic > rules for tz-aware datetime objects -- I always meant "naive" to refer to > tz-less datetime objects. "Naive arithmetic" was my neologism, starting in this batch of messages. The docs don't call the arithmetic anything, or acknowledge that more than one kind of arithmetic is possible. This batch of messages needed to call it _something_, so I made something up. The docs do briefly explain the "native time" _model_ (and acknowledge that more than one kind of model is possible). The kind of arithmetic Python implements is the only kind that delivers correct answers _within_ the naive time model,. so I've been calling it "naive arithmetic" - in the sense of "the arithmetic behavior required by the naive time model". Which is an unfortunate verbal mess, in large part because "naive arithmetic" is used for _both_ what the docs call "naive objects" and "aware objects". Then again, calling _anything_ "naive" in the docs was probably also unfortunate from the start ;-) > I would prefer something like "classic arithmetic" for tz-aware datetime objects. Read literally, that doesn't make sense to me, and I can't tease out the intent. That is, calling an object (whatever it is) a kind of arithmetic (whatever it is) doesn't make sense to me. I had guessed, that you wanted to call the kind of _arithmetic_ currently implemented "classic arithmetic". but in the next sentence you seem to want to call that "human arithmetic": > We can then introduce two new terms for different forms of arithmetic: > "human arithmetic" for the form that can do things like "+ 2 months" in a > way that (mostly) matches human expectations, and "strict arithmetic" for > the form that Lennart needs (essentially move a specific number of seconds > along UTC). Do you really intend that we use all three: "classic arithmetic", "human arithmetic", and "strict arithmetic"?. If so, I don't grasp the intended distinction between "classic" and "human".(both seem to be the same as what I've been calling "naive arithmetic": the arithmetic Python currently implements for binary arithmetic operators involving at least one datetime object). Anyway, because "strict arithmetic" more-or-less literally means "arithmetic that wholly satisfies the requirements of a given model", in isolation the phrase leaves the question of _which_ model open. So, as was suggested later in the thread, I'd prefer "timeline arithmetic" (and couldn't care less whether it's called "timeline", "time line", or both). And I'll conveniently overlook that "timeline arithmetic" on its own leaves open _which_ timeline (naive or timezone) is intended ;-) > FWIW (not much, we're stuck with it now), my intention with classic > arithmetic was to approximate human arithmetic, but only for cases that > didn't require messy heuristics such as "Feb 29, 2016 plus one year" or "Jan > 31, 1956 minus 9 months". I always viewed the _model_ ("naive time") as primary. Specific arithmetic requirements (for builtin arithmetic operators) then necessarily followed from the choice of model. In any case, while mixed datetime/timedelta arithmetic supports only a small subset of what people want in the way of "calendar operations", it is an exceedingly useful subset on its own, _and_ in implementing fancier operations. It was a great start. ... > I also (naively :-) assumed that people interested in strict arithmetic would > just keep using the POSIX timestamps used by the time module. >> (BTW, historically, early versions of Python datetime had a separate >> datetime subclass called datetimetz (IIRC), but the final design got >> rid of this unnecessary complexity.) > I don't believe that was ever released, but it's possible we contemplated > that and even implemented it in an early pure-Python prototype. FWIW, IIRC it did exist in an early prototype but was discarded before it was even halfway implemented. From chris.barker at noaa.gov Thu Jul 30 18:06:07 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 09:06:07 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 8:26 AM, ISAAC J SCHWABACHER wrote: > > From: Datetime-SIG wisc.edu at python.org> on behalf of Chris Barker > > Then there seem to be the big hang-up: people want a way to define > Periods (as defined above) and want to be able to do datetime math with > them. I"m still really confused as to why folks seemed to think "time zone > aware" somehow meant using Peiods rather than Durations for arithmetic, > but there you go. Clearly this is very useful thing to have, but it's NEW > feature, and not covered in the PEP. > > I think you're missing something here. This *isn't* the current > behavior-- adding a 24 hour timedelta (a Duration) to an aware datetime (a > ZonedDateTime) *doesn't* produce an aware datetime corresponding to the > Instant 24 hours after the Instant corresponding to the first datetime; > rather, it produces an aware datetime equal to the first but with its days > field incremented by one. This result corresponds to an Instant that may > be 23 or 25 hours (or some weirder number, in exceptional cases) after the > first Instant. Thank you for stating this so clearly -- and yes, I was totally mistaken! Which is to say, currently, datetime.timedelta behaves neither as a Period > nor as a Duration. In order to use it as a Duration, you need to convert > to UTC before doing arithmetic and convert back after. *That* is what has > people up in arms. > OK -- and now I'm "up in arms" as well -- OK, not the least bit up in arms, but quite disappointed -- a true Duration calculation is a very, very useful thing, and having it on TZ-aware datetimes is a critical need. Given backward compatibility, I guess we can't change the behavior of datetime + timedelta, but we need something that provides the Duration concept. And, frankly, we could really use a proper Period object as well. I"m not sure what you mean by behaves "neither as a Period", but it clearly is missing a lot of nice functionality as a Period -- i.e. a way to express Periods in units other than days (i.e. next year, next months, etc...) Also: The datetime docs are really, really horrible and confusing on this aspect. Combine that and Tim Peter's discussion of the implementation, and it seemed really really obvious (to me) that TimeDelta was a Duration -- there was even a quote along the lines of "datetime and timedelta are really just fancy ways of encoding microseconds). And from the docs (and implementation): """ and days, seconds and microseconds are then normalized so that the representation is unique, with 0 <= microseconds < 1000000 0 <= seconds < 3600*24 (the number of seconds in one day) """ So, in this case, a "day" is always and forever 24 hours is 86400 seconds. really weird that that gets interpreted in a timezone with DST as meaning "a calendar day". So it appears that a timedelta is not a fancy way to encode microseconds, but rather, a fancy way to encode a "Period" in units of days, resolved to microseconds. So: it's clear to me, anyway, that it would be desirable to have a way to do both Period and Duration calculations with TZ aware DT objects. How to get there is beyond me at this point -- almost seems we may need to start over. Sigh. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Thu Jul 30 18:19:25 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 09:19:25 -0700 Subject: [Datetime-SIG] "Use cases" (was Re: [Python-Dev] Status on PEP-431 Timezones) In-Reply-To: References: Message-ID: Is there any disagreement that both Duration and Period (to use the Noda terms) operations have important and common use-cases? Granted, if not, that doesn't tell us anything about what should be supported in the stdlib, but it seems odd to be arguing about something this basic. -Chris On Wed, Jul 29, 2015 at 6:35 PM, Tim Peters wrote: > [moved from python-dev] > > [Lennart Regebro ] > >>> I have yet to see a use case for that. > > [Tim] > >> Of course you have. When you address them, you usually dismiss them > >> as "calendar operations" (IIRC). > > [Lennart] > > Those are not usecases for this broken behaviour. > > Ever get the feeling we use languages that share many words but few > meanings? I do ;-) > > I can tell you what "use case" means to me: task T is a use case for > gimmick G if and only if G can be used straightforwardly to accomplish > T. That's all. By my meaning, you have been shown use cases. > > > I agree there is a usecase for where you want to add one day to an 8am > > datetime, and get 8am the next day. Calling them "date operations" or > > "calendar operations" is not dismissing them. > > In context, "you usually dismiss them" meant you refuse to accept them > as being use cases (dismiss them for that purpose). Which you do. I > had no intent to imply that you, e.g., held such apps in contempt > (which is a possible meaning of "dismiss"), and apologize if it came > across that way. > > > I got into this whole mess because I implemented calendars. That use > > case is the main usecase for those operations. > > By my definition, I certainly agree that mucking with calendars is a > use case for calendar operations (even without knowing precisely what > "calendar operations" means). > > > But that usecase is easily handled in several ways. > > By my definition, the number of ;_possible_ straightforward ways to > accomplish T is irrelevant to whether T is a use case. It's a use > case for all straightforward ways of accomplishing T. > > > Already today in how datetime works, you have two solutions: The first > > is to use a time zone naive datetime. > > That's not a solution at all to the specific kinds of apps I (& > others) sketched before. Those apps _also_ need to keep track of > local times in multiple time zones, and _also_ need to convert times > among those time zones. Their datetime objects need to have fully > capable tzinfo members. They also need to compute simple kinds of > "calendar operations". > > > This is what most people who want to ignore time > > zones should use. The other is to separate the datetime into date and > > time objects and add a day to the date object. > > Same objection. There was never a claim that _all_ applications are > "use cases" for the status quo; the claim was that you were given > _some_ applications that were use cases. > > > But most importantly, there are better ways to solve this that > > datetime today doesn't support at all: > > "There's a better way to solve it" also has no bearing, in my > definition of "use case", on whether a particular T _is_ a "use case" > for G. There are typically many distinct ways to accomplish a given > T; T is typically a use case for many gimmicks. > > > 1. You can use something like dateutil.rrule for repeating events. > > (works today, but requires a third-party module). > > I agree the apps in question are use cases for some dateutil gimmicks. > > > 2. timedelta could not incorrectly pretend that one day is always 24 > > hours, but actually handle days separately, and always increase the > > days when a day is given. (This would however mean we no longer can > > support fractional days). > > This one is too sketchy for me to guess. If the claim is just that > _some_ kind of timedelta variant could be created that would handle > the specific apps in question if arithmetic worked differently _and_ > the implementations of datetime arithmetic were changed to do > something quite different from the new default when given an instance > of that timedelta variant, then sure. Whether that would be a "better > way" is clear as mud without fleshing out a world of details. > > > 3. There could be a datetelta() object that makes operations on dates, > > leaving hours, minuts, seconds and microseconds alone, or something > > like Lubridates Perod and Delta objects, where a Period() essentially > > operates on wall time, and a Duration() operates on real time. > > Don't know anything about those, so no comment. > > In any case, a full-featured "calendar operations" module would (IMO) > be a welcome addition. In effect, the builtin datetime-timedelta > arithmetic makes some kinds of "calendar operations" dead easy, but > they're limited to moving. in naive time, by (in conceptual terms) > linear combinations of days, weeks, and (rarely) hours. > > > So that's not the usecase I'm asking for. I am specifically asking for > > a usecase where I want an object that is timezone aware, but ignores > > the timezone for everything other than conversion to other timezones. > > And, e.g., you've never seen the description of the cross-timezone > meeting-scheduling app? It wasn't brought up by me, but I have > summarized it for you before. It needs fully aware datetime objects > (both to mirror local clocks, and to convert between timezones), and > it needs simple "same local time a week from now" operations. All > very easily done with the status quo (the only "hard part" is getting > the right tzinfo objects to begin with), and so is unquestionably - by > my definition - a use case for doing naive arithmetic on aware > datetimes. Not only "a" use case, but a good one. I can't imagine a > simpler way (for the user) to accomplish what that app needs. > > > Because that's what datetime implements. That's what I want a usecase > > for. > > And you've been given some. I expect you'll disagree, but if you do > I'll let it end with your response. > > > "I want the same time next day" is not such a usecase. > > With just that much In isolation, no, I agree it isn't a _good_ use > case for doing naive arithmetic on an aware datetime object. But > since it _does_ solve the problem, by my definition I'm afraid it does > count as _a_ use case. If, for reasons neither stated nor denied, > that same app not only needs 'same time next day" but also needs "and > then I need to convert same time next day to some other timezone > (e.g., I'm in a hacker network and my payload won't be ready until > same time next day, and then I have to coordinate releasing the > payload with my criminal partners in China). then that's a fine use > case. Yes, I realize there are other ways that can done. Doesn't > change that it's _a_ use case as is. > > >> But it doesn't matter whether you _call_ them "calendar operations", > >> or anything else. What they're called doesn't change any of the > >> high-order bits: they are use cases, they already work, they have > >> worked that way for a dozen years (an eternity in "computer time"), > >> they were always intended to work that way, and the docs have always > >> said they work that way. > > > They only work like that because people have adapted to how datetime > > does things. If datetime had done this properly from the start, it > > would have worked even better. > > Of course people use whatever is most convenient to get the task at hand > done. > > When people are already getting correct results for _their_ purposes, > using obvious (to them) code, in what way(s) would changing the > arithmetic make those apps work better? I mean, of course, the same > apps that are already working fine. > > > ... > > I stopped arguying for changing datetime two days ago. I've also > > mentioned that several times. > > Yet the argument never ends ;-) Seriously, I hope you find a way to > get interested in this again. You have a wealth of experience that's > valuable here! > > >> using that thing in non-trivial ways without a > >> justification so compelling that I can't recall a case of it ever > >> happening. > > > Well, I've seen several of those on Stackoverflow. > > Happy to look at specific examples. In truth, I _do_ recall some, but > not since Python 1.0.0 was released. > > Example: waaaaaaaaaay back when, ints used (an illusion of) > infinitely wide 2's-complement internally, but longs used (an illusion > of) infinitely wide 1's-complement internally. Both were intended and > documented. > > One consequence: if you had a negative integer K and shifted it > right, the value of the result could differ depending on whether > type(K) was int or long. This made nightmares for my code at the > time, because I needed to mix signed ints and signed longs frequently. > Guido changed it (so that all integer types used the 2's-complement > scheme). But despite that Python had only 2(*) users at the time, he > was still cautious and apologetic about it. > > (*) Maybe 3. I used an old script to compute this, but the exact > value got lost due to the "different representations, with visible > consequences, for negative integers of different types" design flaw > ;-) > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > The PSF Code of Conduct applies to this mailing list: > https://www.python.org/psf/codeofconduct/ > -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim.peters at gmail.com Thu Jul 30 18:31:57 2015 From: tim.peters at gmail.com (Tim Peters) Date: Thu, 30 Jul 2015 11:31:57 -0500 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: [Guido] > ... > The road to improvement that I encourage everyone to explore: add an is_dst > flag (with a different name) There is no path whatsoever to "correct in all cases" in its absence, so this should be the top priority for those to whom "correct in all cases" is their top priority. > and create new timedelta-ish classes that implement "human" > arithmetic (similar to what pytz offers) This part seems confused to me: beyond wrapping zoneinfo in a pile of tzinfo objects, pytz's secondary thrust appears to be "correct in all cases" involving DST transition times. Doing things like allowing to correctly distinguish between the ambiguous times when DST ends is, if I understand anything of your intent, a case of better implementing "strict time" than of implementing "human time". IOW, to the extent arithmetic in pytz acts like "human time", it inherits that behavior from what Python already does. > and "strict" arithmetic (similar to [NJ]odaTime, IIUC). That sounds right. > Separately, standardized access in the stdlib to a tz database (see another thread). That's pytz's primary thrust. Also part of dateutil's thrust (dateutil leaves Python's arithmetic results entirely alone in all cases, but also supplies many "calendar operations" useful regardless of whether you use _its_ wrapping of zoneinfo and/or Windows registry databases). > [1] The *implementation* may change, but not in a way that changes > observable behavior, except for the addition of new attributes, parameters > and/or methods. I'm afraid that may not be entirely possible. For example, if datetime objects grow a new attribute, (like some spelling of .is_dst) then repr() presumably needs to display it. But I know what you mean ;-) From chris.barker at noaa.gov Thu Jul 30 18:35:56 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 09:35:56 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: On Thu, Jul 30, 2015 at 9:03 AM, Tim Peters wrote: > "Naive arithmetic" was my neologism, starting in this batch of > messages. The docs don't call the arithmetic anything, or acknowledge > that more than one kind of arithmetic is possible. Which is really something that needs to addressed! > This batch of > messages needed to call it _something_, so I made something up. > Can we just use the Glossary borrowed from Noda? It doesn't define an "arithmetic", but if we need that term, it could be "Period Arithmetic" and "Duration Arithmetic". And I had assumed that your "naive arithmetic" was Duration arithmetic -- i.e. a day is 24 hours, but apparently not. I'm still confused as to how you can: (paraphrasing my understanding of your earlier post): Convert the datetime to a timedelta from year 1 -- add the timedelta -- convert back to a datetime. I suppose it's a failure of mine to understand how datetime uses the tzinfo object, but this description sure sounds to me like you'd get a datetime that really represented 24 hours later, not 23 or 25 (or something else...) Anyway, my current understanding is that the current implementation of datetime and timedelta is "Period Arithmetic", with only Periods defined in units of days (fraction days, down to microsecond resolution). Is that correct? The kind of arithmetic > Python implements is the only kind that delivers correct answers > _within_ the naive time model,. so I've been calling it "naive > arithmetic" - in the sense of "the arithmetic behavior required by the > naive time model". > Sure -- but we really need the docs to clarify what the heck happens when you have a tz-aware datetime. I'd offer to write a patch for the docs, but as you can see, I'm still pretty confused! In any case, while > mixed datetime/timedelta arithmetic supports only a small subset of > what people want in the way of "calendar operations", it is an > exceedingly useful subset on its own, _and_ in implementing fancier > operations. It was a great start. > Well, yes. I was ecstatic when datetime was introduced, and have found it very, very useful since then. However, not for "calendar operations" (Period Arithmetic) , nor for tz-aware datetimes. (because I don't have much need for these) And unfortunately, I think the implementation of timedelta makes it impossible to extend to richer Period Arithmetic -- it fundamentally uses unit sof days, and has no way to encode any other "Period" unit -- i.e. months or years. The implementation could fully support Duration Arithmetic, so it's a bit of shame that that wasn't chosen in the first place. > I also (naively :-) assumed that people interested in strict arithmetic > would > > just keep using the POSIX timestamps used by the time module. > Well, that explains it -- but no, the time module is very limited and painful to use ;-) -- I was all for Datetime, even though my primary use cases are all Duration arithmetic. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Thu Jul 30 18:43:17 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 12:43:17 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal Message-ID: I would like to make a specific proposal on a narrow topic of how to handle ambiguities inherent in representing time instances in common time zones. The following is a rough sketch where I attempted to identify the areas affected by the proposal and outline the proposed changes. ======= Rationale ======= In the most world locations there have been and will be times when local clocks are moved back. In those times intervals are introduced in which local clocks show the same time twice in the same day. In these situations, the information displayed on a local clock (or stored in a Python datetime instance) is insufficient to identify a particular instance in time. The proposed solution is to add a boolean flag to the datetime instances that will distinguish between the two ambiguous times. ======= Proposal ======= The "first" flag ------------------ We propose adding a boolean member called "first" to the instances of datetime.time and datetime.time classes. This member will have the value True for all instances except those that represent the second (chronologically) moment in time in an ambiguous case. Affected APIs ------------------ Attributes ............... Instances of datetime.time and datetime.datetime will get a new boolean attribute called "first." Constructors .................... The __new__ methods of the datetime.time and datetime.datetime classes will get a new keyword-only argument first=True that will control the value of the "first" attribute in the returned instance. Methods ............. The replace() methods methods of the datetime.time and datetime.datetime classes will get a new keyword-only argument first=True that will control the value of the "first" attribute in the returned instance. Affected behaviors ------------------------- Implementations of tzinfo ....................................... Subclasses of datetime.tzinfo will read the values of "first" in utcoffset() and dst() methods and set it appropriately in the instances returned by the fromutc() method. No change to the signatures of these methods is proposed. Pickle size -------------- Pickle sizes for the datetime.datetime and datetime.time objects will not change. The "first" flag will be encoded in the first bit of the byte that currently stores the 4th byte of the datetime.datetime pickle payload or the 1st byte of the datetime.time. In the current implementation [1] these bytes are used to store hour value (0-23) and the first bit is always 0. Note that first=True will be encoded as 0 in the first bit and first=False as 1. (This change only affects pickle format. In C implementation, the "first" member will get a full byte to store the actual boolean value.) Temporal arithmetics ---------------------------- The value of "first" will be ignored in all operations except utcoffset() and dst() methods of tzinfo implementations and __eq__ and __hash__ methods of the datetime.datetime and datetime.time classes. The only methods that will be able to produce nonzero values of "first" are __new__ and replace() methods of the datetime.datetime and datetime.time classes and fromutc() method of some tzinfo implementations. Backward and forward compatibility ----------------------------------------------- This proposal will have no effect on the programs that do not set the "first" flag explicitly or use tzinfo implementations that do. Pickles produced by older programs will remain fully forward compatible. Only datetime/time instances with first=False pickled in the new versions will become unreadable by the older Python versions. Pickles of instances with first=False will remain unchanged. ================== Questions and Answers ================== 1. Why not call the new flag "isdst"? Alice: Bob - let's have a stargazing party at 01:30 AM tomorrow! Bob: Should I presume initially that summer time (for example, Daylight Saving Time) is or is not (respectively) in effect for the specified time? Allice: Huh? Bob: Alice - let's have a stargazing party at 01:30 AM tomorrow! Alice: You know, Bob, 01:30 AM will happen twice tomorrow. Which one do you have in mind? Bob: I did not think about it, but let's pick the first. [1]: https://hg.python.org/cpython/file/d3b20bff9c5d/Include/datetime.h#l17 From tim.peters at gmail.com Thu Jul 30 18:45:51 2015 From: tim.peters at gmail.com (Tim Peters) Date: Thu, 30 Jul 2015 11:45:51 -0500 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: Oops! Forgot one: [Guido] > ... create new timedelta-ish classes that implement "human" arithmetic Note that there's an annoying inelegance here: after datetime2 = datetime1 + timedeltaish # or subtraction then what does: datetime2 - datetime1 produce? Knowledge of the _kind_ of timedelta-ish object used to produce datetime2 is long gone, so it may not be the case that datetime2 - datetime1 == timedeltaish or even produce an object of the same class as timedeltaish. Of course that's never a problem today. If the inelegance is thought to be unbearable, I suppose new timedelta-ish classes could provide an explicit class method to subtract datetime instances (yielding "the right" timedelta-ish object of the class). From chris.barker at noaa.gov Thu Jul 30 18:46:15 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 09:46:15 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 2:25 AM, Guido van Rossum wrote: > Perhaps the original intent was that "days" means calendar days, and for >> naive datetimes, it turns out to be the same thing, but that is not what >> the implementation does, and given that it supports seconds and >> microseconds, but not months or years, the API is pretty clearly designed >> for timespans, not calendar definitions. >> > > I can assure you that the implementation carefully matches the original > intent. > I apologise -- I'm afraid I've dragged this out more than necessary due to my misunderstanding -- see my other posts if anyone cases about that. > Even if I wouldn't design it that way today (which honestly I haven't > decided whether I would or not) I don't want to change anything about the > observable behavior[1] that would give a different outcome, > of course not. > no matter how much more "correct" you believe a different outcome would be. > There is "correct" and incorrect, but I"m not arguing that anything is incorrect about the current behavior -- I thought a timedelta was a duration, but I was wrong, it is a Period in units of days (I think!), and sure it apparently does that right. The docs sure need clarifying, though. > The road to improvement that I encourage everyone to explore: add an > is_dst flag (with a different name) > +1 absolutely > and create new timedelta-ish classes that implement "human" arithmetic > (similar to what pytz offers) and "strict" arithmetic (similar to > [NJ]odaTime, IIUC). Separately, standardized access in the stdlib to a tz > database (see another thread). > Sounds good to me -- both are very useful, and clearly defining which is which makes lots of sense. > [1] The *implementation* may change, but not in a way that changes > observable behavior, except for the addition of new attributes, parameters > and/or methods. > hmm -- given that, then perhaps timedelta could be extended to do more rich Period arithmetic without breaking the current behavior. But I suppose the new PeriodDelta object would have to be fleshed out first, to see if that's possible. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Thu Jul 30 18:53:21 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 09:53:21 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 9:45 AM, Tim Peters wrote: > Oops! Forgot one: > > [Guido] > > ... create new timedelta-ish classes that implement "human" arithmetic > > Note that there's an annoying inelegance here: after > > datetime2 = datetime1 + timedeltaish # or subtraction > > then what does: > > datetime2 - datetime1 > > produce? yup -- with two (or three!) different flavors of a delta, what can you do? > Of course that's never a problem today. If the inelegance is thought > to be unbearable, I suppose new timedelta-ish classes could provide an > explicit class method to subtract datetime instances (yielding "the > right" timedelta-ish object of the class). > Which makes me think -- is it important that there is ONE datetime object, with two delta objects? or should there be two timedelta objects? That might provide a more obvious API -- which kind of arithmetic do you want to do with these? But also, it would open the door to different implementations: for instance, if your primary goal is to support Duration arithmetic, it may make sense to store the datetime in UTC always, and only mess with time zones on I/O. And you may want to store as "microseconds since year 1" directly as well. Of course, easy conversion between the two would be critical. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From felipe.nospam.ochoa at gmail.com Thu Jul 30 19:06:51 2015 From: felipe.nospam.ochoa at gmail.com (Felipe Ochoa) Date: Thu, 30 Jul 2015 13:06:51 -0400 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: I like the terms Period arithmetic and duration arithmetic. In those terms, what we currently have is the following: * "local/naive" datetime (no tzinfo) + timedelta is period arithmetic, where timedelta is a restricted form of period that supports only days, hours, minutes, seconds, and milliseconds. (Which is equivalent to mixed-radix seconds, as Tim has pointed out) * "aware" datetime (with tzinfo) + timedelta is sort of like period arithmetic, though Noda doesn't define this operation. It is equivalent to: 1) remove the tzinfo to get a local/naive dt 2) perform period arithmetic 3) attach the tzinfo again to get an aware dt. I'm fine extending the Noda definition of "period arithmetic" to cover this case I think Guido and others have suggested we add Duration and Period objects which will implement datetime arithmetic just like in Noda. The only difference in our model would be that instead of LocalDateTime vs ZonedDateTime, we have just datetime, with and without tzinfo. I am very much +1 for this idea, and will write up a Duration object in the next couple of days -Felipe On Thursday, July 30, 2015, Chris Barker wrote: > On Thu, Jul 30, 2015 at 9:03 AM, Tim Peters > wrote: > >> "Naive arithmetic" was my neologism, starting in this batch of >> messages. The docs don't call the arithmetic anything, or acknowledge >> that more than one kind of arithmetic is possible. > > > Which is really something that needs to addressed! > > >> This batch of >> messages needed to call it _something_, so I made something up. >> > > Can we just use the Glossary borrowed from Noda? It doesn't define an > "arithmetic", but if we need that term, it could be "Period Arithmetic" and > "Duration Arithmetic". > > And I had assumed that your "naive arithmetic" was Duration arithmetic -- > i.e. a day is 24 hours, but apparently not. I'm still confused as to how > you can: (paraphrasing my understanding of your earlier post): > > Convert the datetime to a timedelta from year 1 -- add the timedelta -- > convert back to a datetime. I suppose it's a failure of mine to understand > how datetime uses the tzinfo object, but this description sure sounds to me > like you'd get a datetime that really represented 24 hours later, not 23 or > 25 (or something else...) > > Anyway, my current understanding is that the current implementation of > datetime and timedelta is "Period Arithmetic", with only Periods defined in > units of days (fraction days, down to microsecond resolution). > > Is that correct? > > The kind of arithmetic >> Python implements is the only kind that delivers correct answers >> _within_ the naive time model,. so I've been calling it "naive >> arithmetic" - in the sense of "the arithmetic behavior required by the >> naive time model". >> > > Sure -- but we really need the docs to clarify what the heck happens when > you have a tz-aware datetime. > > I'd offer to write a patch for the docs, but as you can see, I'm still > pretty confused! > > > In any case, while >> mixed datetime/timedelta arithmetic supports only a small subset of >> what people want in the way of "calendar operations", it is an >> exceedingly useful subset on its own, _and_ in implementing fancier >> operations. It was a great start. >> > > Well, yes. I was ecstatic when datetime was introduced, and have found it > very, very useful since then. However, not for "calendar operations" > (Period Arithmetic) , nor for tz-aware datetimes. (because I don't have > much need for these) > > And unfortunately, I think the implementation of timedelta makes it > impossible to extend to richer Period Arithmetic -- it fundamentally uses > unit sof days, and has no way to encode any other "Period" unit -- i.e. > months or years. > > The implementation could fully support Duration Arithmetic, so it's a bit > of shame that that wasn't chosen in the first place. > > > I also (naively :-) assumed that people interested in strict arithmetic >> would >> > just keep using the POSIX timestamps used by the time module. >> > > Well, that explains it -- but no, the time module is very limited and > painful to use ;-) -- I was all for Datetime, even though my primary use > cases are all Duration arithmetic. > > -Chris > > > -- > > Christopher Barker, Ph.D. > Oceanographer > > Emergency Response Division > NOAA/NOS/OR&R (206) 526-6959 voice > 7600 Sand Point Way NE (206) 526-6329 fax > Seattle, WA 98115 (206) 526-6317 main reception > > Chris.Barker at noaa.gov > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Thu Jul 30 19:13:33 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 13:13:33 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 12:43 PM, Alexander Belopolsky wrote: > I would like to make a specific proposal ... I posted my proposal on github [1] and made minor changed there. [1]: https://github.com/abalkin/ltdf/blob/master/README.rst From chris.barker at noaa.gov Thu Jul 30 19:20:12 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 10:20:12 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: Thanks Felipe -- nice and concise and clear! A couple notes: * "local/naive" datetime (no tzinfo) + timedelta is period arithmetic, > where timedelta is a restricted form of period that supports only days, > hours, minutes, seconds, and milliseconds. (Which is equivalent to > mixed-radix seconds, as Tim has pointed out) > With a naive datetime, doesn't this also mean timedelta supports Duration arithmetic? without any DST uglyness, they are the same thing, at least with well defined units like days. At least I've used it this way for years, with no noticed ill effects. Have I just been lucky? > * "aware" datetime (with tzinfo) + timedelta is sort of like period > arithmetic, though Noda doesn't define this operation. It is equivalent to: > 1) remove the tzinfo to get a local/naive dt 2) perform period arithmetic > 3) attach the tzinfo again to get an aware dt. > We need to add some text along these lines to the docs -- that would have helped a lot. > I'm fine extending the Noda definition of "period arithmetic" to cover > this case > Is it really different than Period Arithmetic that only support units of days? Anyway, not a distinction that matters. I am very much +1 for this idea, and will write up a Duration object in > the next couple of days > great -- would it: Convert to UTC Do the math Convert back to local time zone? Or is there another way to handle it? -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From ethan at stoneleaf.us Thu Jul 30 19:59:38 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Thu, 30 Jul 2015 10:59:38 -0700 Subject: [Datetime-SIG] "Use cases" (was Re: [Python-Dev] Status on PEP-431 Timezones) In-Reply-To: References: Message-ID: <55BA660A.9040302@stoneleaf.us> On 07/30/2015 09:19 AM, Chris Barker wrote: > Is there any disagreement that both Duration and Period (to use the > Noda terms) operations have important and common use-cases? Important, yes. Common? Not sure. Still worth supporting, though. > Granted, if not, that doesn't tell us anything about what should be > supported in the stdlib, but it seems odd to be arguing about something > this basic. The arguments, as far as I can tell, have been about what the stdlib actually supports. -- ~Ethan~ From tritium-list at sdamon.com Thu Jul 30 19:46:46 2015 From: tritium-list at sdamon.com (Alexander Walters) Date: Thu, 30 Jul 2015 13:46:46 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: Message-ID: <55BA6306.2030106@sdamon.com> Just looking at the attribute '.first' does not tell you what it is intended to mean. '.is_dst' of one spelling or another is unambiguous; "This datetime object is in the 'special'[1] time." '.first' also makes the default 'True', and it might just be me, but I don't like that aesthetically. [1] Arguments over if DST is the new standard time or not in some parts of the world not withstanding On 7/30/2015 12:43, Alexander Belopolsky wrote: > I would like to make a specific proposal on a narrow topic of how to > handle ambiguities inherent in representing time instances in common > time zones. The following is a rough sketch where I attempted to > identify the areas affected by the proposal and outline the proposed > changes. > > ======= > Rationale > ======= > > In the most world locations there have been and will be times when > local clocks are moved back. In those times intervals are introduced > in which local clocks show the same time twice in the same day. In > these situations, the information displayed on a local clock (or > stored in a Python datetime instance) is insufficient to identify a > particular instance in time. The proposed solution is to add a > boolean flag to the datetime instances that will distinguish between > the two ambiguous times. > > ======= > Proposal > ======= > > The "first" flag > ------------------ > > We propose adding a boolean member called "first" to the instances of > datetime.time and datetime.time classes. This member will have the > value True for all instances except those that represent the second > (chronologically) moment in time in an ambiguous case. > > Affected APIs > ------------------ > > Attributes > ............... > > Instances of datetime.time and datetime.datetime will get a new > boolean attribute called "first." > > Constructors > .................... > > The __new__ methods of the datetime.time and datetime.datetime classes > will get a new keyword-only argument first=True that will control the > value of the "first" attribute in the returned instance. > > Methods > ............. > > The replace() methods methods of the datetime.time and > datetime.datetime classes will get a new keyword-only argument > first=True that will control the value of the "first" attribute in the > returned instance. > > Affected behaviors > ------------------------- > > Implementations of tzinfo > ....................................... > > Subclasses of datetime.tzinfo will read the values of "first" in > utcoffset() and dst() methods and set it appropriately in the > instances > returned by the fromutc() method. No change to the signatures of > these methods is proposed. > > Pickle size > -------------- > Pickle sizes for the datetime.datetime and datetime.time objects will > not change. The "first" flag will be encoded in the first bit of the > byte that currently stores the 4th byte of the datetime.datetime > pickle payload or the 1st byte of the datetime.time. In the current > implementation [1] these bytes are used to store hour value (0-23) and > the first bit is always 0. Note that first=True will be encoded as 0 > in the first bit and first=False as 1. (This change only affects > pickle format. In C implementation, the "first" member will get a > full byte to store the actual boolean value.) > > Temporal arithmetics > ---------------------------- > The value of "first" will be ignored in all operations except > utcoffset() and dst() methods of tzinfo implementations and __eq__ and > __hash__ methods of the datetime.datetime and datetime.time classes. > The only methods that will be able to produce nonzero values of > "first" are __new__ and replace() methods of the datetime.datetime and > datetime.time classes and fromutc() method of some tzinfo > implementations. > > Backward and forward compatibility > ----------------------------------------------- > > This proposal will have no effect on the programs that do not set the > "first" flag explicitly or use tzinfo implementations that do. > Pickles produced by older programs will remain fully forward > compatible. Only datetime/time instances with first=False pickled in > the new versions will become unreadable by the older Python versions. > Pickles of instances with first=False will remain unchanged. > > > ================== > Questions and Answers > ================== > > 1. Why not call the new flag "isdst"? > > Alice: Bob - let's have a stargazing party at 01:30 AM tomorrow! > Bob: Should I presume initially that summer time (for example, > Daylight Saving Time) is or is not (respectively) in effect for the > specified time? > Allice: Huh? > > Bob: Alice - let's have a stargazing party at 01:30 AM tomorrow! > Alice: You know, Bob, 01:30 AM will happen twice tomorrow. Which one > do you have in mind? > Bob: I did not think about it, but let's pick the first. > > > [1]: https://hg.python.org/cpython/file/d3b20bff9c5d/Include/datetime.h#l17 > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > The PSF Code of Conduct applies to this mailing list: https://www.python.org/psf/codeofconduct/ From chris.barker at noaa.gov Thu Jul 30 20:03:37 2015 From: chris.barker at noaa.gov (Chris Barker - NOAA Federal) Date: Thu, 30 Jul 2015 11:03:37 -0700 Subject: [Datetime-SIG] "Use cases" (was Re: [Python-Dev] Status on PEP-431 Timezones) In-Reply-To: <55BA660A.9040302@stoneleaf.us> References: <55BA660A.9040302@stoneleaf.us> Message-ID: <3995070080207636748@unknownmsgid> Sent from my iPhone > On Jul 30, 2015, at 11:00 AM, Ethan Furman >> Is there any disagreement that both Duration and Period (to use the >> Noda terms) > Important, yes. Common? Not sure. Still worth supporting, though. > > The arguments, as far as I can tell, have been about what the stdlib actually supports. Well, yes, though I think that's been cleared up in recent posts -- so we're moving forward now! Thanks, -Chris From tim.peters at gmail.com Thu Jul 30 20:04:38 2015 From: tim.peters at gmail.com (Tim Peters) Date: Thu, 30 Jul 2015 13:04:38 -0500 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: [Tim] >> "Naive arithmetic" was my neologism, starting in this batch of >> messages. The docs don't call the arithmetic anything, or acknowledge >> that more than one kind of arithmetic is possible. [Chris Barker ] > Which is really something that needs to addressed! Eh. It doesn't really scratch an itch I have, although I realize other people have already scratched down to their bones ;-) Because of the latter, Python should address it. In the few cases I've needed (what Guido now calls "strict" or "timeline") arithmetic, it's just a matter of converting to UTC, doing the arithmetic there, and converting back to the originat tzinfo. These are easy, straightforward functions to write. They don't always get the right answers in the "problem hours" involving DST transitions, but that's not a problem with arithmetic, it's due to that conversions alone can't always deliver the right answers (due to the absence of a correctly updated is_dst-like information in datetime objects). > Can we just use the Glossary borrowed from Noda? It doesn't define an > "arithmetic", but if we need that term, it could be "Period Arithmetic" and > "Duration Arithmetic". I haven't had made time to study the glossary hard, so have no opinion as to whether it's adequate (or even sensible) for Python's purposes. > And I had assumed that your "naive arithmetic" was Duration arithmetic -- > i.e. a day is 24 hours, but apparently not. I'm still confused as to how you > can: (paraphrasing my understanding of your earlier post): > > Convert the datetime to a timedelta from year 1 -- add the timedelta -- > convert back to a datetime. I suppose it's a failure of mine to understand > how datetime uses the tzinfo object, but this description sure sounds to me > like you'd get a datetime that really represented 24 hours later, not 23 or > 25 (or something else...) > > Anyway, my current understanding is that the current implementation of > datetime and timedelta is "Period Arithmetic", with only Periods defined in > units of days (fraction days, down to microsecond resolution). > > Is that correct? As I lack expert knowledge of what "Period Arithmetic" means _exactly_,. I can't answer your question. But, really, it's dead easy to understand what datetime actually does: its _model_ is "naive time". In naive time, a day _is_ exactly 24 hours, and not even the _concept_ of "time zone" exists. Everything (well, almost ;-) ) about how arithmetic works _follows_ from that view of the world. The only irregularities are due to the lumpy nature of the Gregorian calendar (leap years, and months with differing numbers of days). There's no such thing as "time zones" in the naive time model. What endlessly screws some people up is that (almost) all that remains strictly true for arithmetic on datetime objects that _do_ have a fully functinoal tzinfo member. They _still_ follow the "naive time" model. The presence or absence of a tzinfo member makes (almost) no difference at all to arithmetic. I personally would have preferred that "aware" datetime objects use strict/timeline arithmetic instead, but it's not a big deal to me either way. > ... > Sure -- but we really need the docs to clarify what the heck happens when > you have a tz-aware datetime. Nothing at all changes about the arithmetic, _except_ when subtracting two aware datetime objects. Then the subtraction (in effect) converts both to UTC before subtracting. Because when mixing datetimes from _different_ "time zones", there's no plausible justification for considering them to both be in the _same_ "naive time". So in that specific case, strict/timeline arithmetic is done. And that's the source of the repeated "(almost)" repetitions earlier. Ah, BTW, comparison of two aware dateimes also acts in strict/timeline fashion. In my head, that's a consequence of how subtraction works, but not everyone has the benefit of my mental afflictions ;-) > I'd offer to write a patch for the docs, but as you can see, I'm still > pretty confused! Then, by all means, wait until clarity erupts ;-) I think the only strong clues about this now are buried in footnotes on the docs covering datetime's arithmetic operators. They explain exactly _what_ happens, but with no explanation of _why_ it works that way. "That sucks" would be fair. > ... > Well, yes. I was ecstatic when datetime was introduced, and have found it > very, very useful since then. Me too. Honest, has it actually become _less_ useful to you just because this batch of messages started? As many in the Python world can tell you, I _can_ be as obnoxious about being "anally correct" as anyone, and far more so than most. I disliked "naive time" at first glance. I was forced ;-) to implement it (Guido was my boss in real life at the time). But as I used it, I grew to like it a whole lot. Provided you embrace the "naive time" model for what it is, datetime is great. Nevertheless, I would have preferred that aware datetimes use strict/timeline arithmetic in all cases, and would have _greatly_ preferred addressing is_dst from the start. > However, not for "calendar operations" (Period Arithmetic) , nor for tz-aware > datetimes. (because I don't have much need for these) Then you _live_ in a "naive time" world. > And unfortunately, I think the implementation of timedelta makes it > impossible to extend to richer Period Arithmetic -- it fundamentally uses > unit sof days, and has no way to encode any other "Period" unit -- i.e. > months or years. Without taking time now to try to learn exactly what all the new buzz phrases mean, mixed datetime/timedelta arithemtic was never intended to handle all possible, or even all common, use cases for Period Arithmetic. Just the ones with inarguably clear meanings _in_ the naive time model. There is no possible argument about what, e.g., "day" or "week" mean in naive time: in naive time, their meanings as microsecond durations and as deltas between datetimes are the same. But as microsecond durations, "month" and "year" have no clear meanings even in naive time, so timedelta doesn't support those units. > The implementation could fully support Duration Arithmetic, so it's a bit of > shame that that wasn't chosen in the first place. A timedelta represents a specific number of microseconds. That's all it does. When adding/subtracting to;from a datetime, the result is that many microseconds removed in "naive time". That timedelta's "day" is equivalent to naive time's "day" is a consequence of the naive time model. They work flawlessly in tandem. They may not work worth shit together in any other model of time. Note that Guido has already proposed adding new timedelta-ish classes, to "do the right things" for other models of time (well, _the_ other model: the messy ways local clocks actually work, although still ignoring the possibility of leap seconds) and/or fancier kinds of calendar operations (a commonly used phrase in these messages, which I won't presume to translate into the new vocabulary I haven't yet mastered). From alexander.belopolsky at gmail.com Thu Jul 30 20:08:08 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 14:08:08 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: <55BA6306.2030106@sdamon.com> References: <55BA6306.2030106@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 1:46 PM, Alexander Walters wrote: > '.is_dst' of one spelling or another is unambiguous; .. and is "clearly" defined by the POSIX standard as follows: "A positive or 0 value for tm_isdst shall cause mktime() to presume initially that Daylight Savings Time, respectively, is or is not in effect for the specified time. A negative value for tm_isdst shall cause mktime() to attempt to determine whether Daylight Savings Time is in effect for the specified time." [1] Call me when you find two people who can agree on what this means. [1]: http://pubs.opengroup.org/onlinepubs/009695399/functions/mktime.html From tritium-list at sdamon.com Thu Jul 30 20:15:16 2015 From: tritium-list at sdamon.com (Alexander Walters) Date: Thu, 30 Jul 2015 14:15:16 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: <55BA6306.2030106@sdamon.com> Message-ID: <55BA69B4.4040708@sdamon.com> On 7/30/2015 14:08, Alexander Belopolsky wrote: > On Thu, Jul 30, 2015 at 1:46 PM, Alexander Walters > wrote: >> '.is_dst' of one spelling or another is unambiguous; > .. and is "clearly" defined by the POSIX standard as follows: > > "A positive or 0 value for tm_isdst shall cause mktime() to presume > initially that Daylight Savings Time, respectively, is or is not in > effect for the specified time. A negative value for tm_isdst shall > cause mktime() to attempt to determine whether Daylight Savings Time > is in effect for the specified time." [1] > > > Call me when you find two people who can agree on what this means. > > > [1]: http://pubs.opengroup.org/onlinepubs/009695399/functions/mktime.html We are not talking about implementing the POSiX argument to mktime, and I dont think anyone on the list ever was. .is_dst is a bool flag for 'if set, the time represented is in the DST time, if not set, it is in the non-DST time'. '.first' doesnt even imply a bool. "First what?" someone might ask. From tritium-list at sdamon.com Thu Jul 30 20:00:56 2015 From: tritium-list at sdamon.com (Alexander Walters) Date: Thu, 30 Jul 2015 14:00:56 -0400 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: Message-ID: <55BA6658.6080409@sdamon.com> On 7/30/2015 10:48, ISAAC J SCHWABACHER wrote: > Australia/Melbourne is a time zone, +1000 is an offset, and EST is an accident waiting to happen. > > ijs > Australia/Melbourne is the *Olsan name* for a time zone. +1000 is the current legal definition of that timezone in terms of a GMT offset, EST is the common name of one of many timezones, likely US Eastern Standard Time, but could be one of many. Timezones are political constructs that developers need to work around, not the other way around. Olsan's names are not written in law anywhere (that I know of). From ischwabacher at wisc.edu Thu Jul 30 20:22:49 2015 From: ischwabacher at wisc.edu (ISAAC J SCHWABACHER) Date: Thu, 30 Jul 2015 18:22:49 +0000 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: <55BA6658.6080409@sdamon.com> References: <55BA6658.6080409@sdamon.com> Message-ID: Down with the governments of the world! Arthur David Olson for supreme leader! ________________________________________ From: Datetime-SIG on behalf of Alexander Walters Sent: Thursday, July 30, 2015 13:00 To: datetime-sig at python.org Subject: Re: [Datetime-SIG] Clearing up terminology On 7/30/2015 10:48, ISAAC J SCHWABACHER wrote: > Australia/Melbourne is a time zone, +1000 is an offset, and EST is an accident waiting to happen. > > ijs > Australia/Melbourne is the *Olsan name* for a time zone. +1000 is the current legal definition of that timezone in terms of a GMT offset, EST is the common name of one of many timezones, likely US Eastern Standard Time, but could be one of many. Timezones are political constructs that developers need to work around, not the other way around. Olsan's names are not written in law anywhere (that I know of). _______________________________________________ Datetime-SIG mailing list Datetime-SIG at python.org https://mail.python.org/mailman/listinfo/datetime-sig The PSF Code of Conduct applies to this mailing list: https://www.python.org/psf/codeofconduct/ From skip.montanaro at gmail.com Thu Jul 30 20:24:07 2015 From: skip.montanaro at gmail.com (Skip Montanaro) Date: Thu, 30 Jul 2015 13:24:07 -0500 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <55BA6658.6080409@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 1:22 PM, ISAAC J SCHWABACHER wrote: > Arthur David Olson for supreme leader! As long as it's a position which reports to the BDFL, I'm down with that. :-) Skip From alexander.belopolsky at gmail.com Thu Jul 30 20:33:02 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 14:33:02 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: <55BA69B4.4040708@sdamon.com> References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 2:15 PM, Alexander Walters wrote: > We are not talking about implementing the POSiX argument to mktime, and I > dont think anyone on the list ever was. .is_dst is a bool flag for 'if set, > the time represented is in the DST time, if not set, it is in the non-DST > time'. > > '.first' doesnt even imply a bool. "First what?" someone might ask. I have no emotional attachment to any particular name. If you like "is_first" better than "first" on the grammatical grounds - I have no problem changing the spelling. I do have two problems with calling it isdst: 1. Whether we want to implement the POSIX standard or not, but tm_isdst member is the POSIX solution to the problem at hand and if we give datetime objects a member variable called isdst, but change the semantics, we will see no end of bug reports. (And since no one understands POSIX semantics, we have no choice but to change them. :-) 2. It will be very confusing to have t.is_dst ? t.dst() which will happen whenever you have an ambiguity due to a change in the standard time. From ethan at stoneleaf.us Thu Jul 30 20:33:33 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Thu, 30 Jul 2015 11:33:33 -0700 Subject: [Datetime-SIG] naive DateTime, aware DateTime, precise DateTIme Message-ID: <55BA6DFD.8040102@stoneleaf.us> Instead of making a new timedelta object, which, after all, represents exactly what it says, why don't we make a new DateTime and Time that do the duration arithmetic? Anyone who wants that behaviour has to explicitly use the type so there would be no backwards compatibility issues with the existing DateTime, Time, or timedelta objects. -- ~Ethan~ From alexander.belopolsky at gmail.com Thu Jul 30 20:40:22 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 14:40:22 -0400 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: <55BA6658.6080409@sdamon.com> References: <55BA6658.6080409@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 2:00 PM, Alexander Walters wrote: > EST is the common name of one of many timezones, likely US Eastern Standard > Time, but could be one of many. You are the third person on this list who saw $ TZ=Australia/Melbourne date +"%c%z" Thu 30 Jul 2015 10:21:18 AM EST+1000 and decided that EST is "likely US Eastern Standard Time." And neither of the following two facts have stopped you: 1. Melbourne is in Australia, not in the US. 2. The DST is in effect in the Eastern US in July. From guido at python.org Thu Jul 30 21:18:15 2015 From: guido at python.org (Guido van Rossum) Date: Thu, 30 Jul 2015 21:18:15 +0200 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 6:31 PM, Tim Peters wrote: > [Guido] > > ... > > The road to improvement that I encourage everyone to explore: add an > is_dst > > flag (with a different name) > > There is no path whatsoever to "correct in all cases" in its absence, > so this should be the top priority for those to whom "correct in all > cases" is their top priority. > And that's why I listed it first. :) > > and create new timedelta-ish classes that implement "human" > > arithmetic (similar to what pytz offers) > > This part seems confused to me: beyond wrapping zoneinfo in a pile of > tzinfo objects, pytz's secondary thrust appears to be "correct in all > cases" involving DST transition times. Doing things like allowing to > correctly distinguish between the ambiguous times when DST ends is, if > I understand anything of your intent, a case of better implementing > "strict time" than of implementing "human time". IOW, to the extent > arithmetic in pytz acts like "human time", it inherits that behavior > from what Python already does. > Oops, I should have checked my facts. I misremembered what pytz does. Indeed "human time" is not one of its features. > > and "strict" arithmetic (similar to [NJ]odaTime, IIUC). > > That sounds right. > > > Separately, standardized access in the stdlib to a tz database (see > another thread). > > That's pytz's primary thrust. Also part of dateutil's thrust > (dateutil leaves Python's arithmetic results entirely alone in all > cases, but also supplies many "calendar operations" useful regardless > of whether you use _its_ wrapping of zoneinfo and/or Windows registry > databases). > Aha! I'd forgotten about dateutil -- it claims "computing of relative deltas (next month, next year, next monday, last week of month, etc)" which sounds more like my "human time" (at least the "next month, next year" part). > > [1] The *implementation* may change, but not in a way that changes > > observable behavior, except for the addition of new attributes, > parameters > > and/or methods. > > I'm afraid that may not be entirely possible. For example, if > datetime objects grow a new attribute, (like some spelling of .is_dst) > then repr() presumably needs to display it. But I know what you mean > ;-) > ;-) -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Thu Jul 30 21:23:57 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 12:23:57 -0700 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 11:33 AM, Alexander Belopolsky < alexander.belopolsky at gmail.com> wrote: > I have no emotional attachment to any particular name. The intent is for this new flag to be used for that ambiguous time period during the DST transitions. However, at least in theory, it COULD be used for any time -- i.e. I was US Eastern Standard Time, even though it's the middle of the summer. WHat a user should do is use a tzinfo object that is specifically the Easter Time zone offset, with no DST. (is this spelled "EST" or something in the Olsen database?). But we need to (a) be really clear in the docs whether the flag is consulted any any other time. and (b) probably be really careful in the code to make sure the flag is set appropriately at all times. and, in this case, using a name like "is_dst" would imply to me that you could turn DST on or off at any time. Whereas .is_first would mean nothing to me at a glance, so I'd go read the docs, and hopefully get a nice explanation ;-) -Chris If you like > "is_first" better than "first" on the grammatical grounds - I have no > problem changing the spelling. > > I do have two problems with calling it isdst: > > 1. Whether we want to implement the POSIX standard or not, but > tm_isdst member is the POSIX solution to the problem at hand and if we > give datetime objects a member variable called isdst, but change the > semantics, we will see no end of bug reports. (And since no one > understands POSIX semantics, we have no choice but to change them. :-) > > 2. It will be very confusing to have t.is_dst ? t.dst() which will > happen whenever you have an ambiguity due to a change in the standard > time. > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > The PSF Code of Conduct applies to this mailing list: > https://www.python.org/psf/codeofconduct/ > -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Thu Jul 30 21:30:42 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 15:30:42 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: <55BA6306.2030106@sdamon.com> References: <55BA6306.2030106@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 1:46 PM, Alexander Walters wrote: > '.first' also makes the default 'True', and it might just be me, but I don't > like that aesthetically. No, it is not just you. I also struggled with that and had to specify that first=False is encoded as 1 in the pickle format for backward compatibility reasons. Obviously, we cannot have a flag called "second." [1] For me, the obvious way to differentiate two moments in time is by their chronological order and defaulting on an earlier time in the face of ambiguity is usually the smart choice in real life. (It is better to come an hour earlier to an important meeting than an hour later.) A possible alternative to first=True (or is_first=True) would be later=False (or is_later=False), but again you you ask me which 01:30 AM I want to pick - I will probably answer "the first" rather than "not the later". Although I will be the first to admit that I don't have the perfect name for this flag - let's leave the naming part to the time when we all agree on everything else. If you don't like "first" - call it "ltdf" (Local Time Disambiguation Flag) for now. [1]: https://github.com/abalkin/ltdf/blob/master/README.rst#questions-and-answers From alexander.belopolsky at gmail.com Thu Jul 30 21:34:52 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 15:34:52 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 3:23 PM, Chris Barker wrote: > Whereas .is_first would mean nothing to me at a glance, so I'd go read the > docs, and hopefully get a nice explanation ;-) Did you read ? From chris.barker at noaa.gov Thu Jul 30 21:35:08 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 12:35:08 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <55BA6658.6080409@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 11:40 AM, Alexander Belopolsky < alexander.belopolsky at gmail.com> wrote: > You are the third person on this list who saw > > $ TZ=Australia/Melbourne date +"%c%z" > Thu 30 Jul 2015 10:21:18 AM EST+1000 > > and decided that EST is "likely US Eastern Standard Time." And > neither of the following two > facts have stopped you: > > 1. Melbourne is in Australia, not in the US. > 2. The DST is in effect in the Eastern US in July. nor that an offset of +1000 is not, and never was or will be the offset for "US Eastern Standard Time." All good proof that short names for semi timezones is very, very error prone! (despite the fact that I do it all the time when I write) I'm pretty sure the iso 8601 spec only puts offsets in the string -- uttin gboth an offset and a abbreviation seems like trouble to me :-) But we've got a long way to go before we need to bikeshed the __str__ and __repr__ implementations... -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From guido at python.org Thu Jul 30 21:38:25 2015 From: guido at python.org (Guido van Rossum) Date: Thu, 30 Jul 2015 21:38:25 +0200 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 6:46 PM, Chris Barker wrote: > [...] I thought a timedelta was a duration, but I was wrong, it is a > Period in units of days (I think!), and sure it apparently does that right. > Honestly I don't think timedelta cleanly maps to either of those concepts[1]. While it's true that when a timedelta is added to a datetime it behaves like a Period, when timedeltas are added or subtracted they behave more like Durations: adding several timedeltas just results in modding the number of seconds to be in [0, 86400) and assigning the rest to days (e.g. a timedelta of -1 seconds ends up being -1 days and +86399 seconds). So I don't think it can be extended to provide more human time operations. [1] From http://nodatime.org/1.2.x/userguide/concepts.html; Duration is a simple number of ticks, while a Period is a vector of calendar-based units like year, month, etc. -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Thu Jul 30 21:40:07 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 15:40:07 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 3:23 PM, Chris Barker wrote: > But we need to (a) be really clear in the docs whether the flag is consulted > any any other time. and (b) probably be really careful in the code to make > sure the flag is set appropriately at all times. "This member will have the value True for all instances except those that represent the second (chronologically) moment in time in an ambiguous case." [1] Does this require any more clarification? If so, can you suggest it? [1]: https://github.com/abalkin/ltdf/blob/master/README.rst#the-first-flag From chris.barker at noaa.gov Thu Jul 30 21:48:56 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 12:48:56 -0700 Subject: [Datetime-SIG] naive DateTime, aware DateTime, precise DateTIme In-Reply-To: <55BA6DFD.8040102@stoneleaf.us> References: <55BA6DFD.8040102@stoneleaf.us> Message-ID: On Thu, Jul 30, 2015 at 11:33 AM, Ethan Furman wrote: > Instead of making a new timedelta object, which, after all, represents > exactly what it says, why don't we make a new DateTime and Time that do the > duration arithmetic? > I like that -- as I read Tim's last post, it struck me that the focus as been on the timedelta object, but that's not where the confusion is -- you are right: a timedelta object represents a span of time, in microseconds. exactly what it says. The confusion comes in when a timedelta interacts with a datetime and a tzinfo object. I'm not sure where in the code the actual logic lies, if it does (or could) lie with the DurationDateTime object, then that object coulds use the existing timedelta object for its delta. On the other hand, a PeriodDateTime object could not use the existing timedelta object -- as it can only represent an actual time span, and not something like "months" or "years". And that would clear up the "what kind of delta to return from subtraction" issue. Also -- it would open the door to a different implementation of datetime and timezones -- i.e. always store UTC, translate to the prescribed time zone on I/O. A use case I'm not sure about though -- how often would folks need to do both kinds of arithmetic on the same datetime objects? If that's a common use case, it would be a shame to split that objects into different types. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Thu Jul 30 21:50:05 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 15:50:05 -0400 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 3:18 PM, Guido van Rossum wrote: > On Thu, Jul 30, 2015 at 6:31 PM, Tim Peters wrote: >> >> [Guido] >> > ... >> > The road to improvement that I encourage everyone to explore: add an >> > is_dst >> > flag (with a different name) >> >> There is no path whatsoever to "correct in all cases" in its absence, >> so this should be the top priority for those to whom "correct in all >> cases" is their top priority. > > > And that's why I listed it first. :) "first" it is :-) https://github.com/abalkin/ltdf/blob/master/README.rst#the-first-flag From tim.peters at gmail.com Thu Jul 30 21:51:10 2015 From: tim.peters at gmail.com (Tim Peters) Date: Thu, 30 Jul 2015 14:51:10 -0500 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: [Tim, to Guido] > Do you really intend that we use all three: "classic arithmetic", > "human arithmetic", and "strict arithmetic"?. If so, I don't grasp > the intended distinction between "classic" and "human".(both seem to > be the same as what I've been calling "naive arithmetic": the > arithmetic Python currently implements for binary arithmetic operators > involving at least one datetime object). I _think_ I've divined the intent now: - "classic arithmetic": what Python datetime arithmetic currently does - "strict arithmetic": aka timeline arithmetic, what Lennart wants - "human arithmetic" aka "calendar operations" - including at least relative deltas involving units (like months and years) which have no fixed meaning in naive time This intersects with "classic arithmetic" (current "datetime +- timedelta"). but unlike those cases of classic arithmetic is intended to cover both the "naive" and "UTC timeline" models of time. For example, there "should be" a way to spell "an hour from now" that follows "strict arithmetic" rules when the datetime is aware. Or not ;-) From ischwabacher at wisc.edu Thu Jul 30 21:55:36 2015 From: ischwabacher at wisc.edu (ISAAC J SCHWABACHER) Date: Thu, 30 Jul 2015 19:55:36 +0000 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: [Tim] > But, really, it's dead easy to understand what datetime actually does: > its _model_ is "naive time". In naive time, a day _is_ exactly 24 > hours, and not even the _concept_ of "time zone" exists. Everything > (well, almost ;-) ) about how arithmetic works _follows_ from that > view of the world. The only irregularities are due to the lumpy > nature of the Gregorian calendar (leap years, and months with > differing numbers of days). There's no such thing as "time zones" in > the naive time model. > > What endlessly screws some people up is that (almost) all that remains > strictly true for arithmetic on datetime objects that _do_ have a > fully functinoal tzinfo member. They _still_ follow the "naive time" > model. The presence or absence of a tzinfo member makes (almost) no > difference at all to arithmetic. I personally would have preferred > that "aware" datetime objects use strict/timeline arithmetic instead, > but it's not a big deal to me either way. [ijs] I thought I understood what you were saying until now, but through this entire discussion I have been under the impression that you felt the exact opposite of that last sentence (except for the not being a big deal part). > Nothing at all changes about the arithmetic, _except_ when subtracting > two aware datetime objects. Then the subtraction (in effect) converts > both to UTC before subtracting. Because when mixing datetimes from > _different_ "time zones", there's no plausible justification for > considering them to both be in the _same_ "naive time". So in that > specific case, strict/timeline arithmetic is done. And that's the > source of the repeated "(almost)" repetitions earlier. > > Ah, BTW, comparison of two aware dateimes also acts in strict/timeline > fashion. In my head, that's a consequence of how subtraction works, > but not everyone has the benefit of my mental afflictions ;-) So once we have an is_dst bit, what will be the result of tz = timezone('America/Chicago') datetime(2013, 11, 3, 1, 30, tzinfo=tz, is_dst=True) - datetime(2013, 11, 3, 1, 0, tzinfo=tz, is_dst=False) ? How can it be consistent with current behavior and be anything other than timedelta(0, 1800), even though the first time preceded the second? ijs From guido at python.org Thu Jul 30 22:05:01 2015 From: guido at python.org (Guido van Rossum) Date: Thu, 30 Jul 2015 22:05:01 +0200 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: On Thu, Jul 30, 2015 at 6:03 PM, Tim Peters wrote: > [Guido] > > ... > > I also never meant the term "naive" to be used for the existing > arithmetic > > rules for tz-aware datetime objects -- I always meant "naive" to refer to > > tz-less datetime objects. > > "Naive arithmetic" was my neologism, starting in this batch of > messages. The docs don't call the arithmetic anything, or acknowledge > that more than one kind of arithmetic is possible. This batch of > messages needed to call it _something_, so I made something up. > Cool. I missed that one message out of 100s. :-) > The docs do briefly explain the "native time" _model_ (and acknowledge > that more than one kind of model is possible). I assume you meant naive, not native. > The kind of arithmetic > Python implements is the only kind that delivers correct answers > _within_ the naive time model,. so I've been calling it "naive > arithmetic" - in the sense of "the arithmetic behavior required by the > naive time model". > Sure. > Which is an unfortunate verbal mess, in large part because "naive > arithmetic" is used for _both_ what the docs call "naive objects" and > "aware objects". Then again, calling _anything_ "naive" in the docs > was probably also unfortunate from the start ;-) > It was definitely naive. :-) > > I would prefer something like "classic arithmetic" for tz-aware datetime > objects. > > Read literally, that doesn't make sense to me, and I can't tease out > the intent. That is, calling an object (whatever it is) a kind of > arithmetic (whatever it is) doesn't make sense to me. I had guessed, > that you wanted to call the kind of _arithmetic_ currently implemented > "classic arithmetic". but in the next sentence you seem to want to > call that "human arithmetic": > And yet that is what I meant, i.e., calling the current arithmetic for tz-aware objects classic, because I wanted to avoid naming it naive (because of the aforementioned verbal mess). > > We can then introduce two new terms for different forms of arithmetic: > > "human arithmetic" for the form that can do things like "+ 2 months" in a > > way that (mostly) matches human expectations, and "strict arithmetic" for > > the form that Lennart needs (essentially move a specific number of > seconds > > along UTC). > > Do you really intend that we use all three: "classic arithmetic", > "human arithmetic", and "strict arithmetic"?. If so, I don't grasp > the intended distinction between "classic" and "human".(both seem to > be the same as what I've been calling "naive arithmetic": the > arithmetic Python currently implements for binary arithmetic operators > involving at least one datetime object). > Yes, I meant to introduce human arithmetic as a third form, to support adding e.g. months or years, while classic and strict arithmetic shouldn't. (Since timedelta doesn't keep its days and seconds separated, it's not really a Period, so I think it shouldn't be extended further. And adding months is a requirement for human arithmetic -- e.g. I was called a bad word on Twitter yesterday because timedelta doesn't support months.) > Anyway, because "strict arithmetic" more-or-less literally means > "arithmetic that wholly satisfies the requirements of a given model", > in isolation the phrase leaves the question of _which_ model open. > So, as was suggested later in the thread, I'd prefer "timeline > arithmetic" (and couldn't care less whether it's called "timeline", > "time line", or both). And I'll conveniently overlook that "timeline > arithmetic" on its own leaves open _which_ timeline (naive or > timezone) is intended ;-) > Sure. > > FWIW (not much, we're stuck with it now), my intention with classic > > arithmetic was to approximate human arithmetic, but only for cases that > > didn't require messy heuristics such as "Feb 29, 2016 plus one year" or > "Jan > > 31, 1956 minus 9 months". > > I always viewed the _model_ ("naive time") as primary. Specific > arithmetic requirements (for builtin arithmetic operators) then > necessarily followed from the choice of model. In any case, while > mixed datetime/timedelta arithmetic supports only a small subset of > what people want in the way of "calendar operations", it is an > exceedingly useful subset on its own, _and_ in implementing fancier > operations. It was a great start. > I agree. :-) > ... > > > I also (naively :-) assumed that people interested in strict arithmetic > would > > just keep using the POSIX timestamps used by the time module. > > > > >> (BTW, historically, early versions of Python datetime had a separate > >> datetime subclass called datetimetz (IIRC), but the final design got > >> rid of this unnecessary complexity.) > > > I don't believe that was ever released, but it's possible we contemplated > > that and even implemented it in an early pure-Python prototype. > > FWIW, IIRC it did exist in an early prototype but was discarded before > it was even halfway implemented. > I stand corrected. My memory seems to be failing -- I also thought there was a datetime PEP, but I guess we avoided the PEP process (even though datetime was added in 2.3, well after PEP 1 was written) because we were all working in the same office. (Or do I misremember that too? :-) -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Thu Jul 30 22:06:20 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 13:06:20 -0700 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: On Thu, Jul 30, 2015 at 12:51 PM, Tim Peters wrote: > I _think_ I've divined the intent now: > > - "classic arithmetic": what Python datetime arithmetic currently does > > - "strict arithmetic": aka timeline arithmetic, what Lennart wants > aka "Duration Arithmetic" > - "human arithmetic" aka "calendar operations" aka "Period Arithmetic" > For example, there "should be" a way to spell "an > hour from now" that follows "strict arithmetic" rules when the > datetime is aware. > > Or not ;-) > well, "should" is a loaded word, but it would be very, very useful (to some of us anyway). I deal with scientific datasets, I NEVER want 86400 seconds later to mean 23 or 25 hours later ;-) -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Thu Jul 30 22:22:19 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 13:22:19 -0700 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> Message-ID: On Thu, Jul 30, 2015 at 12:40 PM, Alexander Belopolsky < alexander.belopolsky at gmail.com> wrote: > On Thu, Jul 30, 2015 at 3:23 PM, Chris Barker > wrote: > > But we need to (a) be really clear in the docs whether the flag is > consulted > > any any other time. and (b) probably be really careful in the code to > make > > sure the flag is set appropriately at all times. > > "This member will have the value True for all instances except those > that represent the second (chronologically) moment in time in an > ambiguous case." [1] > > Does this require any more clarification? well, it certainly would if it were named somethign like "is_dst", but in the intereast of abslute calrity, how about we add something like: "This member can not be set to force the DST adjustment to behave any differently than the tzinfo object implements it." and/or "This member is not an indicator of whether DST is currently in effect, but is only an indicator or which offset to use in ambiguous cases." -Chris > If so, can you suggest it? > > [1]: https://github.com/abalkin/ltdf/blob/master/README.rst#the-first-flag > -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim.peters at gmail.com Thu Jul 30 22:37:39 2015 From: tim.peters at gmail.com (Tim Peters) Date: Thu, 30 Jul 2015 15:37:39 -0500 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: [Tim] >> ....I personally would have preferred that "aware" datetime objects >> use strict/timeline arithmetic instead, but it's not a big deal to me either >> way. [[ijs] > I thought I understood what you were saying until now, but through > this entire discussion I have been under the impression that you felt > the exact opposite of that last sentence (except for the not being a > big deal part). Ah. but my "preferred" above is past tense. That's how I felt at the time - and would still feel if we were starting over from scratch. Throughout the vast bulk of _this_ entire discussion we've been talking about the present and foreseeable future (in which "starting over from scratch" doesn't exist). Now backward compatibility, and explaining how & why it's possible to live happily enough with the status quo,, are far more important than that one of Tim's mild preferences was frustrated a dozen years ago ;-) >> [explains that strict/timeline arithmetic _is_ currently done when >> subtracting or comparing two aware datetimes] [[ijs] > So once we have an is_dst bit, what will be the result of > > tz = timezone('America/Chicago') > datetime(2013, 11, 3, 1, 30, tzinfo=tz, is_dst=True) - datetime(2013, 11, 3, 1, 0, tzinfo=tz, is_dst=False) > > ? I assume you already know, so I too will leave it as an exercise for the reader ;-) > How can it be consistent with current behavior and be anything other > than timedelta(0, 1800), even though the first time preceded the second? The result will change. The intended and documented behavior has always been to follow "strict arithmetic" rules in this case. So that it currently doesn't is, and always has been, a bug. Not a bug in subtraction itself, it's a bug in .utcoffset(), which couldn't possibly get all cases right before the is_dst flag was added. The instant utcoffset() is repaired, subtraction and comparison will be too. Of course it's possible that the change will break somebody's currently working code. But that's true of all bug fixes. I _might_ care if anyone could convince me that it has any real chance of breaking code except for some timezone wonk's collection of edge cases peppered with # EVIL PYTHON!!! HAVE THEY NO SHAME!!!!!??????!!!!!! comments ;-) From ethan at stoneleaf.us Thu Jul 30 23:00:58 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Thu, 30 Jul 2015 14:00:58 -0700 Subject: [Datetime-SIG] naive DateTime, aware DateTime, precise DateTIme In-Reply-To: References: <55BA6DFD.8040102@stoneleaf.us> Message-ID: <55BA908A.1090104@stoneleaf.us> [redirecting back to list] On 07/30/2015 11:49 AM, Skip Montanaro wrote: > On Thu, Jul 30, 2015 at 1:33 PM, Ethan Furman wrote: >> Instead of making a new timedelta object, which, after all, represents >> exactly what it says, why don't we make a new DateTime and Time that do the >> duration arithmetic? >> >> Anyone who wants that behaviour has to explicitly use the type so there >> would be no backwards compatibility issues with the existing DateTime, Time, >> or timedelta objects. > > I'm sorry. I must surely have missed something. I freely admit having > mentally elided the datetime-related discussions on python-dev. Under > what circumstances (other than perhaps the grey areas around the > change in or out of daily savings, or intervals crossing leap seconds) > do the current types not perform as expected? Are there test cases > missing from the test suite which would fail using the current > implementation? It is exactly those grey areas that have caused all the hullabaloo, and that's where 24 hours isn't (through no fault of timedelta). Using the example code from the datetime docs [1] as the base and going forward: --> my_time = datetime(2015, 3, 7, 13, 30, tzinfo=Pacific) --> my_time.strftime('%H:%M %z') '13:30 -0800' --> (my_time + 24 * HOUR).strftime('%H:%M %z') '13:30 -0700' The actual duration of time between those two instances is not 24 HOURS, but the blame for that lies with datetime, not timedelta. So my thought is to either make an entirely new type, or have a keyword argument, with the effect of a datetime that does account for dst switches: # HYPOTHETICAL CODE, DOES NOT CURRENTLY WORK --> my_time = datetime(2015, 3, 7, 13, 30, tzinfo=Pacific, precise=True) --> my_time.strftime('%H:%M %z') '13:30 -0800' --> (my_time + 24 * HOUR).strftime('%H:%M %z') '14:30 -0700' # assuming I did the math right in my head ;) I must admit, though, I'm not sure how often such a class would be used -- if the application is important enough to be exact with the durations (nuclear power plants, flying planes, etc.) then I would think a time zone such as UTC would be used just to avoid any possible confusion around those dst switches. -- ~Ethan~ [1] https://docs.python.org/3/library/datetime.html#datetime.tzinfo From carl at oddbird.net Thu Jul 30 22:28:40 2015 From: carl at oddbird.net (Carl Meyer) Date: Thu, 30 Jul 2015 14:28:40 -0600 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: <55BA88F8.4080105@oddbird.net> On 07/30/2015 10:46 AM, Chris Barker wrote: > There is "correct" and incorrect, but I"m not arguing that anything is > incorrect about the current behavior -- I thought a timedelta was a > duration, but I was wrong, it is a Period in units of days (I think!), > and sure it apparently does that right. No, it isn't a Period, and it doesn't "do that right". The current behavior _is_ incorrect (or at least lacking in internal coherence), and I don't think we can get clarity on what we want unless we acknowledge that. The discussion keeps getting sidetracked on the red herring of whether there are use cases for period arithmetic with "one day" defined as "same local time next day" as a period unit. Of course there are such use cases (and timedelta(1) can satisfy those use cases), but the current timedelta (as it behaves in arithmetic with tz-aware datetimes) is a hybrid that is not coherent considered either as a Period or a Duration. "Satisfying some use cases sometimes" is not sufficient for correctness; conceptual coherency matters too. Timedelta can only be considered a "Period object in units of days" if one accepts that the things it calls "hours", "minutes", and "seconds" are not really hours, minutes, or seconds, but rather fractional units of the "day-as-same-time-next-day" period that often (but not always) correspond to real hours, minutes, and seconds. I don't think this is a tenable explanation (and no one has attempted it), but you've just shown that it's one possible conclusion from defending the current model. Tim's valiant efforts notwithstanding, I don't think there is any coherent conceptual model that justifies the current behavior of timedelta. The _implementation_ can easily be explained of course (and Tim has done so very clearly, many times - I'd summarize it as "all arithmetic temporarily pretends all datetimes are naive, and then blindly reattaches the original tzinfo member"), but in terms of the underlying concepts, it makes no sense. In order to defend the current model as coherent, one has to discard one of the following points, and (despite having read every message in all the related threads), I am still not clear precisely which one of these Tim et al consider untrue or expendable: 1) A datetime with a tzinfo member that carries both a timezone and a specific UTC offset within that timezone (e.g. a pytz timezone instance) corresponds precisely and unambiguously to a single instant in astronomical time (as well as carrying additional information). 2) A timedelta object is clearly a Duration, not a Period, because timedelta(days=1), timedelta(hours=24), and timedelta(seconds=86400) result in indistinguishable objects. I think this point is uncontroversial; Tim has said several times that a timedelta is just a complicated representation of an integer number of microseconds. That's a Duration. 3) If one has two datetime objects that each unambiguously correspond to an instant in real time, and one subtracts them and gets back an object which represents a Duration in real microseconds, the only reasonable content for that Duration is the elapsed microseconds in real time between the two instants. Much virtual ink has been spilled over whether the behavior of "datetime + timedelta(days=1)" is correct, but this is an intentionally muddying case to consider, because there _are_ two perfectly reasonable interpretations of "add one day to a datetime". It's just that one of those interpretations (the Period one), which has been used to justify the current model, is inconsistent with _everything else_ about the behavior and implementation of timedelta. To be clear, I'm not arguing that this behavior can now be changed in the existing library objects in a backwards-incompatible way. But accepting that it is lacking in internal coherence (rather than just being an "alternative and equally good model") would be useful in clarifying what kind of an implementation we actually want (IMO, something very much like JodaTime/NodaTime). And then can we figure out how to get there from here. Carl -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From ethan at stoneleaf.us Thu Jul 30 23:19:36 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Thu, 30 Jul 2015 14:19:36 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: <55BA88F8.4080105@oddbird.net> References: <55BA88F8.4080105@oddbird.net> Message-ID: <55BA94E8.1000507@stoneleaf.us> On 07/30/2015 01:28 PM, Carl Meyer wrote: > [...] The _implementation_ can easily be explained [...] > I'd summarize it as "all arithmetic temporarily pretends all > datetimes are naive, and then blindly reattaches the original > tzinfo member") [...] This is the heart of the matter. The problem is not the timedelta, which is simply a number of seconds, but with how datetime uses it. And we cannot change existing behavior, but we can add to it -- so a new option for datetime that told it to take dst switches into account so that the new datetime was in fact timedelta seconds away should do the trick. (Don't ask me which trick, I don't remember any more ;) -- ~Ethan~ From ischwabacher at wisc.edu Thu Jul 30 23:51:32 2015 From: ischwabacher at wisc.edu (ISAAC J SCHWABACHER) Date: Thu, 30 Jul 2015 21:51:32 +0000 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: [Tim] > >> ....I personally would have preferred that "aware" datetime objects > >> use strict/timeline arithmetic instead, but it's not a big deal to me either > >> way. > > [ijs] > > I thought I understood what you were saying until now, but through > > this entire discussion I have been under the impression that you felt > > the exact opposite of that last sentence (except for the not being a > > big deal part). > > Ah. but my "preferred" above is past tense. That's how I felt at the > time - and would still feel if we were starting over from scratch. > Throughout the vast bulk of _this_ entire discussion we've been > talking about the present and foreseeable future (in which "starting > over from scratch" doesn't exist). Now backward compatibility, and > explaining how & why it's possible to live happily enough with the > status quo,, are far more important than that one of Tim's mild > preferences was frustrated a dozen years ago ;-) And this is the first time you've mentioned that. :) > >> [explains that strict/timeline arithmetic _is_ currently done when > >> subtracting or comparing two aware datetimes] [ijs] But only when the aware datetimes have different time zones! It's precisely because of this behavior that pytz has one fixed-offset DstTzInfo object for each offset attained over a time zone's history, so that two datetimes in the same time zone but with different offsets will have different tzinfo members and therefore be converted to UTC before being subtracted. This also means that addition leaves the datetime with the same fixed offset DstTzInfo object, so that calls to .utcoffset() and .dst() return the wrong result until the datetime object is normalized, which can be accomplished either with tz.normalize(dt) or with dt.astimezone(tz), except that the second way doesn't work if tz is dt.tzinfo (as opposed to one of the other DstTzInfo objects corresponding to tz). So anyone who is already using pytz is using timedeltas as durations anyway, it's just that they and Stuart Bishop have to jump through hoops to accomplish it. Which, come to think of it, might mean that the backward compatibility problem is overrated-- the behavior could be changed for aware datetimes only, and .normalize() could be added as a no-op. > > So once we have an is_dst bit, what will be the result of > > > > tz = timezone('America/Chicago') > > datetime(2013, 11, 3, 1, 30, tzinfo=tz, is_dst=True) - datetime(2013, 11, 3, 1, 0, tzinfo=tz, is_dst=False) > > > > ? > > I assume you already know, so I too will leave it as an exercise for > the reader ;-) > > > How can it be consistent with current behavior and be anything other > > than timedelta(0, 1800), even though the first time preceded the second? > > The result will change. The intended and documented behavior has > always been to follow "strict arithmetic" rules in this case. So that > it currently doesn't is, and always has been, a bug. Not a bug in > subtraction itself, it's a bug in .utcoffset(), which couldn't > possibly get all cases right before the is_dst flag was added. The > instant utcoffset() is repaired, subtraction and comparison will be > too. I'm not clear on how narrowly you mean "this case". What about tz = timezone('America/Chicago') dt = datetime(2013, 11, 3, tzinfo=tz) [[(dt.astimezone(timezone.utc) + timedelta(hours=n1)).astimezone(tz) - dt.astimezone(timezone.utc) + timedelta(hours=n2)).astimezone(tz) for n2 in range(5)] for n1 in range(5)] ? > Of course it's possible that the change will break somebody's > currently working code. But that's true of all bug fixes. I _might_ > care if anyone could convince me that it has any real chance of > breaking code except for some timezone wonk's collection of edge cases > peppered with > > # EVIL PYTHON!!! HAVE THEY NO SHAME!!!!!??????!!!!!! > > comments ;-) ...I might have had some comments of that nature in my code until fairly recently. Though they weren't as angry as the comments about getting pytz and dateutil.tz to interoperate. Or the comments about the device that tried to store sub-second resolution data in Excel format (days since 1899-12-30)... to five decimal places. ijs From chris.barker at noaa.gov Fri Jul 31 00:10:53 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 15:10:53 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: <55BA94E8.1000507@stoneleaf.us> References: <55BA88F8.4080105@oddbird.net> <55BA94E8.1000507@stoneleaf.us> Message-ID: On Thu, Jul 30, 2015 at 2:19 PM, Ethan Furman wrote: > On 07/30/2015 01:28 PM, Carl Meyer wrote: > > [...] The _implementation_ can easily be explained [...] >> I'd summarize it as "all arithmetic temporarily pretends all >> datetimes are naive, and then blindly reattaches the original >> tzinfo member") [...] >> > > This is the heart of the matter. The problem is not the timedelta, which > is simply a number of seconds, but with how datetime uses it. > conceptually yes, in the code? I don't know. which __add__method actually does the work? But given backward compatibility, there is not [point in arguing out whether the current implementation is coherent, or wrong, or highly useful or???? It seems we have general consensus that both Period arithmetic and Duration Arithmetic with time zone aware datetime objects are useful. And that the current implementation in the datetime module does not provide a complete (or even mostly complete) implementation of either of these. And that we can't add functionality to timedelta to better support Period arithmetic without totally breaking backward compatibility And that we can't change the way datetime+tzinfo+timedelta interact witout breaking backward compatibility. So: Some combination of a new and new timedeltas are required. And we cannot change existing behavior, but we can add to it -- so a new > option for datetime that told it to take dst switches into account so that > the new datetime was in fact timedelta seconds away should do the trick. > hmm -- that might buy us Duration Arithmetic, but how do we get Period Arithmetic. By the way -- which __add__ actually does the implementation? datetime's or timedelta's ? (both are slots, so not easy to see the code....) -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Fri Jul 31 00:22:16 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 15:22:16 -0700 Subject: [Datetime-SIG] naive DateTime, aware DateTime, precise DateTIme In-Reply-To: <55BA908A.1090104@stoneleaf.us> References: <55BA6DFD.8040102@stoneleaf.us> <55BA908A.1090104@stoneleaf.us> Message-ID: On Thu, Jul 30, 2015 at 2:00 PM, Ethan Furman wrote: > It is exactly those grey areas that have caused all the hullabaloo, and > that's where 24 hours isn't (through no fault of timedelta). Exactly -- but that's really dangerous, actually, if something works "as expected" most of the time, people will blindly go about their business using it, and then get an ugly bug report way down the line (hopefully). my thought is to either make an entirely new type, or have a keyword > argument, with the effect of a datetime that does account for dst switches: > > # HYPOTHETICAL CODE, DOES NOT CURRENTLY WORK > --> my_time = datetime(2015, 3, 7, 13, 30, tzinfo=Pacific, precise=True) > --> my_time.strftime('%H:%M %z') > '13:30 -0800' > --> (my_time + 24 * HOUR).strftime('%H:%M %z') > '14:30 -0700' # assuming I did the math right in my head ;) > > I must admit, though, I'm not sure how often such a class would be used -- > if the application is important enough to be exact with the durations > (nuclear power plants, flying planes, etc.) then I would think a time zone > such as UTC would be used just to avoid any possible confusion around those > dst switches. > There is a hug gap between "needs to be accurate to less than hour" and "nuclear power plants, flying planes" I for one, work all the time with datasets that, yes, SHOULD all be in UTC, but are often not, and I need to both accept input and return output in whatever timezone the user has/needs, and arithmetic had better be real, genuine 24 hours is 24 hours.... In fact, I can certainly see that some use cases call for Period Arithmetic (which I never need), but I can't image a use case that calls for Duration Arithmetic but doesn't care about an hour one way or the other! In practice, all my code does the time-zone conversion on I/O, keeping everything in naive datetimes internally (or unix tics -- ugg!) But it would be nice nice to have good, robust time-zone aware datetimes instead -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From ethan at stoneleaf.us Fri Jul 31 00:24:38 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Thu, 30 Jul 2015 15:24:38 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: <55BA88F8.4080105@oddbird.net> <55BA94E8.1000507@stoneleaf.us> Message-ID: <55BAA426.9060103@stoneleaf.us> On 07/30/2015 03:10 PM, Chris Barker wrote: > By the way -- which __add__ actually does the implementation? datetime's or timedelta's ? class timedelta: def __add__(self, other): if isinstance(other, timedelta): # for CPython compatibility, we cannot use # our __class__ here, but need a real timedelta return timedelta(self._days + other._days, self._seconds + other._seconds, self._microseconds + other._microseconds) return NotImplemented timedelta only adds directly to other timedeltas; so datetime is doing the actual addition. -- ~Ethan~ From chris.barker at noaa.gov Fri Jul 31 01:18:18 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 16:18:18 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: <55BAA426.9060103@stoneleaf.us> References: <55BA88F8.4080105@oddbird.net> <55BA94E8.1000507@stoneleaf.us> <55BAA426.9060103@stoneleaf.us> Message-ID: On Thu, Jul 30, 2015 at 3:24 PM, Ethan Furman wrote: > By the way -- which __add__ actually does the implementation? datetime's >> or timedelta's ? >> > > class timedelta: > > def __add__(self, other): > if isinstance(other, timedelta): > # for CPython compatibility, we cannot use > # our __class__ here, but need a real timedelta > return timedelta(self._days + other._days, > self._seconds + other._seconds, > self._microseconds + other._microseconds) > return NotImplemented > > > timedelta only adds directly to other timedeltas; so datetime is doing the > actual addition. great, thanks -- so timedelta knows nothing of datetimes at all, it seems -- nice! And you are quite right -- what we need a datetime with a different __add__ (and a few others, I suppose) And it could be pretty darn backward compatible -- it would behave exactly the same for naive datetimes, and, I think, any time zone without a DST, and even any timezone when the DST boundary isn't crossed. I'm thinking its "as simple" as: - convert to utc - convert to a timedelta from year 1 - do the addition - convert back to a utc datetime - convert back to the tzinfo's timezone Or is there more to it than that that I'm missing? -Chris > > -- > ~Ethan~ > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > The PSF Code of Conduct applies to this mailing list: > https://www.python.org/psf/codeofconduct/ > -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Fri Jul 31 01:50:32 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 19:50:32 -0400 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 5:25 AM, Guido van Rossum wrote: > Even if I wouldn't design it that way today (which honestly I haven't > decided whether I would or not) I don't want to change anything about the > observable behavior[1] that would give a different outcome, no matter how > much more "correct" you believe a different outcome would be. The > deprecation time would have be measured in decades. > > The road to improvement that I encourage everyone to explore: add an is_dst > flag (with a different name) and create new timedelta-ish classes that > implement "human" arithmetic (similar to what pytz offers) and "strict" > arithmetic (similar to [NJ]odaTime, IIUC). I think we can change the behavior datetime.__add__ and datetime.__sub__ if we do it based on the type of the object attached as tzinfo. For example, if we introduce a new abstract subclass of the tzinfo class called say "tzstrict", then we can be sure that there is no tzinfo implementation in the wild that inherits from tzstrict (we fully control the datetime module namespace.) Now, we can make datetime.__add__ and __sub__ check the type of the tzinfo member on its argument(s) and apply the new rules if one of them is an instance of tzstrict. With these changes in place, users who want new aware datetime arithmetic will use timezone implementations that inherit from tzstrict and legacy applications can continue using existing timezone libraries. And we can spend the next decade arguing what kind of timezone implementation belongs to the standard library. :-) From ethan at stoneleaf.us Fri Jul 31 02:16:55 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Thu, 30 Jul 2015 17:16:55 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: <55BABE77.9050802@stoneleaf.us> On 07/30/2015 04:50 PM, Alexander Belopolsky wrote: > I think we can change the behavior datetime.__add__ and > datetime.__sub__ if we do it based on the type of the object attached > as tzinfo. Yup, it's really the datetime.__xxx__ methods that need to do something different, so we can base that off a flag to the datetime, or the type of the tzinfo. I suppose the key question is which will make it more obvious that "strict" rules are in affect? -- ~Ethan~ From tim.peters at gmail.com Fri Jul 31 02:36:31 2015 From: tim.peters at gmail.com (Tim Peters) Date: Thu, 30 Jul 2015 19:36:31 -0500 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: [Alexander Belopolsky ] > I think we can change the behavior datetime.__add__ and > datetime.__sub__ if we do it based on the type of the object attached > as tzinfo. For example, if we introduce a new abstract subclass of > the tzinfo class called say "tzstrict", then we > can be sure that there is no tzinfo implementation in the wild that > inherits from tzstrict (we fully control the datetime module > namespace.) Now, we can make datetime.__add__ and __sub__ check the > type of the tzinfo member on its argument(s) and apply the new rules > if one of them is an instance of tzstrict. It's a happy idea :-) > With these changes in place, users who want new aware datetime > arithmetic will use timezone implementations that inherit from > tzstrict and legacy applications can continue using existing timezone > libraries. And we can spend the next decade arguing what kind of > timezone implementation belongs to the standard library. :-) Or fixing all the bugs in the recommended way to write tzstrict instances ;-) Speaking of which, the current tzinfo API has no way to ask "is this an ambiguous time?" or "is this an invalid (missing) time?" The most important new question callers will want to resolve is "what should `first` (aka is_dst) be now?". The only (at best indirectly) relevant things we can ask it now are "what's the total UTC offset at the local-time instant I represent?", and likewise "what's the DST adjustment component of the total UTC offset at (etc)?:" And there's no way at all now to ask (not even indirectly) whether the standard UTC offset has changed. So it's unclear to me how arithmetic (or anything else) can use the current tzinfo API efficiently to set the `first` (aka is_dst) flag correctly in all cases. Perhaps tzstrict could grow a helpful new method or two to make this easy for callers? The logic is bound to be annoying enough that we'd want to concentrate it in tzstrict (rather then replicate it all over call sites). But no concrete suggestions from me at this time. From alexander.belopolsky at gmail.com Fri Jul 31 03:00:45 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 30 Jul 2015 21:00:45 -0400 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: Message-ID: On Thu, Jul 30, 2015 at 8:36 PM, Tim Peters wrote: > Speaking of which, the current tzinfo API has no way to ask "is this > an ambiguous time?" I was hoping that we would agree on the name of the flag before someone asks this question. :-) With my proposal, a naive datetime t is ambiguous in timezone tz if tz.utcoffset(t) < tz.utcoffset(t.replace(first=False)) > or "is this an invalid (missing) time?" I was hoping to sneak in a rule that for an invalid time t tz.utcoffset(t) > tz.utcoffset(t.replace(first=False)) (I really don't want tz.utcoffset(t) to ever raise an exception) and of course, for most of the times tz.utcoffset(t) == tz.utcoffset(t.replace(first=False)) > The most > important new question callers will want to resolve is "what should > `first` (aka is_dst) be now?". I want most callers to be able to get away with not knowing that `first` exists and consistently get the earlier time from an ambiguous input and some "nearby" time from an invalid input. A careful application will have to call tz.utcoffset() with both values of the flag and either warn about the default choice or ask the user for an additional input. From tim.peters at gmail.com Fri Jul 31 03:04:43 2015 From: tim.peters at gmail.com (Tim Peters) Date: Thu, 30 Jul 2015 20:04:43 -0500 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: <55BABE77.9050802@stoneleaf.us> References: <55BABE77.9050802@stoneleaf.us> Message-ID: [Ethan Furman ] > Yup, it's really the datetime.__xxx__ methods that need to do something > different, so we can base that off a flag to the datetime, or the type of > the tzinfo. > > I suppose the key question is which will make it more obvious that "strict" > rules are in affect? I like Alexander's new tzstrict (subclass of tzinfo) idea best so far. Flags invariably create nasty problems, like: - needing to make them thread-local (just because you want strict arithmetic in your main thread doesn't mean the 3rd-party code you're running in other threads can live with that choice - and perhaps they were written before the flag even existed, so have no idea they _need_ to protect themselves now) - various packages fighting over what they need in a single thread (e.g., some library will change the flag, then suffer an unexpected exception which manages to forget restoring the flag; the caller catches the exception and moves on, oblivious to that crucial state has been corrupted) - horrid "discoverability" problems when anything goes wrong ("huh! after an hour I found the problem: the datetime arithmetic mode was wrong! But why? I'm running a hundred thousand lines of code nobody around me wrote, from 25 packages I barely understand, and there's no way to find out now who changed it. when, or why."). It's important to remember that Python is used in some very complex environments Explicitly picking a "strict zone" when you want strict arithmetic is something nobody else's code can change retroactively (because Python programmers are never rude enough to abuse their powers ;-) ), instantly discoverable by runtime introspection, and more-or-less easily discoverable by static source inspection (if the code is written sanely). From ethan at stoneleaf.us Fri Jul 31 03:09:05 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Thu, 30 Jul 2015 18:09:05 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: <55BABE77.9050802@stoneleaf.us> Message-ID: <55BACAB1.5080301@stoneleaf.us> On 07/30/2015 06:04 PM, Tim Peters wrote: > I like Alexander's new tzstrict (subclass of tzinfo) idea best so far. > Flags invariably create nasty problems, like: It's growing on me, too. The flag idea was per-instance, though, not global (and not changeable once an instance was created), so most of those horrible nightmare situations wouldn't happen. And, yeah, I remember that Guido doesn't like flags. ;) -- ~Ethan~ From chris.barker at noaa.gov Fri Jul 31 05:15:51 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Thu, 30 Jul 2015 20:15:51 -0700 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: <55BACAB1.5080301@stoneleaf.us> References: <55BABE77.9050802@stoneleaf.us> <55BACAB1.5080301@stoneleaf.us> Message-ID: On Thu, Jul 30, 2015 at 6:09 PM, Ethan Furman wrote: > On 07/30/2015 06:04 PM, Tim Peters wrote: > > I like Alexander's new tzstrict (subclass of tzinfo) idea best so far. >> > hmm -- somehow the tz object really feels like the wrong place for it. If you don't like flags, why not a datetime subclass? -- is that any more ugly than another tzinfo subclass? We should also think about how to handle the Period arithmetic case -- would that be a special kind of tzinfo object? I would think not -- after all, you'd certainly need a different kind of timedelta object. It would be nice not to have too many new objects. -Chris > Flags invariably create nasty problems, like: >> > > It's growing on me, too. > > The flag idea was per-instance, though, not global (and not changeable > once an instance was created), so most of those horrible nightmare > situations wouldn't happen. And, yeah, I remember that Guido doesn't like > flags. ;) > > -- > ~Ethan~ > > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > The PSF Code of Conduct applies to this mailing list: > https://www.python.org/psf/codeofconduct/ > -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim.peters at gmail.com Fri Jul 31 08:54:28 2015 From: tim.peters at gmail.com (Tim Peters) Date: Fri, 31 Jul 2015 01:54:28 -0500 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: .... [Tim] >>>> [explains that strict/timeline arithmetic _is_ currently done when >>>> subtracting or comparing two aware datetimes] [ijs] > But only when the aware datetimes have different time zones! Oh, fudge - yes. My mistake! I overlooked that in my explanation. And, to be clear, two datetime objects x and y "have the same timezone" in _this_ context means: x.tzinfo is y.tzinfo That is, iff they share a common tzinfo object. In that case they are indeed subtracted (ditto compared) using classic arithmetic Given that classic arithmetic is used whenever it can be partly justified in under 4 pages of dense text, there's simply not a compelling reason to break from the naive-time model in that case. So I take back everything I said about your specific example: > tz = timezone('America/Chicago') > datetime(2013, 11, 3, 1, 30, tzinfo=tz, is_dst=True) - datetime(2013, 11, 3, 1, 0, tzinfo=tz, is_dst=False) Assuming this isn't some tzinfo implementation that, e.g., sometimes magically replaces instances bound to datetimes, then both datetimes share a common tzinfo member, the result won't change. There are other cases that _will_ change, when the tzinfo members are different objects. If you want code similar to this that does give a timeline arithmetic result, you'll need to use whatever spelling of "use timeline arithmetic" is implemented (if any). > It's precisely because of this behavior that pytz has one fixed-offset > DstTzInfo object for each offset attained over a time zone's history, > so that two datetimes in the same time zone but with different offsets > will have different tzinfo members and therefore be converted to UTC > before being subtracted. Both painful and clever. While I don't personally care about timezone transition anomalies (I've never written an app that cared, nor expect I ever will), if I _did_ I think it's bloody obvious that "the right thing" to do in Python's current state is to stick to UTC for every operation apart from conversions for input or output. Classic arithmetic and timeline arithmetic give the same results in UTC (or any other eternally-fixed-offset timezone). Insert "Doctor! Doctor! It hurts when I do this!" "So stop doing it" ;-) > This also means that addition leaves the datetime with the same fixed > offset DstTzInfo object, so that calls to .utcoffset() and .dst() return the > wrong result until the datetime object is normalized, which can be > accomplished either with tz.normalize(dt) or with dt.astimezone(tz) >, except that the second way doesn't work if tz is dt.tzinfo (as opposed > to one of the other DstTzInfo objects corresponding to tz). I won't do the "Doctor! Doctor" joke more than once in a single message ;-) > So anyone who is already using pytz is using timedeltas as > durations anyway, it's just that they and Stuart Bishop have > to jump through hoops to accomplish it. Which, come to think > of it, might mean that the backward compatibility problem is > overrated-- the behavior could be changed for aware datetimes > only, and .normalize() could be added as a no-op. I believe Stuart also strongly recommends sticking to UTC (at least for people who do care about transitions). I conclude he went to all the trouble primarily because he found it to be an irresistibly bizarre technical puzzle. I'm only surprised that attitude is apparently contagious ;-) > ... > I'm not clear on how narrowly you mean "this case" Since I retracted what I said, doesn't matter. > What about > > tz = timezone('America/Chicago') > dt = datetime(2013, 11, 3, tzinfo=tz) > [[(dt.astimezone(timezone.utc) + timedelta(hours=n1)).astimezone(tz) > - dt.astimezone(timezone.utc) + timedelta(hours=n2)).astimezone(tz) for n2 in range(5)] for n1 in range(5)] > > ? I think the project would be better served if you directed this ingenuity and energy into creating unit tests, or at least a persistent document that grows over time, or a wiki entry ... What do _you_ think should happen? I agree that getting edge cases right is important, but since I strongly doubt I'll be working on them it's of little real use to invite me to think about them. At heart, they're just not interesting to me - and mailing lists are black holes. After I finish answering, this will all be lost in time ;-) Briefly as I can, because nobody yet knows what will and won't be implemented, or when each piece that is implemented will land: - Conversions have always done the best job they could in all cases; conversions are _outside_ the "naive time" model. - But conversions inherit utcoffset()'s limitations. Provided utcoffset's current limitations are repaired, conversion should do the correct thing in all cases. It cannot today. - Since you start in Chicago standard time, I expect that (assuming it's implemented) some spelling.of is_dst will record "no, it's not DST" in your dt object. That will never change across the duration of the program. There is no spelling of is_dst today. - The two instances of `dt.astimezone(timezone.utc)` could be hoisted out of the nested loops and computed just once: it's a loop invariant. That value should already be computed correctly (it's converting a not-near-an-edge-case Chicago daylight time to UTC, right? easy). - And there doesn't appear to be anything tricky about the two additions.. Their left-hand sides are the same loop invariant, and then a varying number of hours are added to that invariant. Finally, the additions are performed _in_ UTC, where classic and timeline arithmetic produce the same results. Nothing changes, and all that should also already be done correctly - You've contrived for the additions to create two UTC time spellings that will convert to the same time spelling in America/Chicago (the "repeated hour" at the end of Chicago DST). Both now and regardless of what may change, both such UTC spellings will convert to 1:00:00 Chicago time, via astimezone(tz). - The top-level subtraction will continue to use classic arithmetic because both operands share the same tzindo object. Unless some spelling of "use timeline arithmetic all the time" is implemented that's somehow triggered by code outside the fragment shown. So I don't expect any change to the _displayed_ results here. _If_ the top-level subtraction were done with timeline arithmetic instead, then I would expect changes, provided an .is_dst equivalent is implemented. In that case, some astimezone(tz) intermediate results would change, not in the Chicago HH:MM:SS results delivered, but that some of the Chicago 01:00:00 results would have is_dst False and others True. Classic arithmetic won't even see that, but timeline subtraction would take those differences into account. Enough? Did I even stumble into the issue you were _really_ wondering about? ;-) > ... > ...I might have had some comments of that nature in my code until fairly recently. Though they > weren't as angry as the comments about getting pytz and dateutil.tz to interoperate. Hear about the guy who went to the doctor and complained "Doctor! Doctor! It hurts when I do this!"? Na, me neither ;-) > Or the comments about the device that tried to store sub-second resolution data in > Excel format (days since 1899-12-30)... to five decimal places. I _am_ an expert on floating-point trivia. In case you were wondering, the person who wrote the software for that device was ... optimistic ;-) From tim.peters at gmail.com Fri Jul 31 09:40:22 2015 From: tim.peters at gmail.com (Tim Peters) Date: Fri, 31 Jul 2015 02:40:22 -0500 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: [Guido] > .... > I assume you meant naive, not native. Always. In any context ;-) BTW, the only thing truly naive about datetime was how little time everyone expected its development to consume. 13 years later and a billion people are still arguing over how to finish implementing mathematically trivial timezone arithmetic ;-) > Yes, I meant to introduce human arithmetic as a third form, to support > adding e.g. months or years, while classic and strict arithmetic shouldn't. Got it. > (Since timedelta doesn't keep its days and seconds separated, it's not > really a Period, so I think it shouldn't be extended further. Absolutely not. It's just a funky way to spell a large integer (number of microseconds), and it's only in naive time that _any_ common named durations longer than an hour actually match a fixed number of microseconds. The only new argument I think we _could_ sanely add to the timedelta constructor is `fortnights=`. Well, that and `googoldays=`, except that would overflow for any non-zero value. So it goes: patch on the way! ;-) > And adding months is a requirement for human arithmetic -- e.g. I was > called a bad word on Twitter yesterday because timedelta doesn't support > months.) Thanks for telling me! It's another excellent reason to keep my life blissfully Twitter-free. >>>> (BTW, historically, early versions of Python datetime had a separate >>>> datetime subclass called datetimetz (IIRC), but the final design got >>>> rid of this unnecessary complexity.) >>> I don't believe that was ever released, but it's possible we >>> contemplated that and even implemented it in an early >>> pure-Python prototype. >> FWIW, IIRC it did exist in an early prototype but was discarded before >> it was even halfway implemented. > I stand corrected. Na. I could well be wrong about everything. Much of my few lucid moments are lost to bemoaning all I've forgotten. > My memory seems to be failing -- I also thought there was a datetime > PEP, Oops! It really is failing! There definitely was not. > but I guess we avoided the PEP process (even though datetime > was added in 2.3, well after PEP 1 was written) because we were > all working in the same office. (Or do I misremember that too? :-) Nobody could have made time to write a PEP. We were utterly drowning in "input" without one. Lots of discussion took place on a Zope-hosted public DateTime wiki. Yesterday I tried pretty hard to find it without success - I guess it's lost now. Also enormous wads of Python and Zope mailing list traffic. And what ended up being the text of the first version of the manual docs was written by me in a markup-free plain text file that was checked in and publicized frequently, kept roughly in synch with the ever-changing Python prototype and test suite. None of those three ever get "too far" ahead of the others. So everyone interested got plain-text docs, a prototype, and a test suite, all along the way, plus wiki and multiple mailing list access for questions, requests and discussions. Besides, it was your project. There wasn't much suspense over whether it would be accepted ;-) From tim.peters at gmail.com Fri Jul 31 16:37:59 2015 From: tim.peters at gmail.com (Tim Peters) Date: Fri, 31 Jul 2015 09:37:59 -0500 Subject: [Datetime-SIG] Clearing up terminology In-Reply-To: References: <-6120061269507718094@unknownmsgid> Message-ID: Correcting an error, albeit an inconsequential one: [Tim] > - Since you start in Chicago standard time, I expect that (assuming > it's implemented) some spelling.of is_dst will record "no, it's not > DST" in your dt object. That will never change across the duration of > the program. There is no spelling of is_dst today. s/Chicago standard time/Chicago daylight time/ s/no, it's not/yes, it is/ From tritium-list at sdamon.com Fri Jul 31 17:22:06 2015 From: tritium-list at sdamon.com (Alexander Walters) Date: Fri, 31 Jul 2015 11:22:06 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> Message-ID: <55BB929E.8040201@sdamon.com> 1. no one will expect the datetime module is_dst to map to the posix mktime function. If they expect a mapping to the posix api, they are using the time module. I think you are the only one who thought that. Just because another api uses a clear term with one set of semantics, does not mean we cant use the clear term with a different set of semantics. 2. "Is this instance of time DST? Oh, it has a member attribute 'is_dst', let me print that and see..." "I need to tell python this time I am inputting is DST. ...I will pass True to the is_dst argument" "I am in the northern hemisphere and need to construct a date in the middle of july. My nation-state observes DST. ...what the hell do i do with a 'first' argument?" On 7/30/2015 14:33, Alexander Belopolsky wrote: > On Thu, Jul 30, 2015 at 2:15 PM, Alexander Walters > wrote: >> We are not talking about implementing the POSiX argument to mktime, and I >> dont think anyone on the list ever was. .is_dst is a bool flag for 'if set, >> the time represented is in the DST time, if not set, it is in the non-DST >> time'. >> >> '.first' doesnt even imply a bool. "First what?" someone might ask. > I have no emotional attachment to any particular name. If you like > "is_first" better than "first" on the grammatical grounds - I have no > problem changing the spelling. > > I do have two problems with calling it isdst: > > 1. Whether we want to implement the POSIX standard or not, but > tm_isdst member is the POSIX solution to the problem at hand and if we > give datetime objects a member variable called isdst, but change the > semantics, we will see no end of bug reports. (And since no one > understands POSIX semantics, we have no choice but to change them. :-) > > 2. It will be very confusing to have t.is_dst ? t.dst() which will > happen whenever you have an ambiguity due to a change in the standard > time. From carl at oddbird.net Fri Jul 31 17:36:32 2015 From: carl at oddbird.net (Carl Meyer) Date: Fri, 31 Jul 2015 09:36:32 -0600 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: <55BB929E.8040201@sdamon.com> References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> <55BB929E.8040201@sdamon.com> Message-ID: <55BB9600.4010109@oddbird.net> On 07/31/2015 09:22 AM, Alexander Walters wrote: ... > "Is this instance of time DST? Oh, it has a member attribute 'is_dst', > let me print that and see..." That's a great reason _not_ to name the proposed attribute `is_dst`, because it does not answer the question "is this datetime DST?", and isn't intended to. The intent is to disambiguate times within the overlap resulting from a UTC-offset fallback, whether from DST or any other change in a timezone's UTC offset. > "I need to tell python this time I am inputting is DST. ...I will pass > True to the is_dst argument" > > "I am in the northern hemisphere and need to construct a date in the > middle of july. My nation-state observes DST. ...what the hell do i do > with a 'first' argument?" If you are constructing a datetime in the middle of July, you have no need to set this attribute, because there are no ambiguous times in the middle of July. Your tzinfo (if it's useful) already knows that July is DST in your timezone, it doesn't need you to set any attribute manually. Carl -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From alexander.belopolsky at gmail.com Fri Jul 31 17:59:47 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Fri, 31 Jul 2015 11:59:47 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: <55BB929E.8040201@sdamon.com> References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> <55BB929E.8040201@sdamon.com> Message-ID: On Fri, Jul 31, 2015 at 11:22 AM, Alexander Walters wrote: > 1. no one will expect the datetime module is_dst to map to the posix mktime > function. Please don't overgeneralize. The fact that *I* would expect "is_dst" in local to UTC converstion to act as the familiar "tm_isdst" does in local to "seconds since 1970-01-01T00:00 UTC" conversion is enough to invalidate your claim about "no one". I also suspect I am not alone. > If they expect a mapping to the posix api, they are using the > time module. For years, we recommended people who needed to translate naive datetimes assumed to be local to UTC to use datetime.utcfromtimestamp(time.mktime(dt.timetuple())). I think anyone who ever followed this recommendation will be surprised if we make "is_dst" behave differently from what "tm_isdst" does (on their platform!) > I think you are the only one who thought that. I'll let others deny this. (Confirming this would take a world-wide poll.) > Just because > another api uses a clear term with one set of semantics, does not mean we > cant use the clear term with a different set of semantics. > POSIX's use of "tm_isdst" in mktime is as clear as mud. If you disagree, follow the link I posted before and read what the standard says before arguing that it is clear. > "Is this instance of time DST? Oh, it has a member attribute 'is_dst', let > me print that and see..." I have never had a need to answer the question "Is this instance of time DST?" What I normally want to know is the UTC offset. Most people I know have trouble telling whether DST is winter or summer time. If they know that for their location, most will get baffled if asked if this is the same in the other hemisphere. Please read the two dialogs I posted at the end of my proposal, , and tell us who asks a better question Bob or Alice? > > "I need to tell python this time I am inputting is DST. ...I will pass True > to the is_dst argument" That's the problem. Most people don't know whether they are inputing DST or STD and it does not matter 99.99% of the time. In that rare 0.01% case, that don't want to learn what DST is just to be able to pick between two possible times. It is much easier to decide whether you want something happen earlier or later than to decide whether you want it happen when DST is or is not (respectively) in effect. > > "I am in the northern hemisphere and need to construct a date in the middle > of july. My nation-state observes DST. ...what the hell do i do with a > 'first' argument?" You know too much. :-) If you need a date in the middle of July - pick July 15. From guido at python.org Fri Jul 31 18:02:01 2015 From: guido at python.org (Guido van Rossum) Date: Fri, 31 Jul 2015 18:02:01 +0200 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: <55BABE77.9050802@stoneleaf.us> <55BACAB1.5080301@stoneleaf.us> Message-ID: On Fri, Jul 31, 2015 at 5:15 AM, Chris Barker wrote: > On Thu, Jul 30, 2015 at 6:09 PM, Ethan Furman wrote: > >> On 07/30/2015 06:04 PM, Tim Peters wrote: >> >> I like Alexander's new tzstrict (subclass of tzinfo) idea best so far. >>> >> I like it too. > hmm -- somehow the tz object really feels like the wrong place for it. > > If you don't like flags, > If we're talking about a *global* flag, yes, that's a horrid idea. > why not a datetime subclass? -- is that any more ugly than another tzinfo > subclass? > Most code creates datetime instances through its constructor. But most code creates tzinfo instances through factory functions (usually in 3rd party libraries, since the stdlib has no tz database). I'm guessing there are way more places where datetime() is called than places where a tzinfo is created. So yes, a datetime subclass is uglier. > We should also think about how to handle the Period arithmetic case -- > would that be a special kind of tzinfo object? I would think not -- after > all, you'd certainly need a different kind of timedelta object. It would be > nice not to have too many new objects. > If needed, we could create as many alternative time-delta-ish classes as we wanted, and through the magic of Python's binary operator overloading (in particular __radd__ and __rsub__) we could have each time-delta-ish class implement a different kind of arithmetic on vanilla datetime objects. -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.belopolsky at gmail.com Fri Jul 31 18:06:54 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Fri, 31 Jul 2015 12:06:54 -0400 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: <55BB9600.4010109@oddbird.net> References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> <55BB929E.8040201@sdamon.com> <55BB9600.4010109@oddbird.net> Message-ID: On Fri, Jul 31, 2015 at 11:36 AM, Carl Meyer wrote: > If you are constructing a datetime in the middle of July, you have no > need to set this attribute, because there are no ambiguous times in the > middle of July. That's if you are lucky. I mentioned this example before: Ukraine moved the clock back one hour on 1990-07-01. That was not in the middle of July, but close. This introduced an ambiguous hour where both the first and the second hour were in DST. (Yes, they kept observing STD/DST on top of that change, so they had two ambiguous hours in 1990.) From alexander.belopolsky at gmail.com Fri Jul 31 18:26:17 2015 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Fri, 31 Jul 2015 12:26:17 -0400 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: <55BABE77.9050802@stoneleaf.us> <55BACAB1.5080301@stoneleaf.us> Message-ID: On Fri, Jul 31, 2015 at 12:02 PM, Guido van Rossum wrote: > On Fri, Jul 31, 2015 at 5:15 AM, Chris Barker wrote: >> >> On Thu, Jul 30, 2015 at 6:09 PM, Ethan Furman wrote: >>> >>> On 07/30/2015 06:04 PM, Tim Peters wrote: >>> >>>> I like Alexander's new tzstrict (subclass of tzinfo) idea best so far. > > > I like it too. Thanks for the kind words, Tim, Ethan and Guido! I've also wondered about a possibility to delegate arithmetics to the timezone class altogether. For example, we could have a rule like this: def __add__(self, delta): if hasattr(self.tzinfo, 'add'): return self.tzinfo.add(self, delta) This, in theory, is powerful enough to support leap seconds if we represent 23:59:60.x as time(23, 59, 59, x, first=False). From guido at python.org Fri Jul 31 18:37:22 2015 From: guido at python.org (Guido van Rossum) Date: Fri, 31 Jul 2015 18:37:22 +0200 Subject: [Datetime-SIG] Calendar vs timespan calculations... In-Reply-To: References: <55BABE77.9050802@stoneleaf.us> <55BACAB1.5080301@stoneleaf.us> Message-ID: [re-adding the list] On Fri, Jul 31, 2015 at 6:21 PM, ?ukasz Rekucki wrote: > On 31 July 2015 at 18:02, Guido van Rossum wrote: > > On Fri, Jul 31, 2015 at 5:15 AM, Chris Barker > wrote: > >> > >> On Thu, Jul 30, 2015 at 6:09 PM, Ethan Furman > wrote: > >>> > >>> On 07/30/2015 06:04 PM, Tim Peters wrote: > >>> > >>>> I like Alexander's new tzstrict (subclass of tzinfo) idea best so far. > > > > > > I like it too. > > What happens then when you substract a datetime with *strict* tzinfo > and a *naive* one? Would A - B == - (B - A) still be true ? That's for the authors of the new PEP to decide, really, but I think it could be made to follow the strict rules in both cases, since clearly the code isn't an old program requiring backward compatibility (how would such a program end up with a strict tzinfo?). -- --Guido van Rossum (python.org/~guido) -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Fri Jul 31 18:51:18 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Fri, 31 Jul 2015 09:51:18 -0700 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: <55BB929E.8040201@sdamon.com> References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> <55BB929E.8040201@sdamon.com> Message-ID: On Fri, Jul 31, 2015 at 8:22 AM, Alexander Walters wrote: > 1. no one will expect the datetime module is_dst to map to the posix > mktime function. If they expect a mapping to the posix api, they are using > the time module. I think you are the only one who thought that. Just > because another api uses a clear term with one set of semantics, does not > mean we cant use the clear term with a different set of semantics. > well, yes. but: > "Is this instance of time DST? Oh, it has a member attribute 'is_dst', > let me print that and see..." > this is extending the use-case of the flag -- maybe a good idea, but not the original intent. As I understnd it the original intent is only to disambiguate the "the same time twice" case. "I need to tell python this time I am inputting is DST. ...I will pass > True to the is_dst argument" > why do you need to do that??? the point here is that you use the timezones definition od DST -- you don't need to think about it, except in the ambiguous case -- in which case, are you thining "Daylight vs Standard Time" or "first interval, or ??? "intuitive" means "works like I expect" -- but eveyone expects different things.... "I am in the northern hemisphere and need to construct a date in the middle > of july. My nation-state observes DST. ...what the hell do i do with a > 'first' argument?" nothing -- there is no ambiguity in the middle of July. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.barker at noaa.gov Fri Jul 31 19:02:00 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Fri, 31 Jul 2015 10:02:00 -0700 Subject: [Datetime-SIG] How open are we to re-thinking the whole thing? Message-ID: It seems we've all come to the conclusion that there are three types of arithmetic here -- we can discuss until the cows come home about how useful "classic" (what is implemented in datetime now) arithmetic is, and exactly how it behaves in various corner cases, but it is here to stay for backward compatibility, and if we want either of the other two ("Duration" and "Period"), then we'll need to write implementations of them. So the question I have is: do we want to re-use as much of the current API and existing objects as possible, or should we start "from scratch", and design what we want/need now, with all the benefits of hindsight? For example: Duration arithmetic is actually pretty easy (or am I just being "naive" ;-) ): - convert to UTC - do the arithmetic - convert back to the time zone desired. Done. Granted, that's only easy if the "convert" part is done, but once we work out the nuances of the "is_dst" flag, then that's done. Period arithmetic is theoretically easy, but full of corner cases that have to be resolved, one by one... I think the real challenge here is how to get these two while keeping maximum compatibility with the current objects and API. So maybe we shouldn't worry so much about that. "the right > thing" to do in Python's current state is to stick to UTC for every > operation apart from conversions for input or output. Exactly -- and "the right thing to do" to properly support duration arithmetic is for that to be what happens under the hood. Which, brings up a point: If new code is going to be written, and new APIs defined, then maybe a re-thinking of the datetime data structure is in order: As Tim points out, both datetime and timedelta are really just fancy ways to encode milliseconds. They make it easy to work with the calendar representation version of these quantities -- i.e. on I/O -- because that's what humans want to work with. Also, the method of attaching the tzinfo object makes it easy to create and read and write datetimes in a given time zone. But if one were to design a system optimized for a different purpose, i.e. to support Duration arithmetic, it makes more sense to: * store datetimes in a "time_unit_since an epoch" representation (e.g. milliseconds since year 1 in the proleptic gregorian calendar) * store timedeltas in a "time_unit" (e.g. milliseconds) and (somewhat independent): * store timezone aware datetimes in UTC, and do the conversion to/from calendar representation on I/O. [that makes Duration addition described above reduce to: "add two numbers"] On the other hand, if you want to support "Period Arithmetic" (aka Calendar Operations), then it's easier to use Calendar encoding internally -- after all, "moving to the next day", (or next month, or...) is natural and easy (except for the edge cases!) in Calendar encoding. All this points to having two independent systems for the two types of math: two datetime objects two timedelta objects That makes it easy to decide what "type" of delta to return when subtracting two dates, and easy for the user to know what type of arithmetic they are going to get. Also, it could be in a datetime2 package, and have fewer issues with backward compatibility and make it clear to users that they are getting something different than the existing datetime package. Downsides: * More code to implement and maintain -- always a bad thing * Harder for users that need to do both kinds of arithmetic in one application -- if that's a common use case, then one datetime object with multiple deltas might be better. And the datetime object would have to be optimised for one or the other use-case -- so be it. Another totally side note about API. Particularly for Period arithmetic, the timedelta API feels a bit "OO-heavy" to me: If I want "tomorrow", I need to do: DateTime.now() + PeriodDelta(days=1) I think I'd rather something like: DateTime.now().next_day() or DateTime.now().moveforward("1 day") And if the Period arithmetic is in methods, then we don't have to worry about what kind of delta to return when subtracting. Just a thought....... (side question: It seems to me that doing the Period operations one way is pretty straightforward e.g. "add a day", but is it well defined in the other direction? e.g. what is the Period between datetime1 and datetime2?) -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim.peters at gmail.com Fri Jul 31 19:20:37 2015 From: tim.peters at gmail.com (Tim Peters) Date: Fri, 31 Jul 2015 12:20:37 -0500 Subject: [Datetime-SIG] Local time disambiguation proposal In-Reply-To: References: <55BA6306.2030106@sdamon.com> <55BA69B4.4040708@sdamon.com> <55BB929E.8040201@sdamon.com> Message-ID: [Alexander Walters] >> 1. no one will expect the datetime module is_dst to map to the posix mktime >> function. [Alexander Belopolsky] > Please don't overgeneralize. The fact that *I* would expect "is_dst" > in local to UTC converstion to act as the familiar "tm_isdst" does > in local to "seconds since 1970-01-01T00:00 UTC" > conversion is enough to invalidate your claim about "no one". I also > suspect I am not alone. You're far from alone, but there's no need to argue the point: you already won ;-) That is, Guido already Pronounced on this: https://mail.python.org/pipermail/datetime-sig/2015-July/000094.html ... The road to improvement that I encourage everyone to explore: add an is_dst flag (with a different name) ... And you've already explained why at length: the intended meaning of tm_isdst is baffling in some cases, so we do want different semantics, but because CPython is intended to work nicely with C code written by C programmers it's always a mistake to use similar names in similar contexts when the semantics differ in fundamental ways. "first" is a good solution: not confusable with any familiar name in C's view of time, and its meaning is both sensible and utterly clear in all ambiguous cases. At least until the next C standard adds tm_first to mean "equal to tm_isdst except in rare cases of double (or greater) leap seconds, in which case the value is as specified by the Finely Interpolated Real Second Time (FIRST) standard" ;--) From ethan at stoneleaf.us Fri Jul 31 22:09:45 2015 From: ethan at stoneleaf.us (Ethan Furman) Date: Fri, 31 Jul 2015 13:09:45 -0700 Subject: [Datetime-SIG] How open are we to re-thinking the whole thing? In-Reply-To: References: Message-ID: <55BBD609.1060107@stoneleaf.us> Personally I think what we have is pretty good. We can shore up the cracks with a new tzinfo object to handle actual durations across time skips. We can add a datedelta to handle things like weeks and months and years -- if we need to. I think the first step is the new tzinfo, and after that it seems there are already a bunch of third-party modules to handle "human time" calculations. -- ~Ethan~ From chris.barker at noaa.gov Fri Jul 31 22:37:23 2015 From: chris.barker at noaa.gov (Chris Barker) Date: Fri, 31 Jul 2015 13:37:23 -0700 Subject: [Datetime-SIG] How open are we to re-thinking the whole thing? In-Reply-To: <55BBD609.1060107@stoneleaf.us> References: <55BBD609.1060107@stoneleaf.us> Message-ID: On Fri, Jul 31, 2015 at 1:09 PM, Ethan Furman wrote: > Personally I think what we have is pretty good. > > We can shore up the cracks with a new tzinfo object to handle actual > durations across time skips. > > We can add a datedelta to handle things like weeks and months and years -- > if we need to. I think the first step is the new tzinfo, and after that it > seems there are already a bunch of third-party modules to handle "human > time" calculations. > Fair enough. Specifying that you want Duration Arithmetic in a time zone object seems pretty kludgy to me -- after all, it has nothing to do logically with what time zone you are in. But it does seem like the least disruptive way to patch it into the current system. And datetime + timedelta, does, in fact, already provide Duration Arithmetic for naive datetimes. And I just noticed that dateutils has: """ Timezone (tzinfo) implementations for tzfile(5) format files (/etc/localtime, /usr/share/zoneinfo, etc), TZ environment string (in all known formats), iCalendar format files, given ranges (with help from relative deltas), local machine timezone, fixed offset timezone, UTC timezone, and Windows registry-based time zones. """ (as well, I think, as a build-in Olson database) I have no idea how robust it is, but it looks like it's got everything we need to put time zones into the stdlib... (and a PeriodDelta type...) -CHB > > -- > ~Ethan~ > _______________________________________________ > Datetime-SIG mailing list > Datetime-SIG at python.org > https://mail.python.org/mailman/listinfo/datetime-sig > The PSF Code of Conduct applies to this mailing list: > https://www.python.org/psf/codeofconduct/ > -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker at noaa.gov -------------- next part -------------- An HTML attachment was scrubbed... URL: