<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Aug 18, 2015 at 7:12 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="adM"><div class=""><div class="gmail_extra"><div class="gmail_quote"><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>[Guido van Rossum] <br></div><span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_extra">Similar for adding a datetime and a timedelta. Optimizing this should be  IMO the only question is how should a datetime object choose between classic arithmetic[1] and timeline arithmetic. My proposal here is to make that a boolean property of the tzinfo object -- we could either use a marker subclass or an attribute whose absence implies classic arithmetic.<br></div></blockquote><div><br></div></span><div>With this proposal, we will need something like this:</div><div><br></div><div><font face="monospace, monospace">def __sub__(self, other):</font></div><div><font face="monospace, monospace">    if self.tzinfo is not None and self.tzinfo.strict:</font></div><div><font face="monospace, monospace">        self_offset = self.utcoffset()</font></div><div><font face="monospace, monospace">        other_offset = other.utcoffset()</font></div><div><font face="monospace, monospace">        naive_self = self.replace(tzinfo=None)</font></div><div><font face="monospace, monospace">        naive_other = other.replace(tzinfo=None)</font></div><div><font face="monospace, monospace">        return naive_self - </font><span style="font-family:monospace,monospace">self_offset - </span><span style="font-family:monospace,monospace">naive_other + </span><span style="font-family:monospace,monospace">other_offset</span><span style="font-family:monospace,monospace"> </span></div><div><font face="monospace, monospace">    # old logic</font></div><div><font face="monospace, monospace"><br></font></div><div>So we need to create six intermediate Python objects just to do the math.  On top of that, we need the utcoffset() method which is a pain to write in C, so we will wrap our optimized dst() function and compute utcoffset() as dst(t) + timedelta(hours=-5), creating four more intermediate Python objects.  At the end of the day, I will not be surprised if aware datetime subtraction is 10x slower than naive and every Python textbook recommends to avoid doing arithmetic with aware datetime objects.</div></div><br></div></div>
</blockquote></div><br></div></div></div><div class="gmail_extra">I doubt it. Most textbooks aren't that concerned with saving a few cycles. (Do most Python textbooks even discuss the cost of object creation or function calls?) Anyways, wouldn't PEP 500 be even slower?</div></blockquote><div><br></div><div>I don't think so.  We can implement PEP 500 as a C equivalent of </div></div><br><font face="monospace, monospace">def __sub__(self, other):<br>    try:<br>        try:<br>           return self.tzinfo.__datetime_diff__(self, other)<br>        except TypeError: # assume other is a timedelta<br>           return self.tzinfo.__datetime_sub__(self, other)<br>    except AttributeError: # assume missing PDDM<br>        pass<br>    # old logic</font></div><div class="gmail_extra"><font face="monospace, monospace"><br></font></div><div class="gmail_extra">and <span style="font-family:monospace,monospace">__datetime_diff__ </span>/ <span style="font-family:monospace,monospace">__datetime_sub__ </span>may be even faster than a single timedelta - timedelta operation because no timezone would support a time span of more than a century or two and can do even microsecond-precision calculations in machine integers.<font face="monospace, monospace"><br></font></div><div class="gmail_extra"><br></div><div class="gmail_extra">Granted, most timezone implementations will just implement .utcoffset() and inherit the slow __datetime_sub/diff__ implementations from tzstrict, but users who care about a few simple timezones will have an option to optimize those.</div></div>