We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
JavaScript negative timestamp are not supported
# Bug

When parsing a JavaScript positive timestamp (number of milliseconds since EPOCH), pydantic parses it properly. However, for a negative JavaScript timestamp (before 1st January 1970), a `date value out of range` error is thrown.

```
  File "pydantic/main.py", line 447, in pydantic.main.BaseModel.parse_obj
  File "pydantic/main.py", line 336, in pydantic.main.BaseModel.__init__
  File "pydantic/main.py", line 887, in pydantic.main.validate_model
  File "pydantic/fields.py", line 549, in pydantic.fields.ModelField.validate
  File "pydantic/fields.py", line 704, in pydantic.fields.ModelField._validate_singleton
  File "pydantic/fields.py", line 711, in pydantic.fields.ModelField._apply_validators
  File "pydantic/class_validators.py", line 313, in pydantic.class_validators._generic_validator_basic.lambda11
  File "pydantic/datetime_parse.py", line 169, in pydantic.datetime_parse.parse_datetime
  File "pydantic/datetime_parse.py", line 80, in pydantic.datetime_parse.from_unix_seconds
OverflowError: date value out of range
```

## Version

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
             pydantic version: 1.5.1
            pydantic compiled: True
                 install path: /Users/thibaud/Documents/Programmation/Scopyleft/Terrapeutes/aposto-server/venv/lib/python3.7/site-packages/pydantic
               python version: 3.7.3 (default, Mar  6 2020, 22:34:30)  [Clang 11.0.3 (clang-1103.0.32.29)]
                     platform: Darwin-19.5.0-x86_64-i386-64bit
     optional deps. installed: ['typing-extensions', 'email-validator']
```

## Code example

The following code raises the describe error (while it would correctly work with `{ "jsTimestamp": 1118102400000 }`).

```py
from datetime import datetime

from pydantic import BaseModel


class MyModel(BaseModel):
    jsTimestamp: datetime

