Skip to content

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

Description

@Sohel2309

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

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.

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