Snowflake write_pandas 未正确插入日期

ASt*_*urt 12 python datetime pandas snowflake-cloud-data-platform

我有一个名为“df”的 pandas 数据框,它是根据 Netezza 数据库的 SQL 查询结果创建的。我正在 Jupyter 笔记本上工作。数据框有两行,其中两列(CREATEDDATE 和 STAGEDATE)包含日期时间值。当我运行 print(df) 时,结果如下所示:

                   ID ISDELETED            PARENTID         CREATEDBYID  \
0  017o000003tQRftAAG     false  a0no000000Hrv1IAAR  005o0000001w8wgAAA   
1  017o000003jl52cAAA     false  a0no000000GszDUAAZ  005o0000001w2pTAAQ   

          CREATEDDATE    FIELD OLDVALUE NEWVALUE  STAGEDATE  
0 2015-07-30 14:51:41  created     None     None 2016-06-06  
1 2015-07-16 14:48:37  created     None     None 2016-06-06
Run Code Online (Sandbox Code Playgroud)

如果我运行 print(df.dtypes),结果是这样的:

ID                     object
ISDELETED              object
PARENTID               object
CREATEDBYID            object
CREATEDDATE    datetime64[ns]
FIELD                  object
OLDVALUE               object
NEWVALUE               object
STAGEDATE      datetime64[ns]
dtype: object
Run Code Online (Sandbox Code Playgroud)

因此,据我所知,我的日期时间列的格式正确,可以使用 write_pandas() 写入 Snowflake。然而,在我这样做之后,雪花中的日期有很大不同: 在此输入图像描述

例如,2016-06-06 的 STAGEDATE 值现在为 48399-06-06。有谁知道如何解决这一问题?我正在使用 pyodbc 从 Netezza 进行拉取,并使用 df = cs.execute() 来填充数据帧。我正在导入并使用 Snowflake.connector 来连接到 Snowflake,并运行以下命令来获取 write_pandas:

from snowflake.connector.pandas_tools import write_pandas
Run Code Online (Sandbox Code Playgroud)

小智 10

我用 pday在这里编写的代码找到了解决方案。此函数会自动向日期类型 cols 添加时区(函数中的默认时区为 UTC)。

def fix_date_cols(df, tz='UTC'):
    cols = df.select_dtypes(include=['datetime64[ns]']).columns
    for col in cols:
        df[col] = df[col].dt.tz_localize(tz)
Run Code Online (Sandbox Code Playgroud)

所以我建议在将数据帧传递给 write_pandas 之前使用这个函数。

据我所知,问题是日期时间对象被误解了,因为它的定义不够明确。添加时区信息将强制将元素解释为日期时间。

但我真的建议你阅读这段精彩的对话,其中有很好的解释,它真的对我很有帮助。


Sim*_*rim 1

SELECT '2016-06-06'::timestamp as a
    ,to_timestamp_ntz(date_part('epoch_second', a),0)::date as a_s
    ,to_timestamp_ntz(date_part('epoch_millisecond', a),0)::date as a_ms
    ,to_timestamp_ntz(date_part('epoch_millisecond', a),3)::date as b_ms;
Run Code Online (Sandbox Code Playgroud)

给出

A                        A_S          A_MS         B_MS
2016-06-06 00:00:00.000  2016-06-06   48399-06-06  2016-06-06
Run Code Online (Sandbox Code Playgroud)

也就是说,您的日期转换为纪元毫秒并解析为秒给出您的日期。

所以你可以扔掉毫秒,或者改变日期的解析方式。