diff --git a/changes/1600-mlbiche.md b/changes/1600-mlbiche.md new file mode 100644 index 0000000000..e58c4f500c --- /dev/null +++ b/changes/1600-mlbiche.md @@ -0,0 +1 @@ +Update datetime parser to support negative timestamps diff --git a/docs/usage/types.md b/docs/usage/types.md index a9b2a451b1..67db54fe5c 100644 --- a/docs/usage/types.md +++ b/docs/usage/types.md @@ -248,7 +248,7 @@ types: * `datetime` fields can be: * `datetime`, existing `datetime` object - * `int` or `float`, assumed as Unix time, i.e. seconds (if <= `2e10`) or milliseconds (if > `2e10`) since 1 January 1970 + * `int` or `float`, assumed as Unix time, i.e. seconds (if >= `-2e10` or <= `2e10`) or milliseconds (if < `-2e10`or > `2e10`) since 1 January 1970 * `str`, following formats work: * `YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z[±]HH[:]MM]]]` diff --git a/pydantic/datetime_parse.py b/pydantic/datetime_parse.py index 69e7882dfb..1bdc13a3af 100644 --- a/pydantic/datetime_parse.py +++ b/pydantic/datetime_parse.py @@ -75,7 +75,7 @@ def get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[Non def from_unix_seconds(seconds: Union[int, float]) -> datetime: - while seconds > MS_WATERSHED: + while abs(seconds) > MS_WATERSHED: seconds /= 1000 dt = EPOCH + timedelta(seconds=seconds) return dt.replace(tzinfo=timezone.utc) diff --git a/tests/test_datetime_parse.py b/tests/test_datetime_parse.py index 545a499b57..20cba7b2b0 100644 --- a/tests/test_datetime_parse.py +++ b/tests/test_datetime_parse.py @@ -93,6 +93,7 @@ def test_time_parsing(value, result): (1_494_012_444, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), # values in ms ('1494012444000.883309', datetime(2017, 5, 5, 19, 27, 24, 883, tzinfo=timezone.utc)), + ('-1494012444000.883309', datetime(1922, 8, 29, 4, 32, 35, 999117, tzinfo=timezone.utc)), (1_494_012_444_000, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), ('2012-04-23T09:15:00', datetime(2012, 4, 23, 9, 15)), ('2012-4-9 4:8:16', datetime(2012, 4, 9, 4, 8, 16)),