如何在pyodbc输出转换器函数中解压sqlserver DATETIME?

2024-09-28 21:17:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在向pyodbc连接对象添加输出转换器,以处理从SQL Server返回的日期类型。我能够用以下内容解压datetime.time结构:

tuple   = struct.unpack("HHHI", dateObj)

效果很好。但是,我无法找出datetime.datetime对象的秘诀,根据pyodbc文档,它是一个时间戳结构,定义为here

^{pr2}$

数据库中该列的数据是2018-01-11 11:50:16.000,如果没有add_output_convert陷阱,pyodbc将返回:

TypeError: datetime.datetime(2018, 1, 11, 11, 50, 16) is not JSON serializable

看起来pyodbc悄悄地放弃了分数,这很好。unpack()格式不应该是以下格式之一:

tuple = struct.unpack("hHHHHHI", dateObj)  # with missing fraction
tuple = struct.unpack("hHHHHH", dateObj)

是吗?后者只返回:

error: unpack requires a string argument of length 12

对于记录,根据sys.getsizeofdateObj是41字节。对格式有什么建议吗?这是Windows 10 64位,以及Linux 64位。在


Tags: 对象类型sqldatetimeservertime格式结构
1条回答
网友
1楼 · 发布于 2024-09-28 21:17:04

你好像一直在寻找一些错误的线索。SQL Server ODBC驱动程序不为日期时间值返回41字节的数据,它只返回8字节。(sys.getsizeof返回值41,因为它包含与垃圾回收相关的“开销”),而且这8个字节不可能表示时间戳结构,因此它必须是其他的。在

从基本测试开始。。。在

import pyodbc


def datetime_as_string(raw_bytes):
    return raw_bytes


cnxn = pyodbc.connect('DSN=SQLmyDb;', autocommit=True)
cnxn.add_output_converter(pyodbc.SQL_TYPE_TIMESTAMP, datetime_as_string)
crsr = cnxn.cursor()

test_value = '2018-01-11 11:50:16'
rtn = crsr.execute("SELECT CAST(? AS DATETIME)", test_value).fetchval()
print(repr(rtn))

crsr.close()
cnxn.close()

。。。我看到您的测试值用'e\xa8\x00\x00\xa0\x14\xc3\x00'表示。在Windows计算器中使用hex转换器的一段时间后,我发现其中的内容并不明显。出于直觉,我尝试了test_value = '1900-01-01 00:00:00',结果返回了'\x00\x00\x00\x00\x00\x00\x00\x00',所以至少我有一个地方可以开始(sqlserver DATETIME值的“epoch”)。在

test_value = '1901-01-01 00:00:00'(纪元后1年)返回'm\x01\x00\x00\x00\x00\x00\x00''m'0x6d0x016d是365,所以这是令人鼓舞的。在

test_value = '1900-01-01 00:00:01'(epoch后1秒)返回'\x00\x00\x00\x00,\x01\x00\x00'','0x2c0x012c是300。在

test_value = '1900-01-01 00:00:02'(纪元后2秒)返回'\x00\x00\x00\x00X\x02\x00\x00''X'0x580x0258是600。在

因此,sqlserverodbc驱动程序返回两个4字节有符号整数,第一个是epoch在整天内的偏移量,第二个是以1/300秒为增量的部分日期。在

所以我把输出转换器的功能改为

^{pr2}$

这似乎起到了作用。在

相关问题 更多 >