Skip to content

Commit a7e1e19

Browse files
committed
Better timestamp to datetime helper
1 parent d1ce63a commit a7e1e19

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

src/croniter/croniter.py

+15-4
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,14 @@ def is_32bit():
126126
YEAR_CRON_LEN = len(YEAR_FIELDS)
127127
# retrocompat
128128
VALID_LEN_EXPRESSION = set(a for a in CRON_FIELDS if isinstance(a, int))
129+
TIMESTAMP_TO_DT_CACHE = {}
129130
EXPRESSIONS = {}
130131
try:
131132
# py3 recent
132133
UTC_DT = datetime.timezone.utc
133134
except AttributeError:
134135
UTC_DT = pytz.utc
136+
MARKER = object()
135137

136138

137139
def timedelta_to_seconds(td):
@@ -324,19 +326,28 @@ def datetime_to_timestamp(d):
324326

325327
_datetime_to_timestamp = datetime_to_timestamp # retrocompat
326328

327-
def timestamp_to_datetime(self, timestamp):
329+
def timestamp_to_datetime(self, timestamp, tzinfo=MARKER):
328330
"""
329331
Converts a UNIX timestamp `timestamp` into a `datetime` object.
330332
"""
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
331342
if OVERFLOW32B_MODE:
332343
# degraded mode to workaround Y2038
333344
# see https://github.com/python/cpython/issues/101069
334345
result = EPOCH + datetime.timedelta(seconds=timestamp)
335346
else:
336347
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
340351
return result
341352

342353
_timestamp_to_datetime = timestamp_to_datetime # retrocompat

0 commit comments

Comments
 (0)