【问题标题】:Pyodbc not returning precise datetime dataPyodbc 不返回精确的日期时间数据
【发布时间】:2015-12-03 18:50:40
【问题描述】:

我在 Python 3.4.3 中使用 pyodbc 从 Microsoft Access 数据库 (.mdb) 中读取数据。我用来提取时间戳的查询几乎可以工作 - 我得到了正确的日期和小时/分钟/秒数据,但数据库包含精确到百分之一秒的时间。我的时间戳似乎被截断了。有谁知道我怎样才能得到被遗漏的几分之一秒?

代码

t = cursor.execute('SELECT Time FROM ConditionData')

for record in t:
    print(record)

输出:

(datetime.datetime(2013, 7, 27, 8, 24, 54), )
(datetime.datetime(2013, 7, 27, 8, 27, 48), )
(datetime.datetime(2013, 7, 27, 8, 28, 1), )
(datetime.datetime(2013, 7, 27, 8, 29, 29), )
(datetime.datetime(2013, 7, 27, 8, 32, 44), )

实际时间戳(未截断的秒数):

7/27/2013 8:24:54.27
7/27/2013 8:27:48.95
7/27/2013 8:28:01.97
7/27/2013 8:29:29.12
7/27/2013 8:32:44.40

【问题讨论】:

    标签: python sql datetime ms-access pyodbc


    【解决方案1】:

    Access 中的日期/时间列的标称分辨率为一秒,当从其内部表示(双精度)转换日期/时间值时,Access ODBC 驱动程序将丢弃小数秒。因此,例如,如果我们在 SQL Server 表的 datetime 列中有以下值

    2014-08-12 01:02:03.670
    

    我们在 Access 中对 ODBC 链接表执行以下查询

    import pyodbc
    
    connStr = (
        r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};"
        r"DBQ=C:\Users\Public\Database1.accdb;"
        )
    cnxn = pyodbc.connect(connStr)
    crsr = cnxn.cursor()
    
    sql = """\
    SELECT [Time] FROM ConditionData WHERE ID=1
    """
    crsr.execute(sql)
    row = crsr.fetchone()
    mydatetime = row[0]
    
    print(repr(mydatetime))
    print(mydatetime)
    
    crsr.close()
    cnxn.close()
    

    我们看到

    datetime.datetime(2014, 8, 12, 1, 2, 3)
    2014-08-12 01:02:03
    

    但是,如果我们调整查询并使用 CDbl() 函数返回底层 Double 值,那么我们可以将其转换为 datetime 并保留小数秒,如下所示:

    from datetime import datetime, timedelta
    import math
    import pyodbc
    
    def VT_DATE_double_to_datetime(dbl):
        # math.modf() returns (<fractional_part>, <integer_part>)
        day_parts = math.modf(dbl)
        return (
            datetime(1899, 12, 30) +
            timedelta(days=day_parts[1]) +
            timedelta(seconds=abs(day_parts[0]) * 86400)
            )
    
    
    connStr = (
        r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};"
        r"DBQ=C:\Users\Public\Database1.accdb;"
        )
    cnxn = pyodbc.connect(connStr)
    crsr = cnxn.cursor()
    
    sql = """\
    SELECT CDbl([Time]) AS ddbl FROM ConditionData WHERE ID=1
    """
    crsr.execute(sql)
    row = crsr.fetchone()
    mydatetime = VT_DATE_double_to_datetime(row[0])
    
    print(repr(mydatetime))
    print(mydatetime)
    
    crsr.close()
    cnxn.close()
    

    这给了我们

    datetime.datetime(2014, 8, 12, 1, 2, 3, 670000)
    2014-08-12 01:02:03.670000
    

    【讨论】:

    • 效果很好!非常感谢您的解决方案和对所发生情况的解释。
    猜你喜欢
    • 2017-06-23
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多