Pandas to_sql为ValueError提供了时区感知列

sec*_*ein 8 python postgresql sqlalchemy pandas

我想使用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)
Run Code Online (Sandbox Code Playgroud)

但是当我指定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)
Run Code Online (Sandbox Code Playgroud)

我有以下错误:

ValueError: Cannot cast DatetimeIndex to dtype datetime64[us]
Run Code Online (Sandbox Code Playgroud)

我使用的是python 3.4.3,postgresql 9.4,pandas 0.17.1,sqlalchemy 1.0.5

小智 7

你必须将它作为pd.Timestamp存储在PostgreSQL中.以下代码对我有用:

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)
Run Code Online (Sandbox Code Playgroud)

但是不要忘记使用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))
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,这不再适用于 pandas 1.0.3。引发类型错误 `TypeError: dtype '<class 'pandas._libs.tslibs.timestamps.Timestamp'>' 无法理解` for `df['time'] = df['time'].astype(pd.Timestamp)`。 (2认同)

Rég*_*ara 5

您可以将日期时间转换为字符串:

times = pd.DatetimeIndex(['201510100222', '201510110333'], tz="UTC")
df = pd.DataFrame()
df['time'] = [time.strftime(format="%Y-%m-%d %H:%M:%S%z") for time in times]
Run Code Online (Sandbox Code Playgroud)

然后将它们作为日期时间插入数据库中:

from sqlalchemy import TIMESTAMP
df.to_sql('test', engine, if_exists='replace', index=False,
          dtype={'time': TIMESTAMP(timezone=True)})
Run Code Online (Sandbox Code Playgroud)

这是一个相当丑陋的解决方案,但在我的设置中,它有效。

请注意,postgres 将显示您当前时区的日期时间。我的是欧洲/巴黎,所以这是我查询它们时得到的结果(psql):

test=# select * from test;
          time          
------------------------
 2015-10-10 04:22:00+02
 2015-10-11 05:33:00+02
(2 rows)
Run Code Online (Sandbox Code Playgroud)

而不是类似的东西

          time          
------------------------
 2015-10-10 02:22:00+00
 2015-10-11 03:33:00+00
Run Code Online (Sandbox Code Playgroud)