@@ -126,12 +126,14 @@ def is_32bit():
126
126
YEAR_CRON_LEN = len (YEAR_FIELDS )
127
127
# retrocompat
128
128
VALID_LEN_EXPRESSION = set (a for a in CRON_FIELDS if isinstance (a , int ))
129
+ TIMESTAMP_TO_DT_CACHE = {}
129
130
EXPRESSIONS = {}
130
131
try :
131
132
# py3 recent
132
133
UTC_DT = datetime .timezone .utc
133
134
except AttributeError :
134
135
UTC_DT = pytz .utc
136
+ MARKER = object ()
135
137
136
138
137
139
def timedelta_to_seconds (td ):
@@ -324,19 +326,28 @@ def datetime_to_timestamp(d):
324
326
325
327
_datetime_to_timestamp = datetime_to_timestamp # retrocompat
326
328
327
- def timestamp_to_datetime (self , timestamp ):
329
+ def timestamp_to_datetime (self , timestamp , tzinfo = MARKER ):
328
330
"""
329
331
Converts a UNIX timestamp `timestamp` into a `datetime` object.
330
332
"""
333
+ if tzinfo is MARKER : # allow to give tzinfo=None even if self.tzinfo is set
334
+ tzinfo = self .tzinfo
335
+ k = timestamp
336
+ if tzinfo :
337
+ k = (timestamp , repr (tzinfo ))
338
+ try :
339
+ return TIMESTAMP_TO_DT_CACHE [k ]
340
+ except KeyError :
341
+ pass
331
342
if OVERFLOW32B_MODE :
332
343
# degraded mode to workaround Y2038
333
344
# see https://github.com/python/cpython/issues/101069
334
345
result = EPOCH + datetime .timedelta (seconds = timestamp )
335
346
else :
336
347
result = datetime .datetime .fromtimestamp (timestamp , tz = tzutc ()).replace (tzinfo = None )
337
- if self . tzinfo :
338
- result = result .replace (tzinfo = tzutc ()) .astimezone (self . tzinfo )
339
-
348
+ if tzinfo :
349
+ result = result .replace (tzinfo = UTC_DT ) .astimezone (tzinfo )
350
+ TIMESTAMP_TO_DT_CACHE [( result , repr ( result . tzinfo ))] = result
340
351
return result
341
352
342
353
_timestamp_to_datetime = timestamp_to_datetime # retrocompat
0 commit comments