[Datetime-SIG] Are there any "correct" implementations of tzinfo?

Random832 random832 at fastmail.com
Mon Sep 14 22:08:58 EDT 2015


Alexander Belopolsky <alexander.belopolsky at gmail.com> writes:

> No credit for anything other than the "extra credit" section.  Partial
> credit for that.  Study that printout and you should understand what
> Tim was saying.

My original claim was that the pickler can't know and doesn't care if a
byte string value merely happens to be 10 bytes long for this object, or
is 10 bytes long every time, it will encode it with SHORT_BINBYTES ["C",
count of bytes, string of bytes] regardless.

The datetime constructor itself does care what value is passed to it,
but what I was saying was the class could have been written originally
to accept optionally longer strings and ignore the extra values, so that
future versions could pickle as longer strings and be compatible.

In such a case, the actual pickle format would _still_ have consisted of
__reduce__() == (datetime, (b"..........", [optional tzinfo])), just
with the option of accepting (and ignoring) longer byte strings encoded
by later versions of the datetime class.

The pickle format is versatile enough to pass any (pickleable) value at
all to a constructor (or to __setstate__). Designing the datetime
constructor/setstate in the past to be able to accept a byte string of a
length other than exactly 10 would have allowed the representation to be
extended in the present, rather than smuggling a single extra bit into
one of the existing bytes. But it would not have changed the actual
representation that would have been produced by pickle back then, not
one bit.

And, now, to answer my own question from a previous message...
>>> class C():
...  def __reduce__(self):
...   return (datetime, (b"\x07\xdf\t\x0e\x155'\rA\xb2",))
...
>>> pickle.loads(pickle.dumps(C()))
datetime.datetime(2015, 9, 14, 21, 53, 39, 868786)
>>> class C():
...  def __reduce__(self):
...   return (datetime, (b"\x07\xdf\t\x0e\x955'\rA\xb2",))
...
>>> pickle.loads(pickle.dumps(C()))
datetime.datetime(2015, 9, 14, 149, 53, 39, 868786)
>>> datetime.strftime(pickle.loads(pickle.dumps(C())), '%Y%m%d%H%M%S')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: hour out of range

That was the bit we were talking about, right?



More information about the Python-list mailing list