如果我在T-SQL中执行CAST
,0397
将四舍五入为040
并进行适当的舍入,但pyodbc会将其截断为039
。我怎样才能轻松地像SQL Server一样进行这种舍入呢?
1> select logid, timestamputc from eventlog where logid=166944;
2> go
logid timestamputc
-------------------- --------------------------------------
166944 2017-05-30 08:59:37.6650397
1> select logid from eventlog
where cast(timestamputc as datetime2(6))='2017-05-30 08:59:37.665039';
2> go
logid
--------------------
(0 rows affected)
1> select logid from eventlog
where cast(timestamputc as datetime2(6))='2017-05-30 08:59:37.665040';
2> go
logid
--------------------
166944
使用pyodbc:
[{'logid': 166944, 'timestamputc': '2017-05-30 08:59:37.665039'}]
答案 0 :(得分:1)
正如您所发现的那样,当pyodbc将datetime2(7)
列检索为Python datetime
对象时,其默认行为是截断小数点后七位。如果您希望对datetime
对象进行舍入,因为SQL Server会将datetime2(7)
值CAST返回到datetime2(6)
,那么您可以使用output converter function。
例如,如果将输出转换器功能定义为
def handle_datetime2(dt2_value):
tup = struct.unpack("<6hI", dt2_value) # e.g., (2017, 5, 30, 8, 59, 37, 0, 665039700)
return datetime(tup[0], tup[1], tup[2],
hour=tup[3], minute=tup[4], second=tup[5],
microsecond=math.floor(tup[6] / 1000.0 + 0.5))
并像这样使用
cnxn = pyodbc.connect(conn_str, autocommit=True)
crsr = cnxn.cursor()
cnxn.add_output_converter(pyodbc.SQL_TYPE_TIMESTAMP, handle_datetime2)
dt_string = '2017-05-30 08:59:37.6650397'
dt_value = crsr.execute(f"SELECT CAST('{dt_string}' AS DATETIME2(7))").fetchval()
print(f'{dt_string}\n -> {repr(dt_value)}')
dt_string = '2017-05-30 08:59:37.6650395'
dt_value = crsr.execute(f"SELECT CAST('{dt_string}' AS DATETIME2(7))").fetchval()
print(f'{dt_string}\n -> {repr(dt_value)}')
dt_string = '2017-05-30 08:59:37.6650394'
dt_value = crsr.execute(f"SELECT CAST('{dt_string}' AS DATETIME2(7))").fetchval()
print(f'{dt_string}\n -> {repr(dt_value)}')
结果将如下所示
2017-05-30 08:59:37.6650397
-> datetime.datetime(2017, 5, 30, 8, 59, 37, 665040)
2017-05-30 08:59:37.6650395
-> datetime.datetime(2017, 5, 30, 8, 59, 37, 665040)
2017-05-30 08:59:37.6650394
-> datetime.datetime(2017, 5, 30, 8, 59, 37, 665039)