Skip to content

Handle negative timestamps in from_timestamp - #3026

Draft
lafrech wants to merge 2 commits into
devfrom
negative_timestamps
Draft

Handle negative timestamps in from_timestamp#3026
lafrech wants to merge 2 commits into
devfrom
negative_timestamps

Conversation

@lafrech

@lafrech lafrech commented Aug 18, 2026

Copy link
Copy Markdown
Member

Closes #3019.
Replacement for #3020.

I rewrote #3020 in a less AI-verbose way.

Before submitting, I checked why we prevented negative timestamps in the first place and it seems it is because those are not supported on Windows. See e.g. https://stackoverflow.com/a/71915839.

This sucks.

Should we add a platform check to let this work on sane (non-MS) environments?

@HarperZ9

Copy link
Copy Markdown

I don't think you need a platform check — the issue is fromtimestamp itself, which raises OSError [Errno 22] on Windows for pre-1970 values, even with tz=utc. Building the datetime from a timedelta sidesteps it and gives the same result:

return (dt.datetime(1970, 1, 1, tzinfo=dt.timezone.utc) + dt.timedelta(seconds=value)).replace(tzinfo=None)

Both of your new cases pass with it on Windows (py3.12): -6272964601950-02-14 14:59:00, and -627296459.421950-02-14 14:59:00.580000.

@lafrech

lafrech commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

Nice. But I suppose this comes with a performance penalty, so I'd rather do it only when necessary.
Maybe we could try this in the except OSError path? And on Windows only.

@HarperZ9

Copy link
Copy Markdown

Good call, that keeps the fast path untouched. On Windows it's fromtimestamp itself that raises the OSError, so the except branch scopes it exactly where it's needed with no explicit platform check:

try:
    return dt.datetime.fromtimestamp(value, tz=dt.timezone.utc).replace(tzinfo=None)
except OSError:
    return (dt.datetime(1970, 1, 1, tzinfo=dt.timezone.utc) + dt.timedelta(seconds=value)).replace(tzinfo=None)

Both new cases pass here on Windows (py3.12): -6272964601950-02-14 14:59:00 and -627296459.421950-02-14 14:59:00.580000, and the positive timestamps never enter the except branch so there's no penalty on the common path.

@lafrech

lafrech commented Aug 26, 2026

Copy link
Copy Markdown
Member Author

It revealed a little more complicated as there are cases where OSError is raised on value overflow. This happens at least on Linux. So I had to catch OverflowError in the OSError handling code.

This implies a slight perf regression on out-of-range values, since we get en OSError, then try again with the timedelta method, only to get an OverflowError from timedelta.

It seems acceptable to penalize an error path for a wider feature coverage.

The code looks ugly, but oh well.

@lafrech
lafrech requested a review from sloria August 26, 2026 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Negative POSIX timestamps cannot be deserialized after timestamp serialization

2 participants