MyModel.parse_obj({ "jsTimestamp": -1118102400000 })
```

## Possible solution

A solution would be to update the `from_unix_seconds` function in _datetime_parse.py_ to compare `seconds` with `MS_WATERSHED` as absolute value.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pydantic/datetime_parse.py`
Content:
```
1 """
2 Functions to parse datetime objects.
3 
4 We're using regular expressions rather than time.strptime because:
5 - They provide both validation and parsing.
6 - They're more flexible for datetimes.
7 - The date/datetime/time constructors produce friendlier error messages.
8 
9 Stolen from https://raw.githubusercontent.com/django/django/master/django/utils/dateparse.py at
10 9718fa2e8abe430c3526a9278dd976443d4ae3c6
11 
12 Changed to:
13 * use standard python datetime types not django.utils.timezone
14 * raise ValueError when regex doesn't match rather than returning None
15 * support parsing unix timestamps for dates and datetimes
16 """
17 import re
18 from datetime import date, datetime, time, timedelta, timezone
19 from typing import Dict, Union
20 
21 from . import errors
22 
23 date_re = re.compile(r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})$')
24 
25 time_re = re.compile(
26     r'(?P<hour>\d{1,2}):(?P<minute>\d{1,2})(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
27 )
28 
29 datetime_re = re.compile(
30     r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})'
31     r'[T ](?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
32     r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
33     r'(?P<tzinfo>Z|[+-]\d{2}(?::?\d{2})?)?$'
34 )
35 
36 standard_duration_re = re.compile(
37     r'^'
38     r'(?:(?P<days>-?\d+) (days?, )?)?'
39     r'((?:(?P<hours>-?\d+):)(?=\d+:\d+))?'
40     r'(?:(?P<minutes>-?\d+):)?'
41     r'(?P<seconds>-?\d+)'
42     r'(?:\.(?P<microseconds>\d{1,6})\d{0,6})?'
43     r'$'
44 )
45 
46 # Support the sections of ISO 8601 date representation that are accepted by timedelta
47 iso8601_duration_re = re.compile(
48     r'^(?P<sign>[-+]?)'
49     r'P'
50     r'(?:(?P<days>\d+(.\d+)?)D)?'
51     r'(?:T'
52     r'(?:(?P<hours>\d+(.\d+)?)H)?'
53     r'(?:(?P<minutes>\d+(.\d+)?)M)?'
54     r'(?:(?P<seconds>\d+(.\d+)?)S)?'
55     r')?'
56     r'$'
57 )
58 
59 EPOCH = datetime(1970, 1, 1)
60 # if greater than this, the number is in ms, if less than or equal it's in seconds
61 # (in seconds this is 11th October 2603, in ms it's 20th August 1970)
62 MS_WATERSHED = int(2e10)
63 StrBytesIntFloat = Union[str, bytes, int, float]
64 
65 
66 def get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]:
67     if isinstance(value, (int, float)):
68         return value
69     try:
70         return float(value)
71     except ValueError:
72         return None
73     except TypeError:
74         raise TypeError(f'invalid type; expected {native_expected_type}, string, bytes, int or float')
75 
76 
77 def from_unix_seconds(seconds: Union[int, float]) -> datetime:
78     while seconds > MS_WATERSHED:
79         seconds /= 1000
80     dt = EPOCH + timedelta(seconds=seconds)
81     return dt.replace(tzinfo=timezone.utc)
82 
83 
84 def parse_date(value: Union[date, StrBytesIntFloat]) -> date:
85     """
86     Parse a date/int/float/string and return a datetime.date.
87 
88     Raise ValueError if the input is well formatted but not a valid date.
89     Raise ValueError if the input isn't well formatted.
90     """
91     if isinstance(value, date):
92         if isinstance(value, datetime):
93             return value.date()
94         else:
95             return value
96 
97     number = get_numeric(value, 'date')
98     if number is not None:
99         return from_unix_seconds(number).date()
100 
101     if isinstance(value, bytes):
102         value = value.decode()
103 
104     match = date_re.match(value)  # type: ignore
105     if match is None:
106         raise errors.DateError()
107 
108     kw = {k: int(v) for k, v in match.groupdict().items()}
109 
110     try:
111         return date(**kw)
112     except ValueError:
113         raise errors.DateError()
114 
115 
116 def parse_time(value: Union[time, StrBytesIntFloat]) -> time:
117     """
118     Parse a time/string and return a datetime.time.
119 
120     This function doesn't support time zone offsets.
121 
122     Raise ValueError if the input is well formatted but not a valid time.
123     Raise ValueError if the input isn't well formatted, in particular if it contains an offset.
124     """
125     if isinstance(value, time):
126         return value
127 
128     number = get_numeric(value, 'time')
129     if number is not None:
130         if number >= 86400:
131             # doesn't make sense since the time time loop back around to 0
132             raise errors.TimeError()
133         return (datetime.min + timedelta(seconds=number)).time()
134 
135     if isinstance(value, bytes):
136         value = value.decode()
137 
138     match = time_re.match(value)  # type: ignore
139     if match is None:
140         raise errors.TimeError()
141 
142     kw = match.groupdict()
143     if kw['microsecond']:
144         kw['microsecond'] = kw['microsecond'].ljust(6, '0')
145 
146     kw_ = {k: int(v) for k, v in kw.items() if v is not None}
147 
148     try:
149         return time(**kw_)  # type: ignore
150     except ValueError:
151         raise errors.TimeError()
152 
153 
154 def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime:
155     """
156     Parse a datetime/int/float/string and return a datetime.datetime.
157 
158     This function supports time zone offsets. When the input contains one,
159     the output uses a timezone with a fixed offset from UTC.
160 
161     Raise ValueError if the input is well formatted but not a valid datetime.
162     Raise ValueError if the input isn't well formatted.
163     """
164     if isinstance(value, datetime):
165         return value
166 
167     number = get_numeric(value, 'datetime')
168     if number is not None:
169         return from_unix_seconds(number)
170 
171     if isinstance(value, bytes):
172         value = value.decode()
173 
174     match = datetime_re.match(value)  # type: ignore
175     if match is None:
176         raise errors.DateTimeError()
177 
178     kw = match.groupdict()
179     if kw['microsecond']:
180         kw['microsecond'] = kw['microsecond'].ljust(6, '0')
181 
182     tzinfo_str = kw.pop('tzinfo')
183     if tzinfo_str == 'Z':
184         tzinfo = timezone.utc
185     elif tzinfo_str is not None:
186         offset_mins = int(tzinfo_str[-2:]) if len(tzinfo_str) > 3 else 0
187         offset = 60 * int(tzinfo_str[1:3]) + offset_mins
188         if tzinfo_str[0] == '-':
189             offset = -offset
190         tzinfo = timezone(timedelta(minutes=offset))
191     else:
192         tzinfo = None
193 
194     kw_: Dict[str, Union[int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None}
195     kw_['tzinfo'] = tzinfo
196 
197     try:
198         return datetime(**kw_)  # type: ignore
199     except ValueError:
200         raise errors.DateTimeError()
201 
202 
203 def parse_duration(value: StrBytesIntFloat) -> timedelta:
204     """
205     Parse a duration int/float/string and return a datetime.timedelta.
206 
207     The preferred format for durations in Django is '%d %H:%M:%S.%f'.
208 
209     Also supports ISO 8601 representation.
210     """
211     if isinstance(value, timedelta):
212         return value
213 
214     if isinstance(value, (int, float)):
215         # bellow code requires a string
216         value = str(value)
217     elif isinstance(value, bytes):
218         value = value.decode()
219 
220     try:
221         match = standard_duration_re.match(value) or iso8601_duration_re.match(value)
222     except TypeError:
223         raise TypeError('invalid type; expected timedelta, string, bytes, int or float')
224 
225     if not match:
226         raise errors.DurationError()
227 
228     kw = match.groupdict()
229     sign = -1 if kw.pop('sign', '+') == '-' else 1
230     if kw.get('microseconds'):
231         kw['microseconds'] = kw['microseconds'].ljust(6, '0')
232 
233     if kw.get('seconds') and kw.get('microseconds') and kw['seconds'].startswith('-'):
234         kw['microseconds'] = '-' + kw['microseconds']
235 
236     kw_ = {k: float(v) for k, v in kw.items() if v is not None}
237 
238     return sign * timedelta(**kw_)  # type: ignore
239
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pydantic/datetime_parse.py b/pydantic/datetime_parse.py
--- a/pydantic/datetime_parse.py
+++ b/pydantic/datetime_parse.py
@@ -75,7 +75,7 @@
 
 
 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)

{"golden_diff": "diff --git a/pydantic/datetime_parse.py b/pydantic/datetime_parse.py\n--- a/pydantic/datetime_parse.py\n+++ b/pydantic/datetime_parse.py\n@@ -75,7 +75,7 @@\n \n \n def from_unix_seconds(seconds: Union[int, float]) -> datetime:\n-    while seconds > MS_WATERSHED:\n+    while abs(seconds) > MS_WATERSHED:\n         seconds /= 1000\n     dt = EPOCH + timedelta(seconds=seconds)\n     return dt.replace(tzinfo=timezone.utc)\n", "issue": "JavaScript negative timestamp are not supported\n# Bug\r\n\r\nWhen parsing a JavaScript positive timestamp (number of milliseconds since EPOCH), pydantic parses it properly. However, for a negative JavaScript timestamp (before 1st January 1970), a `date value out of range` error is thrown.\r\n\r\n```\r\n  File \"pydantic/main.py\", line 447, in pydantic.main.BaseModel.parse_obj\r\n  File \"pydantic/main.py\", line 336, in pydantic.main.BaseModel.__init__\r\n  File \"pydantic/main.py\", line 887, in pydantic.main.validate_model\r\n  File \"pydantic/fields.py\", line 549, in pydantic.fields.ModelField.validate\r\n  File \"pydantic/fields.py\", line 704, in pydantic.fields.ModelField._validate_singleton\r\n  File \"pydantic/fields.py\", line 711, in pydantic.fields.ModelField._apply_validators\r\n  File \"pydantic/class_validators.py\", line 313, in pydantic.class_validators._generic_validator_basic.lambda11\r\n  File \"pydantic/datetime_parse.py\", line 169, in pydantic.datetime_parse.parse_datetime\r\n  File \"pydantic/datetime_parse.py\", line 80, in pydantic.datetime_parse.from_unix_seconds\r\nOverflowError: date value out of range\r\n```\r\n\r\n## Version\r\n\r\nOutput of `python -c \"import pydantic.utils; print(pydantic.utils.version_info())\"`:\r\n```\r\n             pydantic version: 1.5.1\r\n            pydantic compiled: True\r\n                 install path: /Users/thibaud/Documents/Programmation/Scopyleft/Terrapeutes/aposto-server/venv/lib/python3.7/site-packages/pydantic\r\n               python version: 3.7.3 (default, Mar  6 2020, 22:34:30)  [Clang 11.0.3 (clang-1103.0.32.29)]\r\n                     platform: Darwin-19.5.0-x86_64-i386-64bit\r\n     optional deps. installed: ['typing-extensions', 'email-validator']\r\n```\r\n\r\n## Code example\r\n\r\nThe following code raises the describe error (while it would correctly work with `{ \"jsTimestamp\": 1118102400000 }`).\r\n\r\n```py\r\nfrom datetime import datetime\r\n\r\nfrom pydantic import BaseModel\r\n\r\n\r\nclass MyModel(BaseModel):\r\n    jsTimestamp: datetime\r\n\r\nMyModel.parse_obj({ \"jsTimestamp\": -1118102400000 })\r\n```\r\n\r\n## Possible solution\r\n\r\nA solution would be to update the `from_unix_seconds` function in _datetime_parse.py_ to compare `seconds` with `MS_WATERSHED` as absolute value.\n", "before_files": [{"content": "\"\"\"\nFunctions to parse datetime objects.\n\nWe're using regular expressions rather than time.strptime because:\n- They provide both validation and parsing.\n- They're more flexible for datetimes.\n- The date/datetime/time constructors produce friendlier error messages.\n\nStolen from https://raw.githubusercontent.com/django/django/master/django/utils/dateparse.py at\n9718fa2e8abe430c3526a9278dd976443d4ae3c6\n\nChanged to:\n* use standard python datetime types not django.utils.timezone\n* raise ValueError when regex doesn't match rather than returning None\n* support parsing unix timestamps for dates and datetimes\n\"\"\"\nimport re\nfrom datetime import date, datetime, time, timedelta, timezone\nfrom typing import Dict, Union\n\nfrom . import errors\n\ndate_re = re.compile(r'(?P<year>\\d{4})-(?P<month>\\d{1,2})-(?P<day>\\d{1,2})$')\n\ntime_re = re.compile(\n    r'(?P<hour>\\d{1,2}):(?P<minute>\\d{1,2})(?::(?P<second>\\d{1,2})(?:\\.(?P<microsecond>\\d{1,6})\\d{0,6})?)?'\n)\n\ndatetime_re = re.compile(\n    r'(?P<year>\\d{4})-(?P<month>\\d{1,2})-(?P<day>\\d{1,2})'\n    r'[T ](?P<hour>\\d{1,2}):(?P<minute>\\d{1,2})'\n    r'(?::(?P<second>\\d{1,2})(?:\\.(?P<microsecond>\\d{1,6})\\d{0,6})?)?'\n    r'(?P<tzinfo>Z|[+-]\\d{2}(?::?\\d{2})?)?$'\n)\n\nstandard_duration_re = re.compile(\n    r'^'\n    r'(?:(?P<days>-?\\d+) (days?, )?)?'\n    r'((?:(?P<hours>-?\\d+):)(?=\\d+:\\d+))?'\n    r'(?:(?P<minutes>-?\\d+):)?'\n    r'(?P<seconds>-?\\d+)'\n    r'(?:\\.(?P<microseconds>\\d{1,6})\\d{0,6})?'\n    r'$'\n)\n\n# Support the sections of ISO 8601 date representation that are accepted by timedelta\niso8601_duration_re = re.compile(\n    r'^(?P<sign>[-+]?)'\n    r'P'\n    r'(?:(?P<days>\\d+(.\\d+)?)D)?'\n    r'(?:T'\n    r'(?:(?P<hours>\\d+(.\\d+)?)H)?'\n    r'(?:(?P<minutes>\\d+(.\\d+)?)M)?'\n    r'(?:(?P<seconds>\\d+(.\\d+)?)S)?'\n    r')?'\n    r'$'\n)\n\nEPOCH = datetime(1970, 1, 1)\n# if greater than this, the number is in ms, if less than or equal it's in seconds\n# (in seconds this is 11th October 2603, in ms it's 20th August 1970)\nMS_WATERSHED = int(2e10)\nStrBytesIntFloat = Union[str, bytes, int, float]\n\n\ndef get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]:\n    if isinstance(value, (int, float)):\n        return value\n    try:\n        return float(value)\n    except ValueError:\n        return None\n    except TypeError:\n        raise TypeError(f'invalid type; expected {native_expected_type}, string, bytes, int or float')\n\n\ndef from_unix_seconds(seconds: Union[int, float]) -> datetime:\n    while seconds > MS_WATERSHED:\n        seconds /= 1000\n    dt = EPOCH + timedelta(seconds=seconds)\n    return dt.replace(tzinfo=timezone.utc)\n\n\ndef parse_date(value: Union[date, StrBytesIntFloat]) -> date:\n    \"\"\"\n    Parse a date/int/float/string and return a datetime.date.\n\n    Raise ValueError if the input is well formatted but not a valid date.\n    Raise ValueError if the input isn't well formatted.\n    \"\"\"\n    if isinstance(value, date):\n        if isinstance(value, datetime):\n            return value.date()\n        else:\n            return value\n\n    number = get_numeric(value, 'date')\n    if number is not None:\n        return from_unix_seconds(number).date()\n\n    if isinstance(value, bytes):\n        value = value.decode()\n\n    match = date_re.match(value)  # type: ignore\n    if match is None:\n        raise errors.DateError()\n\n    kw = {k: int(v) for k, v in match.groupdict().items()}\n\n    try:\n        return date(**kw)\n    except ValueError:\n        raise errors.DateError()\n\n\ndef parse_time(value: Union[time, StrBytesIntFloat]) -> time:\n    \"\"\"\n    Parse a time/string and return a datetime.time.\n\n    This function doesn't support time zone offsets.\n\n    Raise ValueError if the input is well formatted but not a valid time.\n    Raise ValueError if the input isn't well formatted, in particular if it contains an offset.\n    \"\"\"\n    if isinstance(value, time):\n        return value\n\n    number = get_numeric(value, 'time')\n    if number is not None:\n        if number >= 86400:\n            # doesn't make sense since the time time loop back around to 0\n            raise errors.TimeError()\n        return (datetime.min + timedelta(seconds=number)).time()\n\n    if isinstance(value, bytes):\n        value = value.decode()\n\n    match = time_re.match(value)  # type: ignore\n    if match is None:\n        raise errors.TimeError()\n\n    kw = match.groupdict()\n    if kw['microsecond']:\n        kw['microsecond'] = kw['microsecond'].ljust(6, '0')\n\n    kw_ = {k: int(v) for k, v in kw.items() if v is not None}\n\n    try:\n        return time(**kw_)  # type: ignore\n    except ValueError:\n        raise errors.TimeError()\n\n\ndef parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime:\n    \"\"\"\n    Parse a datetime/int/float/string and return a datetime.datetime.\n\n    This function supports time zone offsets. When the input contains one,\n    the output uses a timezone with a fixed offset from UTC.\n\n    Raise ValueError if the input is well formatted but not a valid datetime.\n    Raise ValueError if the input isn't well formatted.\n    \"\"\"\n    if isinstance(value, datetime):\n        return value\n\n    number = get_numeric(value, 'datetime')\n    if number is not None:\n        return from_unix_seconds(number)\n\n    if isinstance(value, bytes):\n        value = value.decode()\n\n    match = datetime_re.match(value)  # type: ignore\n    if match is None:\n        raise errors.DateTimeError()\n\n    kw = match.groupdict()\n    if kw['microsecond']:\n        kw['microsecond'] = kw['microsecond'].ljust(6, '0')\n\n    tzinfo_str = kw.pop('tzinfo')\n    if tzinfo_str == 'Z':\n        tzinfo = timezone.utc\n    elif tzinfo_str is not None:\n        offset_mins = int(tzinfo_str[-2:]) if len(tzinfo_str) > 3 else 0\n        offset = 60 * int(tzinfo_str[1:3]) + offset_mins\n        if tzinfo_str[0] == '-':\n            offset = -offset\n        tzinfo = timezone(timedelta(minutes=offset))\n    else:\n        tzinfo = None\n\n    kw_: Dict[str, Union[int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None}\n    kw_['tzinfo'] = tzinfo\n\n    try:\n        return datetime(**kw_)  # type: ignore\n    except ValueError:\n        raise errors.DateTimeError()\n\n\ndef parse_duration(value: StrBytesIntFloat) -> timedelta:\n    \"\"\"\n    Parse a duration int/float/string and return a datetime.timedelta.\n\n    The preferred format for durations in Django is '%d %H:%M:%S.%f'.\n\n    Also supports ISO 8601 representation.\n    \"\"\"\n    if isinstance(value, timedelta):\n        return value\n\n    if isinstance(value, (int, float)):\n        # bellow code requires a string\n        value = str(value)\n    elif isinstance(value, bytes):\n        value = value.decode()\n\n    try:\n        match = standard_duration_re.match(value) or iso8601_duration_re.match(value)\n    except TypeError:\n        raise TypeError('invalid type; expected timedelta, string, bytes, int or float')\n\n    if not match:\n        raise errors.DurationError()\n\n    kw = match.groupdict()\n    sign = -1 if kw.pop('sign', '+') == '-' else 1\n    if kw.get('microseconds'):\n        kw['microseconds'] = kw['microseconds'].ljust(6, '0')\n\n    if kw.get('seconds') and kw.get('microseconds') and kw['seconds'].startswith('-'):\n        kw['microseconds'] = '-' + kw['microseconds']\n\n    kw_ = {k: float(v) for k, v in kw.items() if v is not None}\n\n    return sign * timedelta(**kw_)  # type: ignore\n", "path": "pydantic/datetime_parse.py"}], "after_files": [{"content": "\"\"\"\nFunctions to parse datetime objects.\n\nWe're using regular expressions rather than time.strptime because:\n- They provide both validation and parsing.\n- They're more flexible for datetimes.\n- The date/datetime/time constructors produce friendlier error messages.\n\nStolen from https://raw.githubusercontent.com/django/django/master/django/utils/dateparse.py at\n9718fa2e8abe430c3526a9278dd976443d4ae3c6\n\nChanged to:\n* use standard python datetime types not django.utils.timezone\n* raise ValueError when regex doesn't match rather than returning None\n* support parsing unix timestamps for dates and datetimes\n\"\"\"\nimport re\nfrom datetime import date, datetime, time, timedelta, timezone\nfrom typing import Dict, Union\n\nfrom . import errors\n\ndate_re = re.compile(r'(?P<year>\\d{4})-(?P<month>\\d{1,2})-(?P<day>\\d{1,2})$')\n\ntime_re = re.compile(\n    r'(?P<hour>\\d{1,2}):(?P<minute>\\d{1,2})(?::(?P<second>\\d{1,2})(?:\\.(?P<microsecond>\\d{1,6})\\d{0,6})?)?'\n)\n\ndatetime_re = re.compile(\n    r'(?P<year>\\d{4})-(?P<month>\\d{1,2})-(?P<day>\\d{1,2})'\n    r'[T ](?P<hour>\\d{1,2}):(?P<minute>\\d{1,2})'\n    r'(?::(?P<second>\\d{1,2})(?:\\.(?P<microsecond>\\d{1,6})\\d{0,6})?)?'\n    r'(?P<tzinfo>Z|[+-]\\d{2}(?::?\\d{2})?)?$'\n)\n\nstandard_duration_re = re.compile(\n    r'^'\n    r'(?:(?P<days>-?\\d+) (days?, )?)?'\n    r'((?:(?P<hours>-?\\d+):)(?=\\d+:\\d+))?'\n    r'(?:(?P<minutes>-?\\d+):)?'\n    r'(?P<seconds>-?\\d+)'\n    r'(?:\\.(?P<microseconds>\\d{1,6})\\d{0,6})?'\n    r'$'\n)\n\n# Support the sections of ISO 8601 date representation that are accepted by timedelta\niso8601_duration_re = re.compile(\n    r'^(?P<sign>[-+]?)'\n    r'P'\n    r'(?:(?P<days>\\d+(.\\d+)?)D)?'\n    r'(?:T'\n    r'(?:(?P<hours>\\d+(.\\d+)?)H)?'\n    r'(?:(?P<minutes>\\d+(.\\d+)?)M)?'\n    r'(?:(?P<seconds>\\d+(.\\d+)?)S)?'\n    r')?'\n    r'$'\n)\n\nEPOCH = datetime(1970, 1, 1)\n# if greater than this, the number is in ms, if less than or equal it's in seconds\n# (in seconds this is 11th October 2603, in ms it's 20th August 1970)\nMS_WATERSHED = int(2e10)\nStrBytesIntFloat = Union[str, bytes, int, float]\n\n\ndef get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]:\n    if isinstance(value, (int, float)):\n        return value\n    try:\n        return float(value)\n    except ValueError:\n        return None\n    except TypeError:\n        raise TypeError(f'invalid type; expected {native_expected_type}, string, bytes, int or float')\n\n\ndef from_unix_seconds(seconds: Union[int, float]) -> datetime:\n    while abs(seconds) > MS_WATERSHED:\n        seconds /= 1000\n    dt = EPOCH + timedelta(seconds=seconds)\n    return dt.replace(tzinfo=timezone.utc)\n\n\ndef parse_date(value: Union[date, StrBytesIntFloat]) -> date:\n    \"\"\"\n    Parse a date/int/float/string and return a datetime.date.\n\n    Raise ValueError if the input is well formatted but not a valid date.\n    Raise ValueError if the input isn't well formatted.\n    \"\"\"\n    if isinstance(value, date):\n        if isinstance(value, datetime):\n            return value.date()\n        else:\n            return value\n\n    number = get_numeric(value, 'date')\n    if number is not None:\n        return from_unix_seconds(number).date()\n\n    if isinstance(value, bytes):\n        value = value.decode()\n\n    match = date_re.match(value)  # type: ignore\n    if match is None:\n        raise errors.DateError()\n\n    kw = {k: int(v) for k, v in match.groupdict().items()}\n\n    try:\n        return date(**kw)\n    except ValueError:\n        raise errors.DateError()\n\n\ndef parse_time(value: Union[time, StrBytesIntFloat]) -> time:\n    \"\"\"\n    Parse a time/string and return a datetime.time.\n\n    This function doesn't support time zone offsets.\n\n    Raise ValueError if the input is well formatted but not a valid time.\n    Raise ValueError if the input isn't well formatted, in particular if it contains an offset.\n    \"\"\"\n    if isinstance(value, time):\n        return value\n\n    number = get_numeric(value, 'time')\n    if number is not None:\n        if number >= 86400:\n            # doesn't make sense since the time time loop back around to 0\n            raise errors.TimeError()\n        return (datetime.min + timedelta(seconds=number)).time()\n\n    if isinstance(value, bytes):\n        value = value.decode()\n\n    match = time_re.match(value)  # type: ignore\n    if match is None:\n        raise errors.TimeError()\n\n    kw = match.groupdict()\n    if kw['microsecond']:\n        kw['microsecond'] = kw['microsecond'].ljust(6, '0')\n\n    kw_ = {k: int(v) for k, v in kw.items() if v is not None}\n\n    try:\n        return time(**kw_)  # type: ignore\n    except ValueError:\n        raise errors.TimeError()\n\n\ndef parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime:\n    \"\"\"\n    Parse a datetime/int/float/string and return a datetime.datetime.\n\n    This function supports time zone offsets. When the input contains one,\n    the output uses a timezone with a fixed offset from UTC.\n\n    Raise ValueError if the input is well formatted but not a valid datetime.\n    Raise ValueError if the input isn't well formatted.\n    \"\"\"\n    if isinstance(value, datetime):\n        return value\n\n    number = get_numeric(value, 'datetime')\n    if number is not None:\n        return from_unix_seconds(number)\n\n    if isinstance(value, bytes):\n        value = value.decode()\n\n    match = datetime_re.match(value)  # type: ignore\n    if match is None:\n        raise errors.DateTimeError()\n\n    kw = match.groupdict()\n    if kw['microsecond']:\n        kw['microsecond'] = kw['microsecond'].ljust(6, '0')\n\n    tzinfo_str = kw.pop('tzinfo')\n    if tzinfo_str == 'Z':\n        tzinfo = timezone.utc\n    elif tzinfo_str is not None:\n        offset_mins = int(tzinfo_str[-2:]) if len(tzinfo_str) > 3 else 0\n        offset = 60 * int(tzinfo_str[1:3]) + offset_mins\n        if tzinfo_str[0] == '-':\n            offset = -offset\n        tzinfo = timezone(timedelta(minutes=offset))\n    else:\n        tzinfo = None\n\n    kw_: Dict[str, Union[int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None}\n    kw_['tzinfo'] = tzinfo\n\n    try:\n        return datetime(**kw_)  # type: ignore\n    except ValueError:\n        raise errors.DateTimeError()\n\n\ndef parse_duration(value: StrBytesIntFloat) -> timedelta:\n    \"\"\"\n    Parse a duration int/float/string and return a datetime.timedelta.\n\n    The preferred format for durations in Django is '%d %H:%M:%S.%f'.\n\n    Also supports ISO 8601 representation.\n    \"\"\"\n    if isinstance(value, timedelta):\n        return value\n\n    if isinstance(value, (int, float)):\n        # bellow code requires a string\n        value = str(value)\n    elif isinstance(value, bytes):\n        value = value.decode()\n\n    try:\n        match = standard_duration_re.match(value) or iso8601_duration_re.match(value)\n    except TypeError:\n        raise TypeError('invalid type; expected timedelta, string, bytes, int or float')\n\n    if not match:\n        raise errors.DurationError()\n\n    kw = match.groupdict()\n    sign = -1 if kw.pop('sign', '+') == '-' else 1\n    if kw.get('microseconds'):\n        kw['microseconds'] = kw['microseconds'].ljust(6, '0')\n\n    if kw.get('seconds') and kw.get('microseconds') and kw['seconds'].startswith('-'):\n        kw['microseconds'] = '-' + kw['microseconds']\n\n    kw_ = {k: float(v) for k, v in kw.items() if v is not None}\n\n    return sign * timedelta(**kw_)  # type: ignore\n", "path": "pydantic/datetime_parse.py"}]}