Make TLObject.serialize_datetime Windows safe.

Also use the '<i' format for struct.pack, as per #1242
This commit is contained in:
binares 2019-07-26 03:04:13 +03:00 committed by GitHub
parent c1123e1eb3
commit 318456cd05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,8 +1,12 @@
import base64 import base64
import json import json
import struct import struct
from datetime import datetime, date, timedelta from datetime import datetime, date, timedelta, timezone
import time
_EPOCH_NATIVE = datetime(*time.gmtime(0)[:6])
_EPOCH_NATIVE_LOCAL = datetime(*time.localtime(0)[:6])
_EPOCH = _EPOCH_NATIVE.replace(tzinfo=timezone.utc)
def _json_default(value): def _json_default(value):
if isinstance(value, bytes): if isinstance(value, bytes):
@ -125,17 +129,21 @@ class TLObject:
return b'\0\0\0\0' return b'\0\0\0\0'
if isinstance(dt, datetime): if isinstance(dt, datetime):
dt = int(dt.timestamp()) #If no tzinfo is provided then we assume dt is in local timezone
epoch_selected = _EPOCH_NATIVE_LOCAL if dt.tzinfo is None else _EPOCH
#We use .total_seconds() method instead of simply dt.timestamp(),
#because on Windows the latter raises OSError on datetimes ~< datetime(1970,1,1)
dt = int((dt - epoch_selected).total_seconds())
elif isinstance(dt, date): elif isinstance(dt, date):
dt = int(datetime(dt.year, dt.month, dt.day).timestamp()) dt = int((datetime(dt.year, dt.month, dt.day) - _EPOCH_NATIVE_LOCAL).total_seconds())
elif isinstance(dt, float): elif isinstance(dt, float):
dt = int(dt) dt = int(dt)
elif isinstance(dt, timedelta): elif isinstance(dt, timedelta):
# Timezones are tricky. datetime.now() + ... timestamp() works # Timezones are tricky. datetime.now() + ... timestamp() works
dt = int((datetime.now() + dt).timestamp()) dt = int(((datetime.now() + dt) - _EPOCH_NATIVE_LOCAL).total_seconds())
if isinstance(dt, int): if isinstance(dt, int):
return struct.pack('<I', dt) return struct.pack('<i', dt)
raise TypeError('Cannot interpret "{}" as a date.'.format(dt)) raise TypeError('Cannot interpret "{}" as a date.'.format(dt))