簡體   English   中英

Pandas to_sql為ValueError提供了時區感知列

[英]Pandas to_sql gives ValueError with timezone-aware column

我想使用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

你必須將它作為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)

但是不要忘記使用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))

您可以將日期時間轉換為字符串:

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]

然后將它們作為日期時間插入數據庫:

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

這是一個非常丑陋的解決方案,但在我的設置上,它的工作原理。

請注意,postgres將在您當前的時區中顯示日期時間。 我的是歐洲/巴黎,所以這是我查詢它時得到的結果(psql):

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

而不是像

          time          
------------------------
 2015-10-10 02:22:00+00
 2015-10-11 03:33:00+00

這適用於pandas 0.16.2,因此您可以簡單地降級pandas以避免錯誤:

conda remove pandas
conda install pandas=0.16.2

在DB中:

(1)在postgresq.conf中設置timezone ='UTC'。 這使得UTC成為數據庫的所有連接的默認時區

(2)對數據庫中的所有時間戳列使用帶時區(也稱為timestamptz)的時間戳。 它們將值存儲為UTC,但在選擇時將它們轉換為您的時區設置。

在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時間並將其轉換為您喜歡的任何內容。

我發現這適用於我(甚至允許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)) 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM