我想使用pandas to_sql在postgresql中存储一个时区感知列。
当时间不是时区感知时,它可以正常工作
times = ['201510100222', '201510110333']
df = pd.DataFrame()
df['time'] = pd.to_datetime(times)
df.time.to_sql('test', engine, if_exists='replace', index=False)
但是当我指定UTC
时times = ['201510100222', '201510110333']
df = pd.DataFrame()
df['time'] = pd.to_datetime(times, utc=True)
df.time.to_sql('test', engine, if_exists='replace', index=False)
我有以下错误:
ValueError: Cannot cast DatetimeIndex to dtype datetime64[us]
我使用的是python 3.4.3,postgresql 9.4,pandas 0.17.1,sqlalchemy 1.0.5
答案 0 :(得分:6)
您必须将其存储为PostgreSQL中的pd.Timestamp。下面的代码对我有用:
times = ['201510100222', '201510110333']
df = pd.DataFrame()
df['time'] = pd.to_datetime(times, utc=True)
df['time'] = df['time'].astype(pd.Timestamp)
df.time.to_sql('test', engine, if_exists='replace', index=False)
但是不要忘记正确创建数据类型为TIMESTAMP WITH TIME ZONE的数据库表。如果要直接从to_sql命令构建表,则必须明确指定它:
from sqlalchemy.types import TIMESTAMP as typeTIMESTAMP
df.time.to_sql('test', engine, if_exists='replace', index=False,dtype=typeTIMESTAMP(timezone=True))
答案 1 :(得分:2)
您可以将日期时间转换为字符串:
from sqlalchemy import TIMESTAMP
df.to_sql('test', engine, if_exists='replace', index=False,
dtype={'time': TIMESTAMP(timezone=True)})
然后将它们作为日期时间插入数据库:
test=# select * from test;
time
------------------------
2015-10-10 04:22:00+02
2015-10-11 05:33:00+02
(2 rows)
这是一个非常丑陋的解决方案,但在我的设置上,它可行。
请注意,postgres会在当前时区显示日期时间。我的是欧洲/巴黎,所以这就是我查询它时得到的结果(psql):
time
------------------------
2015-10-10 02:22:00+00
2015-10-11 03:33:00+00
而不是
module LinkToExtensionHelper
def mailer_link_to(name = nil, options = nil, html_options = nil, &block)
# edit or change name, options, or html_options here like you want
link = link_to(name, options, html_options, &block)
if block_given?
yield(link)
else
link
end
end
end
答案 2 :(得分:0)
这适用于pandas 0.16.2,所以你可以简单地降级pandas以避免错误:
conda remove pandas
conda install pandas=0.16.2
在数据库中:
(1)在postgresq.conf中设置timezone ='UTC'。这使得UTC成为数据库的所有连接的默认时区
(2)对数据库中的所有时间戳列使用带时区(也称为timestamptz)的时间戳。它们将值存储为UTC,但在选择时将它们转换为您的时区设置。
IN PYTHON:
(3)始终使用UTC中的时区创建时间戳:
def get_now_in_utc():
now = datetime.now(tz=pytz.utc)
return now
(4)并将它们与pandas to_sql持续存在
<强>结果:强>
(5)这将使你的持久性成为时区意识和准确。
(6)当从DB查询(在查询中使用AT TIME ZONE表达式)或在代码中(python中的时区转换)时,您始终可以获取UTC时间并将其转换为您喜欢的任何内容。
答案 3 :(得分:0)
我发现这很适合我(甚至允许进行tz转换):
from sqlalchemy.types import TIMESTAMP as typeTIMESTAMP
df = pd.DataFrame({
'datetime': ['2000-10-29 00:00', '2000-10-29 01:00', '2000-10-29 02:00', '2000-10-29 03:00'],
'a': range(4),
})
df.datetime = [pd.Timestamp(i, tz='UTC').tz_convert(tz='Europe/London') for i in df.datetime]
df.datetime = df.datetime.astype(pd.Timestamp) # needs to re-convert to Timestamp
df.to_sql(name=TEST_TABLE_NAME, con=conn, index=False, dtype={'datetime': typeTIMESTAMP(timezone=True)})
# if you want to set it as primary key
conn.execute("""ALTER TABLE "{}" ADD PRIMARY KEY (datetime);""".format(TABLE_NAME))