<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Sep 12, 2015 at 5:46 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"><div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote"><span class="">On Sat, Sep 12, 2015 at 6:24 PM, Guido van Rossum <span dir="ltr"><<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">The repeated claims (by Alexander?) that astimezone() has the power of pytz's localize() need to stop.</blockquote><div><br></div></span><div>Prove me wrong! :-)</div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> Those pytz methods work for any (pytz) timezone -- astimezone() with a default argument only works for the local time zone.</blockquote><div><br></div></span><div>That's what os.environ['TZ'] = zonename is for.  The  astimezone() method works for every timezone installed on your system.  Try it - you won't even need to call time.tzset()!</div></div></div></div></blockquote><div><br></div><div>That's global state. Doesn't count.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> (And indeed what it does is surprising, except perhaps to pytz users.)</blockquote><div><br></div></span><div>That I agree with.  Which makes it even more surprising that I often find myself and pytz advocates on the opposite sides of the fence.</div><div><br></div><div>Granted, setting TZ is a silly trick, but one simple way to bring a full TZ database to Python is to allow .astimezone() take a zonename string like 'Europe/Amsterdam' or 'America/Montevideo' as an argument and act as os.environ['TZ'] = zonename; t.astimezone() does now, but without messing with global state.<br></div></div></div></div></blockquote><div><br></div><div>It might as well be a different method then though.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div>I made this suggestion before, but I find it inferior to "as intended" tzinfos.</div><div><br></div><div>The only real claim that I am making is that fictitious fixed offset timezones are useful and we already have some support for them in stdlib.  The datetime.timezone instances that .astimezone() attaches as tzinfo are not that different from the instances that are attached by pytz's localize and normalize methods.</div></div></div></div></blockquote><div><br></div><div>And it has the same defect.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>In fact, the only major differences between datetime.timezone instances and those used by pytz is that pytz's EST and EDT instances know that they come from America/New_York, while datetime.timezone instances don't.  That's why once you specify America/New_York in localize, your tzinfo.normalize knows it implicitely, while in the extended .astimezone() solution you will have to specify it again.  This is not a problem when you only support one local timezone, but comes with a different set of tradeoffs when you have multiple timezones.</div><div><br></div><div>One advantage of not carrying the memory of the parent zoneinfo in the fixed offset tzinfo instance is that pickling of datetime objects and their interchange between different systems becomes simpler.  A pickle of a datetime.timezone instance is trivial - same as that of a tuple of timedelta and a short string, but if your fixed offset tzinfo carries a reference to a potentially large zoneinfo structure, you get all kinds of interesting problems when you share them between systems that have different TZ databases.</div></div></div></div></blockquote><div><br></div><div>The pickling should be careful to pickle by reference (on the timezone name). That its meaning depends on the tz database is a feature.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>In any case, there are three approaches to designing a TZ database interface in the datetime module: the "as intended" approach, the pytz approach and the astimezone(zonename:str) approach.  The last two don't require a fold attribute to disambiguate end-of-dst times and the first one does.  With respect to arithmetic, the last two approaches are equivalent: both timeline and classic arithmetics are possible, but neither is painless.  The "as intended" approach comes with classic arithmetic that "just works" and encourages the best practice for timeline arithmetic: do it in UTC.  That's why I believe PEP 495 followed by the implementation of fold-aware "as intended" tzinfos (either within stdlib or by third parties) is the right approach.</div></div></div></div>
</blockquote></div><br></div><div class="gmail_extra">Right. So please focus on this path and don't try to pretend to pytz users that hacks around astimezone() make pytz redundant, because they don't. There are other ways to fix the damage that pytz has done.<br></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>
</div></div>