Skip to content

Commit

Permalink
BUG: edge case when reading from postgresl with read_sql_query and da…
Browse files Browse the repository at this point in the history
…tetime with timezone types and a chunksize, #11216

- When we don't specifiy a chunksize we get an object dtype
  which is ok
- We create a propery datetime64[ns, tz] type, but its a
  pytz.FixedOffset(....), which ATM is not really a
  useful/palatable type and is mostly confusing for now.
  In the future could attempt to coerce this to a nice tz,
  e.g. US/Eastern, not sure if this is possible
- Note that this is w/o parse_dates specified
  • Loading branch information
jreback committed Oct 3, 2015
1 parent dff4534 commit dc3de6a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 1 deletion.
10 changes: 9 additions & 1 deletion pandas/io/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ def _parse_date_columns(data_frame, parse_dates):
fmt = None
data_frame[col_name] = _handle_date_column(df_col, format=fmt)


# we want to coerce datetime64_tz dtypes for now
# we could in theory do a 'nice' conversion from a FixedOffset tz
# GH11216
for col_name, df_col in data_frame.iteritems():
if com.is_datetime64tz_dtype(df_col):
data_frame[col_name] = _handle_date_column(df_col)

return data_frame


Expand Down Expand Up @@ -366,7 +374,7 @@ def read_sql_query(sql, con, index_col=None, coerce_float=True, params=None,
----------
sql : string SQL query or SQLAlchemy Selectable (select or text object)
to be executed.
con : SQLAlchemy connectable(engine/connection) or database string URI
con : SQLAlchemy connectable(engine/connection) or database string URI
or sqlite3 DBAPI2 connection
Using SQLAlchemy makes it possible to use any DB supported by that
library.
Expand Down
35 changes: 35 additions & 0 deletions pandas/io/tests/test_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
import nose
import warnings
import numpy as np
import pandas as pd

from datetime import datetime, date, time

from pandas import DataFrame, Series, Index, MultiIndex, isnull, concat
from pandas import date_range, to_datetime, to_timedelta, Timestamp
import pandas.compat as compat
from pandas.compat import StringIO, range, lrange, string_types
from pandas.core import common as com
from pandas.core.datetools import format as date_format

import pandas.io.sql as sql
Expand Down Expand Up @@ -1248,6 +1250,39 @@ def test_default_date_load(self):
self.assertTrue(issubclass(df.DateCol.dtype.type, np.datetime64),
"DateCol loaded with incorrect type")

def test_datetime_with_timezone(self):
# edge case that converts postgresql datetime with time zone types
# to datetime64[ns,psycopg2.tz.FixedOffsetTimezone..], which is ok
# but should be more natural, so coerce to datetime64[ns] for now

# GH11216
df = pd.read_sql_query("select * from types_test_data", self.conn)
if not hasattr(df,'DateColWithTz'):
raise nose.SkipTest("no column with datetime with time zone")

# this is parsed on Travis (linux), but not on macosx for some reason
# even with the same versions of psycopg2 & sqlalchemy, possibly a Postgrsql server
# version difference
dtype = df.DateColWithTz.dtype
self.assertTrue(com.is_object_dtype(dtype) or com.is_datetime64_dtype(dtype),
"DateCol loaded with incorrect type -> {0}".format(dtype))

df = pd.read_sql_query("select * from types_test_data", self.conn, parse_dates=['DateColWithTz'])
if not hasattr(df,'DateColWithTz'):
raise nose.SkipTest("no column with datetime with time zone")

dtype = df.DateColWithTz.dtype
self.assertTrue(com.is_datetime64_dtype(dtype),
"DateCol loaded with incorrect type -> {0}".format(dtype))

df = pd.concat(list(pd.read_sql_query("select * from types_test_data",
self.conn,chunksize=1)),ignore_index=True)
dtype = df.DateColWithTz.dtype
self.assertTrue(com.is_datetime64_dtype(dtype),
"DateCol loaded with incorrect type -> {0}".format(dtype))
expected = sql.read_sql_table("types_test_data", self.conn)
tm.assert_series_equal(df.DateColWithTz, expected.DateColWithTz)

def test_date_parsing(self):
# No Parsing
df = sql.read_sql_table("types_test_data", self.conn)
Expand Down

0 comments on commit dc3de6a

Please sign in to comment.