marshmallow-code / marshmallow-code/marshmallow
[Bug] Negative POSIX timestamps cannot be deserialized after timestamp serialization
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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