-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Followup: Return TIMESTAMP columns as native Python datetime objects #437
Changes from 22 commits
312eb24
41a881d
49076da
c053da3
feebd45
6566879
a38860b
e4fa0fa
77b6550
ee77ec1
5b33589
7e39244
f750966
e6facf3
e6887f4
a8ffdc3
1c46079
8ce9209
ccc00a1
a8532c5
2cc1b90
f355164
3154d32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
|
||
from .exceptions import ProgrammingError | ||
import warnings | ||
from datetime import datetime | ||
|
||
|
||
class Cursor(object): | ||
|
@@ -49,9 +50,47 @@ def execute(self, sql, parameters=None, bulk_parameters=None): | |
|
||
self._result = self.connection.client.sql(sql, parameters, | ||
bulk_parameters) | ||
if "rows" in self._result: | ||
|
||
if "rows" not in self._result: | ||
return | ||
|
||
if "col_types" in self._result: | ||
self.rows = iter(self._transform_result_types()) | ||
|
||
else: | ||
self.rows = iter(self._result["rows"]) | ||
|
||
def _transform_result_types(self): | ||
""" | ||
Generate row items with column values converted to their corresponding | ||
native Python types, based on information from `col_types`. | ||
|
||
Currently, only converting to native `datetime` objects is implemented. | ||
""" | ||
datetime_column_types = [11, 15] | ||
datetime_columns_mask = [ | ||
True if col_type in datetime_column_types else False | ||
for col_type in self._result["col_types"] | ||
] | ||
for row in self._result["rows"]: | ||
yield list(self._transform_datetime_columns(row, iter(datetime_columns_mask))) | ||
|
||
@staticmethod | ||
def _transform_datetime_columns(row, column_flags): | ||
""" | ||
Convert all designated columns to native Python `datetime` objects. | ||
""" | ||
for value in row: | ||
try: | ||
flag = next(column_flags) | ||
except StopIteration: | ||
break | ||
|
||
if flag and value is not None: | ||
value = datetime.fromtimestamp(value / 1e3) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think using There are two scenarios: The user stores UTC on the server:
The user stores local timestamps on the server. Unless they also store the timezone in a separate field this is error prone but
It's important that we don't attach a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another option could be to to let users configure the timezone on the client (with default UTC) and always create timezone aware objects. The default could turn out to be wrong, but at least the user has an easy option to fix it, and it's easier to spot a incorrectly attached tzone then it is to figure out that a conversion happened and why/where some conversion happend. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. With 3154d32, I've switched to use
Shall we bring in the timezone awareness (#359, #361) with a subsequent patch right after this one? |
||
|
||
yield value | ||
|
||
def executemany(self, sql, seq_of_parameters): | ||
""" | ||
Prepare a database operation (query or command) and then execute it | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,9 +80,6 @@ Date should have been set at the insert due to default value via python method:: | |
>>> dt.day == now.day | ||
True | ||
|
||
>>> (now - location.datetime_tz).seconds < 4 | ||
True | ||
|
||
Comment on lines
-83
to
-85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did this test case protect against anything significant? Currently, it croaks on my machine with a difference of |
||
Verify the return type of date and datetime:: | ||
|
||
>>> type(location.date) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does someone have a resource at hand where those column code types are enumerated? The table at 1 coincidentally lists
_timestamp without time zone
as1115
, but here the code is apparently expecting two-digit integer numbers.I will be happy to receive further pointers for better educating myself on this topic.
Footnotes
https://crate.io/docs/crate/reference/en/5.0/interfaces/postgres.html#pg-type ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://crate.io/docs/crate/reference/en/5.0/interfaces/http.html#column-types
The code here will probably also need to handle arrays of timestamps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I will add the conversion for container types as well.
Reading up on your reference, I am asking myself whether it is appropriate that
type=15
(Unchecked object) is handled here as well?