-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
ENH: Support writing timestamps with timezones with to_sql #22654
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
Merged
jorisvandenbossche
merged 36 commits into
pandas-dev:master
from
mroeschke:writing_timezone_sql
Nov 8, 2018
Merged
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
776240b
ENH: Write timezone columns to SQL
befd200
add tests and change type to Timestamp
e9f122f
Lint error and comment our skipif
969d2da
Handle DatetimeTZ block
cc79b90
Ensure the datetimetz data is 2D first
24dbaa5
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
6e86d58
Reading timezones returns timezones in UTC
c7c4a7a
Add whatsnew and some touchups
6aa4878
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
513bbc8
Test other dbs
58772e1
timestamps are actually returned as naive local for myself, sqlite
1a29148
localize -> tz_localize
96e9188
sqlite doesnt support date types
ded5584
type
d575089
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
a7d1b3e
retest
305759c
read_table vs read_query sqlite difference
7a79531
Add note in the to_sql docs
24823f8
Modify whatsnew
7db4eaa
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
76e46dc
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
978a0d3
Address review
8025248
Fix sqlalchemy ref
0e89370
clarify documentation and whatsnew
bab5cfb
Add an api breaking entry change as well
de62788
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
e940279
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
8c754b5
Add new section in whatsnew
e85842f
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
5af83f7
Fix whatsnew to reflect prior bug
6b3a3f1
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
c4304ec
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
1054fdb
handle case when column is datetimeindex
f21c755
Add new whatsnew entry
f872ff7
Merge remote-tracking branch 'upstream/master' into writing_timezone_sql
ef3b20f
don't check name
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -592,12 +592,17 @@ def insert_data(self): | |
data_list = [None] * ncols | ||
blocks = temp._data.blocks | ||
|
||
for i in range(len(blocks)): | ||
b = blocks[i] | ||
for b in blocks: | ||
if b.is_datetime: | ||
# convert to microsecond resolution so this yields | ||
# datetime.datetime | ||
d = b.values.astype('M8[us]').astype(object) | ||
# return datetime.datetime objects | ||
if b.is_datetimetz: | ||
# GH 9086: Ensure we return datetimes with timezone info | ||
# Need to return 2-D data; DatetimeIndex is 1D | ||
d = b.values.to_pydatetime() | ||
d = np.expand_dims(d, axis=0) | ||
else: | ||
# convert to microsecond resolution for datetime.datetime | ||
d = b.values.astype('M8[us]').astype(object) | ||
else: | ||
d = np.array(b.get_values(), dtype=object) | ||
|
||
|
@@ -612,7 +617,7 @@ def insert_data(self): | |
return column_names, data_list | ||
|
||
def _execute_insert(self, conn, keys, data_iter): | ||
data = [{k: v for k, v in zip(keys, row)} for row in data_iter] | ||
data = [dict(zip(keys, row)) for row in data_iter] | ||
conn.execute(self.insert_statement(), data) | ||
|
||
def insert(self, chunksize=None): | ||
|
@@ -741,8 +746,9 @@ def _get_column_names_and_types(self, dtype_mapper): | |
def _create_table_setup(self): | ||
from sqlalchemy import Table, Column, PrimaryKeyConstraint | ||
|
||
column_names_and_types = \ | ||
self._get_column_names_and_types(self._sqlalchemy_type) | ||
column_names_and_types = self._get_column_names_and_types( | ||
self._sqlalchemy_type | ||
) | ||
|
||
columns = [Column(name, typ, index=is_index) | ||
for name, typ, is_index in column_names_and_types] | ||
|
@@ -841,14 +847,19 @@ def _sqlalchemy_type(self, col): | |
|
||
from sqlalchemy.types import (BigInteger, Integer, Float, | ||
Text, Boolean, | ||
DateTime, Date, Time) | ||
DateTime, Date, Time, TIMESTAMP) | ||
|
||
if col_type == 'datetime64' or col_type == 'datetime': | ||
# GH 9086: TIMESTAMP is the suggested type if the column contains | ||
# timezone information | ||
try: | ||
tz = col.tzinfo # noqa | ||
return DateTime(timezone=True) | ||
if col.dt.tz is not None: | ||
return TIMESTAMP(timezone=True) | ||
except AttributeError: | ||
return DateTime | ||
# The column is actually a DatetimeIndex | ||
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. just for my understanding: where was this attribute error catched before? 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. Whoop, sorry, again misunderstanding from not looking at the full diff :-) |
||
if col.tz is not None: | ||
return TIMESTAMP(timezone=True) | ||
return DateTime | ||
if col_type == 'timedelta64': | ||
warnings.warn("the 'timedelta' type is not supported, and will be " | ||
"written as integer values (ns frequency) to the " | ||
|
@@ -1275,8 +1286,9 @@ def _create_table_setup(self): | |
structure of a DataFrame. The first entry will be a CREATE TABLE | ||
statement while the rest will be CREATE INDEX statements. | ||
""" | ||
column_names_and_types = \ | ||
self._get_column_names_and_types(self._sql_type_name) | ||
column_names_and_types = self._get_column_names_and_types( | ||
self._sql_type_name | ||
) | ||
|
||
pat = re.compile(r'\s+') | ||
column_names = [col_name for col_name, _, _ in column_names_and_types] | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
I would move this to the "enhancements" though, I would say that timezones were simply never supported, so it is a nice enhancement that we will now actually support it.
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.
Ah, now looking at the full diff (and not only what changed recently), and see you actually already have that. It's a bit duplicated now, but I am fine with keeping it in both places.