Repository navigation
Commit f97c213
adenyoung
Preserve the fold when pickling DateTime
`DateTime.__reduce_ex__()` returned the class plus the 8-tuple state, so the
fold flag never made it into the pickle stream. A `DateTime` on the second
occurrence of an ambiguous wall time came back as the first one, with a
different offset and a timestamp shifted by an hour:
```python
chicago = pendulum.timezone("America/Chicago")
after = pendulum.datetime(2024, 11, 3, 7, tz="utc").astimezone(chicago)
# 2024-11-03 01:00:00-06:00, fold=1, timestamp 1730617200.0
pickle.loads(pickle.dumps(after)).timestamp()
# Before: 1730613600.0 (2024-11-03 01:00:00-05:00, fold=0)
# After: 1730617200.0
```
The standard library rebuilds a datetime from its state, but `fold` is
keyword-only for `datetime.__new__()`, so it cannot be appended to the
positional tuple that gets expanded into `cls(*args)`. Restore through a
module-level function instead, which rebuilds the instance from its raw
state without going through `create()` (no timezone conversion, no
normalization of non-existent wall times, `tzinfo` kept as-is) and passes
`fold` as a keyword argument.
`copy.copy()` goes through the same `__reduce_ex__()` and is fixed as well.
Pickles written by older versions still load: they store the class plus the
8-tuple, which still builds a valid instance; they simply cannot carry a
fold they never contained.
Closes #9081 parent e06dace commit f97c213
2 files changed
Lines changed: 51 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
53 | 69 | | |
54 | 70 | | |
55 | 71 | | |
| |||
1367 | 1383 | | |
1368 | 1384 | | |
1369 | 1385 | | |
1370 | | - | |
1371 | | - | |
1372 | | - | |
1373 | | - | |
1374 | | - | |
1375 | | - | |
| 1386 | + | |
1376 | 1387 | | |
1377 | 1388 | | |
1378 | 1389 | | |
1379 | 1390 | | |
1380 | | - | |
1381 | | - | |
1382 | | - | |
1383 | | - | |
1384 | | - | |
| 1391 | + | |
| 1392 | + | |
1385 | 1393 | | |
1386 | 1394 | | |
1387 | 1395 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
166 | 167 | | |
167 | 168 | | |
168 | 169 | | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
169 | 201 | | |
170 | 202 | | |
171 | 203 | | |
| |||
0 commit comments