<div dir="ltr">Thanks for the quick response!<br><div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Aug 16, 2015 at 2:45 PM, Alexander Belopolsky <span dir="ltr"><<a href="mailto:alexander.belopolsky@gmail.com" target="_blank">alexander.belopolsky@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Sun, Aug 16, 2015 at 3:23 PM, Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br>
> I think that a courtesy message to python-dev is appropriate, with a link to<br>
> the PEP and an invitation to discuss its merits on datetime-sig.<br>
</span>Will do.  (Does anyone know how to set Reply-To: header in Gmail?)<br></blockquote><div><br></div><div>I think you can set TO: datetime-sig, BCC: python-dev.<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class="">> - I'm surprised the name of the proposed flag doesn't occur in the abstract.<br>
</span>That's because I wanted people to get to the proposal section before<br>
starting to bikeshed on the name of the flag.   More on that below.<br></blockquote><div><br>Heh. :-) <br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - The rationale might explicitly mention the two cases we're thinking about:<br>
> DST transitions and adjustments to the timezone's base offset -- noting that<br>
> the latter may be an arbitrary interval (not just an hour).<br>
</span>Actually, in either case the adjustment can be a fraction of an hour.<br>
I'll add this to the rationale.<br>
<span class=""><br>
> - The sidebar doesn't show up as a sidebar, but as somewhat mysterious text,<br>
> on <a href="https://www.python.org/dev/peps/pep-0495/" rel="noreferrer" target="_blank">https://www.python.org/dev/peps/pep-0495/</a> (it does on <a href="http://legacy.python.org" rel="noreferrer" target="_blank">legacy.python.org</a>,<br>
> but we're trying to avoid that site). Maybe you should file a bug with the<br>
> pydotorg project on GitHub (if you haven't already).<br>
</span>I did: <<a href="https://github.com/python/pythondotorg/issues/808" rel="noreferrer" target="_blank">https://github.com/python/pythondotorg/issues/808</a>>.<br>
<span class=""><br>
> (While I like the<br>
> artwork, it's a bit un-PEP-like, and maybe not worth it given the problems<br>
> making the image appear properly.)<br>
</span>If we don't fix the layout issues before the pronouncement, I'll<br>
remove the graphic.<br>
<span class=""><br>
> - Conversely, on <a href="http://legacy.python.org" rel="noreferrer" target="_blank">legacy.python.org</a> there are some error messages about<br>
> "Unknown directive type "code"" (lines 112, 118).<br>
</span>I'll look into this.  I've never had problems with ReStructuredText<br>
rendering on docs.p.o, but the peps site seems to be more restrictive.<span class=""><br></span></blockquote><div><br></div><div>FWIW I don't get errors when I do "make pep-0498.html" in the peps repo -- I consider that the ultimate arbiter of who's right. Maybe we have an old ReST version generating legacy?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - "a fold is created in the fabric of time" sounds a bit like<br>
> science-fiction. I'd just say "a time fold is created", or "a fold is<br>
> created in time".<br>
</span>Agree.  After all, a "fold" already suggests some kind of fabric.<span class=""><br></span></blockquote><div><br></div><div>:-) Never thought about it this way. I've always just considered it an excessively literary phrase. Can't you fold a line though?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - Despite having read the section about the naming, I'm still not wild about<br>
> the name 'first'. This is in part because this requires True as the default,<br>
> in part because without knowing the background its meaning somewhat<br>
> mysterious.<br>
</span>I agree.  My top candidate is "repeated=False", but an invitation to<br>
bikeshed, <<a href="https://mail.python.org/pipermail/datetime-sig/2015-August/000241.html" rel="noreferrer" target="_blank">https://mail.python.org/pipermail/datetime-sig/2015-August/000241.html</a>>,<br>
was not met with the usual enthusiasm.</blockquote><div><br></div><div>Actually the *usual* enthusiasm is probably expressed by more bikeshedding. :-) In this case I have to agree that "repeated" doesn't sound right.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">To defend the "True means<br>
earlier" choice, I would mention that it matches "isdst=1 means<br>
earlier" in the fold.<span class=""><br></span></blockquote><div><br></div><div>But nobody would be able to remember that mnemonic -- the far majority of people simply don't know whether to move the clock forward or back when DST begins or ends, they just read it in the newspaper the day before (or rely on their cell phone) and try to forget about it as soon as they can. At least, that's how I usually do it (even though I am well capable of reasoning it through from first principles, it's not wort remembering).<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> I'm not wild about the alternatives either, so perhaps this<br>
> requires more bikeshedding. :-( (FWIW I agree that the name should not<br>
> reference DST, since time folds may appear for other reasons.) Hmm... Maybe<br>
> "fold=True" to select the second occurrance?<br>
</span>I really want something that disambiguates two times based on their<br>
most natural characteristics: do you want the earlier or the later of<br>
the two choice?  Anything else, in my view would require additional<br>
knowledge.<br></blockquote><div><br></div><div>Agreed. <br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - I'm a bit surprised that this flag doesn't have three values (e.g. None,<br>
> True, False) -- in C, the tm_isdst flag in struct tm can be -1, 0 and 1,<br>
> where -1 means "figure it out" or "don't care".<br>
</span>With the proposed functionality, one can easily implement any of the<br>
C-style isdst logic.</blockquote><div><br></div><div>Really? The way I interpret the PEP, there's no way to represent the "-1" case using a datetime alone.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The problem, however is that while most C<br>
libraries agree with in their treatment of 0 and 1, the behavior on<br>
tm_isdst=-1 ranges from bad to absurd.  For example, the value<br>
returned by mktime in the ambiguous case may depend on the arguments<br>
passed to the previous call to mktime.<span class=""><br></span></blockquote><div><br></div><div>The actual behavior and bugs of C libraries don't interest me much. I just care about "None" meaning "nobody set it, probably because the code was written before this flag was introduced".<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> The "don't care" case should allow stricter backward compatibility.<br>
</span>I am not sure we want to maintain the behavior described in<br>
<<a href="http://bugs.python.org/issue22627" rel="noreferrer" target="_blank">http://bugs.python.org/issue22627</a>> (Calling timestamp() on a datetime<br>
object modifies the timestamp of a different datetime object.)<span class=""><br></span></blockquote><div><br></div><div>I can't quite follow the bug. Does it imply that datetime objects are mutable? Or is there some global state that's set by the timestamp() function? What is it that ts1.timestamp() changes that affects ts2.timestamp()?<br><br></div><div>Anyway, I'm not saying we should maintain backwards compatibility in that case (assuming you can convince me it's a bug that should be fixed regardless of whether we accept this PEP).<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - "[1] An instance that has first=False in a non-ambiguous case is said to<br>
> represent an invalid time ..." Could you quickly elaborate here whether such<br>
> an invalid time is considered an hour later than the valid corresponding<br>
> time with first=True, given a reasonable timezone with and without DST?<br>
</span>Such an instance is just *invalid* as in "February 29, 2015."  In a<br>
non-ambiguous case,  first=False means "the second of one", which does<br>
not make sense.  Such instances should never be produced except for a<br>
narrow purpose of probing the astimezone() or timestamp() to determine<br>
whether a given datetime is ambiguous or not.<span class=""><br></span></blockquote><div><br></div><div>Yeah, but it can still be created -- and if I have one, how does it behave? (I don't care what it means. :-)<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - "In CPython, a non-boolean value of first will raise a TypeError , but<br>
> other implementations may allow the value None to behave the same as when<br>
> first is not given." This is surprisingly lenient. Why allow the second<br>
> behavior at all?<br>
</span>Because it is currently allowed for the other arguments of replace()<br>
in the pure python datetime implementation that we ship.  I will be<br>
happy to change that starting with the "first".<span class=""><br></span></blockquote><div><br></div><div>OK, seems to make sense to be consistent with the other args -- just explain that reason in the text then.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> (Surely all Python implementations can distinguish between<br>
> a value equal to None and a missing value, even if some kind of hack is<br>
> needed.) Also, why this clause for replace() but not for other methods?<br>
</span>What other methods?  replace() is fairly unique in its treatment of arguments.<span class=""><br></span></blockquote><div><br></div><div>Well, several other methods also have a first=... argument. How should they treat first=None compared to its absence?<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - I'm disappointed that there are now some APIs that explicitly treat a<br>
> naive datetime as local (using the system timezone). I carefully avoided<br>
> such interpretation in the original design, since a naive datetime can also<br>
> be used to represent a point in UTC, or in some timezone that's implicit.<br>
> But I guess this cat is out of the bag since it's already assumed by<br>
> timestamp() and fromtimestamp(). :-(<br>
</span>I held that siege as long as I could.<span class=""><br></span></blockquote><div><br></div><div>And thanks for that! I guess we move on now.<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - "Conversion from POSIX seconds from EPOCH" I'd move this section before<br>
> the opposite clause, since it is simpler and the other clause references<br>
> fromtimestamp(). The behavior of fromtimestamp() may also be considered<br>
> motivational for having only the values True and False for the flag.<br>
</span>Will do.<br>
<span class=""><br>
> - "New guidelines will be published for implementing concrete timezones with<br>
> variable UTC offset." Where?<br>
</span>In the official datetime documentation.  I'll clarify that.<br>
<span class=""><br>
> (Is this just a forward reference to the next section? Then I'd drop it.)<br>
</span>No, I expect that section to be incorporated in the official datetime<br>
library documentation.<span class=""><br></span></blockquote><div> <br></div><div>OK, should definitely be clarified. Note that PEPs rarely say anything about the docs -- the docs simply follow the specs laid out by the PEP. So the PEP could just state the guidelines. (After all the guidelines can always be viewed in the context of the PEP.)<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - "... must follow these guidelines." Here "must" is very strong (it is the<br>
> strongest word in "standards speak", stronger than "should", "ought to",<br>
> "may"). I recommend "should", that's strong enough.<br>
</span>OK.  This is a remnant of the idea to include a first-aware fromutc()<br>
implementation, which after some private discussions with Tim we<br>
decided to abandon.  In light of that idea, "must" made sense as in<br>
"in order for unmodified fromutc() work correctly with your tzinfo<br>
implementation, it *must* ..."<br>
<span class="">> - "We chose the minute byte to store the the "first" bit because this choice<br>
> preserves the natural ordering." This only works with folds of exactly one<br>
> hour. Also, is the natural ordering (of the pickles, apparently) used<br>
> anywhere? I would hope not. Finally, given that two times that differ only<br>
> in their 'first' flag compare equal, the natural ordering (if relevant :-)<br>
> would be to store/compare the 'first' bit last.<br>
</span>I'll remove the rationale.  The ordering is a red herring anyways.  I<br>
needs a place to stick one bit in the 10-byte payload and the minute<br>
byte looked like a natural place.  I made up the ordering rational to<br>
a posteriori justify an arbitrary choice.<br>
<span class=""><br>
> - Temporal Arithmetic (probably shouldn't have an "s" at the end):<br>
</span>Wikipedia is of no help here: "Arithmetic or arithmetics (from the<br>
Greek ἀριθμός arithmos, "number")  ..." I'll check what we use in the<br>
library docs.  (For some reason, I thought that Arithmetic is a branch<br>
of mathematic while arithmetics is a set of rules.)<span class=""><br></span></blockquote><div><br></div><div>Maybe it's British vs. American usage? The Brits also say "maths" while Americans say "math". But I don't think I've ever seen or heard arithmetics with an 's', and I've seen and heard plenty of 'maths'. Anyway, we tend to use American spelling in PEPs.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> this probably needs some motivation. I think it's inevitable (since we don't know<br>
> the size of the time fold), but it still feels weird.<br>
</span>It's what you say and backward compatibility considerations.  We want<br>
existing programs to produce the same results even if they<br>
occasionally encounter first=False instances from say datetime.now().<br>
<span class="">I'll add a footnote.<br>
</span><span class="">> - "[2] As of Python 3.5, tzinfo is ignored whenever timedelta is added or<br>
> subtracted ..." I don't see a reason for this footnoote to discuss possible<br>
> future changes to datetime arithmetic; leave that up to the respective PEP.<br>
</span>I'll remove the discussion of the future changes to datetime arithmetic.<br>
<span class=""><br>
> (OTOH you may have a specific follow-up PEP in mind, and it may be better to<br>
> review this one in the light of the follow-up PEP.)<br>
</span>Yes, there is a PEP-0500, but it is nowhere as ready as this one.<span class=""><br></span></blockquote><div><br></div><div>I think it's overkill (see my previous message).<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - "This proposal will have little effect on the programs that do not read<br>
> the first flag explicitly or use tzinfo implementations that do." This seems<br>
> ambiguous -- if I use a tzinfo implementation that reads the first flag, am<br>
> I affected or not? Also, "the programs" should be just "programs", and I'm<br>
> kind of curious why the hedging of "little effect" (rather than "no effect")<br>
</span>We are changing the behavior of datetime.timestamp on naive instances.<br>
  This is really what the "hedging" is about.<span class=""><br></span></blockquote><div><br></div><div>OK. Might be good to be explicit in the text.<br><br></div><div>But you haven't responded to my complaint that the "or" clause you used is ambiguous in English -- which of the following does it mean?<br><br>- (not "read first flag" or "use tzinfo impls that do")<br>- not ("read first flag" or "use tzinfo impls that do")<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> is needed. Also, you might give some examples of changes that programs that<br>
> *do* use the first flag may experience.<br>
</span>I don't understand.  The programs that  *do* use the first flag now<br>
experience an AttributeError, and that will surely change.  Perhaps<br>
you want to see some examples of how the programs can start using the<br>
first flag?<span class=""><br></span></blockquote><div><br></div><div>I was thinking about what happens in a program that explicitly uses the  flag to create a datetime object and then passes it on to some library code that doesn't know about the flag. But the change in behavior of fromtimestamp() makes this a moot point. Better be explicit about the hedging.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> - In a reply to this thread, you wrote "The rule for the missing time is the<br>
> opposite to that for the ambiguous time. This allows a program that probes<br>
> the TZ database by calling timestamp with two different values of the<br>
> "first" flag to avoid any additional calls to differentiate between the gap<br>
> and the fold." Can you clarify this (I'm not sure how this works, though I<br>
> intuitively agree that the two rules should be each other's opposite) and<br>
> add it to the PEP?<br>
</span>Yes, I posted something like this before, but will include in the PEP.<br>
A first-aware program can do something like the following when it gets<br>
a naive instance dt that it wants to decorated with a timezone.<br>
dt1 = dt.replace(first=True).astimezone()<br>
dt2 = dt.replace(first=False).astimezone()<br>
if dt1 == dt2:<br>
    return dt1<br>
if dt1 < dt2:<br>
    warn("ambiguous time: picked %s but it could be %s", dt1, dt2)<br>
    return dt1<br>
if dt1 > dt2:<br>
    raise ValueError("invalid time", dt, dt1, dt2)<br>
<span class=""><br>
> - Would there be any merit in proposing, together with the idea of a<br>
> three-value flag, that datetime arithmetic should use "timeline arithmetic"<br>
> if the flag is defined and a tzinfo is present?<br>
</span>To add a third value, you will need a full additional bit anyways, so<br>
why not just have a separate flag that controls the choice of<br>
arithmetic and leave "first" a pure fold disambiguation flag?  I<br>
consider the problem of local time disambiguation and that of the<br>
"timeline arithmetic" to be two orthogonal problems.  Yes, "timeline<br>
arithmetic" can benefit from the first flag, but it is possible<br>
without it.  Similarly, the problem of round-tripping the times<br>
between timezones can benefit from "timeline arithmetic", but PEP 495<br>
solves it without introducing the new arithmetic.<br></blockquote><div><br></div><div>Fair enough. The PEP could use some discussion of this topic!<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
In my view PEP 495 solves a long-standing problem for which there is<br>
no adequate workaround within stdlib and third-party workarounds are<br>
cumbersome.  The alternative datetime arithmetic PEP (PEP-0500)<br>
enables some nice to have features, but does not enable anything that<br>
cannot be achieved  by other means.  I would like to avoid mixing the<br>
two proposals.<br>
</blockquote></div><br></div><div class="gmail_extra">Agreed, and I am very glad to see PEP 495, as a concrete proposal for the "first step" that I proposed a while ago. Still, the whole term "first step" implies there will be more steps, and we should make sure the first step is roughly in the right direction!<br clear="all"></div><div class="gmail_extra"><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>