Skip to content

Duration pickle and shallow copy lose year and month components #1023

Description

@GreedyC

Problem

Pickling or shallow-copying a Duration loses its calendar components even though its approximate total length remains equal.

import copy
import pickle
import pendulum

original = pendulum.duration(years=2, months=3, weeks=1, days=2)
restored = pickle.loads(pickle.dumps(original))
print(original.years, original.months)  # 2 3
print(restored.years, restored.months)  # 0 0
print(str(original))   # 2 years 3 months 1 week 2 days
print(str(restored))   # 118 weeks 3 days
print(copy.copy(original).years)  # 0

The inherited timedelta reduction serializes only its normalized day/second/microsecond fields, not the Duration instance state. Existing pickle coverage checks equality, so it doesn't catch the calendar information loss.

I plan to preserve the instance state alongside timedelta's existing reduction, with regressions for every supported pickle protocol, positive/negative/mixed-sign calendar components and shallow copying. Interval already defines its own reduction and should keep its existing behavior.

Reproduced from master with the pure-Python implementation on macOS / Python 3.12.13. Nineteen new regression cases fail before the fix. Checked existing duration pickle/copy issues and PRs for overlapping work.

Investigated with Codex assistance.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions