marshmallow-code / marshmallow-code/marshmallow

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

Open Beginner friendly
#3,019 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
7.2k
Forks
738
Avg merge
1d 23h
Merged PRs (30d)
7

Description

## Bug description

`fields.DateTime(format="timestamp")` can serialize valid datetimes before the Unix epoch (1970) into negative POSIX timestamps, but `marshmallow` then rejects those same negative values when deserializing them.

This creates a round-trip failure where a value produced by Marshmallow cannot be read back by the same field.

## Reproduction

```python
from datetime import datetime, timezone

from marshmallow import fields

field = fields.DateTime(format="timestamp")

value = datetime(1950, 5, 3, tzinfo=timezone.utc)

serialized = field.serialize("date", {"date": value})
print(serialized)
# -620568000.0

field.deserialize(serialized)
# marshmallow.exceptions.ValidationError:
# Not a valid datetime.
```

The underlying Python `datetime.fromtimestamp()` supports negative timestamps, so the negative value itself is valid.

## Expected behavior

A timestamp produced by `fields.DateTime(format="timestamp")` should be accepted by the corresponding deserializer, including valid negative POSIX timestamps representing dates before 1970.

## Actual behavior

Negative POSIX timestamps are rejected during deserialization, even though the serializer can produce them from valid pre-1970 datetimes.

This means timestamp serialization is not reliably round-tripable for dates before the Unix epoch.

## Root cause

`marshmallow.utils.from_timestamp()` explicitly rejects values below zero before calling Python's timestamp conversion.

The underlying `datetime.fromtimestamp()` implementation can correctly handle these negative values, so the explicit negative-value restriction is unnecessarily broad.

Existing `OSError` and `OverflowError` handling can continue to handle genuine platform-specific timestamp conversion failures.

## Proposed fix

Remove the explicit rejection of negative timestamp values from `from_timestamp()` and rely on the existing timestamp conversion and exception handling.

Add regression coverage that:

1. Serializes valid pre-1970 datetimes using both `timestamp` and `timestamp_ms`.
2. Confirms the serialized values are negative.
3. Deserializes those values.
4. Confirms the original datetimes are recovered.

## Validation

I have reproduced the issue on the current development branch.

The regression test fails on the unfixed implementation and passes after the proposed fix.

The full test suite passes with the fix.

I would like to contribute a fix for this issue.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at marshmallow.utils.from_timestamp() and the fields.DateTime timestamp deserialization path. Add regression coverage for negative values from both timestamp and timestamp_ms serialization, then verify the original pre-1970 datetimes are recovered and the full test suite passes.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend-api-design
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.