Skip to content

Commit e899946

Browse files
author
James William Pye
committed
Improve datetime+tz performance.
1 parent e4bc199 commit e899946

1 file changed

Lines changed: 45 additions & 19 deletions

File tree

postgresql/types/io/stdlib_datetime.py

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
seconds_in_hour = 60 * 60
3838

3939
pg_epoch_datetime = datetime.datetime(2000, 1, 1)
40+
pg_epoch_datetime_utc = pg_epoch_datetime.replace(tzinfo = UTC)
4041
pg_epoch_date = pg_epoch_datetime.date()
4142
pg_date_offset = pg_epoch_date.toordinal()
42-
pg_minus_date_offset = -pg_date_offset
4343

4444
## Difference between PostgreSQL epoch and Unix epoch.
4545
## Used to convert a PostgreSQL ordinal to an ordinal usable by datetime
@@ -96,20 +96,43 @@ def date_unpack(x,
9696
):
9797
return get(x) or from_ord(unpack(x) + pg_date_offset)
9898

99-
def timestamp_pack(x):
99+
def timestamp_pack(x,
100+
seconds_in_day = seconds_in_day,
101+
pg_epoch_datetime = pg_epoch_datetime,
102+
):
100103
"""
101104
Create a (seconds, microseconds) pair from a `datetime.datetime` instance.
102105
"""
103-
d = (x - pg_epoch_datetime)
104-
return ((d.days * seconds_in_day) + d.seconds, d.microseconds)
106+
x = (x - pg_epoch_datetime)
107+
return ((x.days * seconds_in_day) + x.seconds, x.microseconds)
105108

106-
def timestamp_unpack(seconds, timedelta = datetime.timedelta):
109+
def timestamp_unpack(seconds,
110+
timedelta = datetime.timedelta,
111+
pg_epoch_datetime = pg_epoch_datetime,
112+
):
107113
"""
108114
Create a `datetime.datetime` instance from a (seconds, microseconds) pair.
109115
"""
110-
return pg_epoch_datetime + timedelta(
111-
seconds = seconds[0], microseconds = seconds[1]
112-
)
116+
return pg_epoch_datetime + timedelta(0, *seconds)
117+
118+
def timestamptz_pack(x,
119+
seconds_in_day = seconds_in_day,
120+
pg_epoch_datetime_utc = pg_epoch_datetime_utc,
121+
):
122+
"""
123+
Create a (seconds, microseconds) pair from a `datetime.datetime` instance.
124+
"""
125+
x = (x - pg_epoch_datetime_utc)
126+
return ((x.days * seconds_in_day) + x.seconds, x.microseconds)
127+
128+
def timestamptz_unpack(seconds,
129+
timedelta = datetime.timedelta,
130+
pg_epoch_datetime_utc = pg_epoch_datetime_utc,
131+
):
132+
"""
133+
Create a `datetime.datetime` instance from a (seconds, microseconds) pair.
134+
"""
135+
return pg_epoch_datetime_utc + timedelta(0, *seconds)
113136

114137
def time_pack(x):
115138
"""
@@ -153,13 +176,14 @@ def interval_unpack(mds, timedelta = datetime.timedelta):
153176
source = 'DRIVER'
154177
)
155178
warnings.warn(w)
156-
sec, ms = seconds_ms
157179
return timedelta(
158180
days = days + (months * 30),
159-
seconds = sec, microseconds = ms
181+
seconds = seconds_ms[0], microseconds = seconds_ms[1]
160182
)
161183

162-
def timetz_pack(x):
184+
def timetz_pack(x,
185+
time_pack = time_pack,
186+
):
163187
"""
164188
Create a ((seconds, microseconds), timezone) tuple from a `datetime.time`
165189
instance.
@@ -168,7 +192,10 @@ def timetz_pack(x):
168192
seconds = (td.days * seconds_in_day + td.seconds)
169193
return (time_pack(x), seconds)
170194

171-
def timetz_unpack(tstz):
195+
def timetz_unpack(tstz,
196+
time_unpack = time_unpack,
197+
FixedOffset = FixedOffset,
198+
):
172199
"""
173200
Create a `datetime.time` instance from a ((seconds, microseconds), timezone)
174201
tuple.
@@ -183,9 +210,8 @@ def timetz_unpack(tstz):
183210

184211
# Used to handle the special cases: infinity and -infinity.
185212
def proc_when_not_in(proc, dict):
186-
def _proc(x):
187-
r = dict.get(x)
188-
return r or proc(x)
213+
def _proc(x, get=dict.get):
214+
return get(x) or proc(x)
189215
return _proc
190216

191217
id_to_io = {
@@ -205,8 +231,8 @@ def _proc(x):
205231
datetime.datetime
206232
),
207233
(FloatTimes, TIMESTAMPTZOID) : (
208-
proc_when_not_in(compose((convert_to_utc, remove_tzinfo, timestamp_pack, lib.time_pack)), time_pack_constants),
209-
proc_when_not_in(compose((lib.time_unpack, timestamp_unpack, set_as_utc)), time_unpack_constants),
234+
proc_when_not_in(compose((convert_to_utc, timestamptz_pack, lib.time_pack)), time_pack_constants),
235+
proc_when_not_in(compose((lib.time_unpack, timestamptz_unpack)), time_unpack_constants),
210236
datetime.datetime
211237
),
212238
(FloatTimes, WithDay, INTERVALOID): (
@@ -236,8 +262,8 @@ def _proc(x):
236262
datetime.datetime
237263
),
238264
(IntTimes, TIMESTAMPTZOID) : (
239-
proc_when_not_in(compose((convert_to_utc, remove_tzinfo, timestamp_pack, lib.time64_pack)), time64_pack_constants),
240-
proc_when_not_in(compose((lib.time64_unpack, timestamp_unpack, set_as_utc)), time64_unpack_constants),
265+
proc_when_not_in(compose((convert_to_utc, timestamptz_pack, lib.time64_pack)), time64_pack_constants),
266+
proc_when_not_in(compose((lib.time64_unpack, timestamptz_unpack)), time64_unpack_constants),
241267
datetime.datetime
242268
),
243269
(IntTimes, WithDay, INTERVALOID) : (

0 commit comments

Comments
 (0)