python UTC日期和sqlalchemy
Posted
技术标签:
【中文标题】python UTC日期和sqlalchemy【英文标题】:python utc dates and sqlalchemy 【发布时间】:2021-10-08 16:56:35 【问题描述】:我的目标是从 pandas 数据框中获取数据并插入 SQL 数据库。但是,我在时间和 UTC 方面遇到了一些问题。我将其分解为 3 个场景,从下面的代码中只需取消注释为每个场景标记的相关代码行。
场景 1,在 pandas 中将日期转换为日期/时间(非 UTC),然后插入到 sql 中,我收到以下错误消息:
"发生异常:ValueError Tz-aware datetime.datetime 不能 转换为 datetime64 除非 utc=True 文件 “/home/tbgiot04/OEE_forge/OEE_module/test_sql.py”,第 34 行,在 df.to_sql("test_table", engn, if_exists='replace')"
utc=True 的场景 2 我收到以下错误,导致未插入数据。
发生异常:ProgrammingError (pyodbc.ProgrammingError) ('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]一张表只能有一个时间戳列。因为表 'test_table' 已经有一个,不能添加列 'end_date'。 (2738)(SQLExecDirectW)“)[SQL:创建表test_table([索引] BIGINT NULL,employee_no BIGINT NULL,start_date TIMESTAMP NULL, end_date TIMESTAMP NULL )
](此错误的背景:http://sqlalche.me/e/13/f405)文件 “/home/tbgiot04/OEE_forge/OEE_module/test_sql.py”,第 37 行,在 df.to_sql("test_table", engn, if_exists='replace')
场景 3,我有 utc = True 行和 dt.tz_localize 行。 pandas/SQL alchemy 发送数据但时间不正确。 pandas DataFrame 和 SQL 数据显示相同,但与源代码中的代码不匹配。如何正确地将这些数据插入 SQL 数据库?
employee_no start_date end_date
0 1 2019-12-05 15:55:47 2019-12-05 15:55:47
1 2 2021-07-13 21:38:39 2021-07-13 21:38:39
.
import pandas as pd
from sqlalchemy import create_engine
AZUREUID = 'tb-test' # Azure SQL database userid
AZUREPWD = 'test' # Azure SQL database password
AZURESRV = 'tb-sql01.database.windows.net' # Azure SQL database server name (fully qualified)
AZUREDB = 'TB-test' # Azure SQL database name (if it does not exit, pandas will create it)
TABLE = 'DataTable' # Azure SQL database table name
#DRIVER = 'ODBC Driver 13 for SQL Server' # ODBC Driver
#DRIVER = 'SQL Server Native Client 11.0' # ODBC Driver
#DRIVER=/opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.0.so.1.1
connectionstring = 'mssql+pyodbc://uid:password@server:1433/database?driver=driver'.format(
uid=AZUREUID,
password=AZUREPWD,
server=AZURESRV,
database=AZUREDB,
driver=DRIVER.replace(' ', '+'))
engn = create_engine(connectionstring)
d = "employee_no" : [1,2], "start_date" : ["2019-12-05 15:55:47 +00:00","2021-07-13 22:38:39 +01:00"] , "end_date" : ["2019-12-05 15:55:47 +00:00","2021-07-13 22:38:39 +01:00"]
df = pd.DataFrame(data=d)
df["start_date"] = pd.to_datetime(df["start_date"]) # senario 1
df["end_date"] = pd.to_datetime(df["end_date"]) # senario 1
#df["start_date"] = pd.to_datetime(df["start_date"], utc=True) # senario 2 and 3
#df["end_date"] = pd.to_datetime(df["end_date"], utc=True) # senario 2 and 3
# df["start_date"] = df["start_date"].dt.tz_localize(None) # senario 3
# df["end_date"] = df["end_date"].dt.tz_localize(None) # senario 3
print(df)
df.to_sql("test_table", engn, if_exists='replace')
【问题讨论】:
SQL Server(我怀疑还有 Azure SQL)接受 properly-formatted string literals 的datetimeoffset
列。虽然通常建议在这种情况下对日期/时间值使用“正确的”日期时间对象,但最好不尝试转换字符串,特别是因为它们看起来已经采用格式T-SQL 需要的。
非常感谢您的快速回答。如果我将它们保留为对象,它们将作为 varchar 导入。在 SQL 中使用日期时间功能的最佳方式是什么。我有很多带有日期的列,我只是拿出 2 个作为示例。
在 pandas 中是否可以将 utc 时间转换为 uk 时间?
【参考方案1】:
如果我将它们保留为 [string] 对象,它们将导入为 varchar。
是的,if_exists="replace"
会发生这种情况。但是,我们可以使用dtype=
来指定所需的列类型:
df1 = pd.DataFrame([(1, "2021-07-13 22:38:39 +01:00")], columns=["id", "dto"])
df1.to_sql(
"dto_test",
engine,
index=False,
if_exists="replace",
dtype="dto": sqlalchemy.DateTime(timezone=True),
)
df2 = pd.read_sql_table("dto_test", engine)
print(df2)
"""
id dto
0 1 2021-07-13 21:38:39+00:00
"""
dto_value = df2.iloc[0, 1]
print(type(dto_value)) # <class 'pandas._libs.tslibs.timestamps.Timestamp'>
print(repr(dto_value)) # Timestamp('2021-07-13 21:38:39+0000', tz='UTC')
所以看起来 pandas 正在将 datetimeoffset 值标准化为 UTC,但至少它是一个时区感知值。
在 pandas 中是否可以将 utc 时间转换为 uk 时间?
我不确定是否要在 pandas 本身中执行此操作,但 pytz 似乎通常用于那种“本地日期/时间”转换,在这种转换中,标准/夏令时/夏令时转换会变得很奇怪所讨论的具体日期(包括时间“变化”的规则的变化,就像最近在 2007 年在美国发生的那样)。
【讨论】:
再次感谢,当我运行相同的代码时,我得到“pyodbc.DataError: ('22007', '[22007] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]转换失败从字符串转换日期和/或时间时。(241) (SQLExecDirectW)')"。我认为你的工作没有错误? 是的,这是从我的 PyCharm 代码窗口直接复制/粘贴的。 FWIW,我正在使用 pandas 1.3.1、SQLAlchemy 1.4.22、pyodbc 4.0.31、msodbcsql 17.7.2,并访问 SQL Server 2017 Express 实例。以上是关于python UTC日期和sqlalchemy的主要内容,如果未能解决你的问题,请参考以下文章
Python - 在特定时区设置日期时间(没有 UTC 转换)