【问题标题】:How to read datetime back from sqlite as a datetime instead of string in Python?如何从sqlite中读取日期时间作为日期时间而不是Python中的字符串?
【发布时间】:2010-12-22 05:45:55
【问题描述】:

我正在使用 Python 2.6.4 中的 sqlite3 模块将日期时间存储在 SQLite 数据库中。插入它非常容易,因为 sqlite 会自动将日期转换为字符串。问题是,在读取它时它会以字符串形式返回,但我需要重建原始的 datetime 对象。我该怎么做?

【问题讨论】:

    标签: python datetime sqlite


    【解决方案1】:

    事实证明 sqlite3 可以做到这一点,甚至是 documented,有点 - 但很容易错过或误解。

    我要做的是:

    • 在 .connect() 调用中传递 sqlite3.PARSE_COLNAMES 选项,例如。
    conn = sqlite3.connect(dbFilePath, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
    
    • 将我想要的类型放入查询中 - 对于日期时间,它实际上不是“日期时间”,而是“时间戳”:

      sql = 'SELECT jobid, startedTime as "[timestamp]" FROM job'
      
      cursor = conn.cursor()
      try:
          cursor.execute(sql)
          return cursor.fetchall()
      finally:
          cursor.close()
      

    如果我传入“datetime”,它会被默默地忽略,我仍然会得到一个字符串。如果我省略引号也一样。

    【讨论】:

    • 请注意,它肯定是"[timestamp]"[timestamp] 被默默忽略,.fetchone 也不会转换类型。多么奇怪的图书馆。
    • 看来真正重要的是双引号字符,既不是您明确指定的别名也不是 as 关键字
    • 我现在已经提交了bugs.python.org/issue35145'sqlite3: "select *" should autoconvert datetime fields'。
    【解决方案2】:

    如果你用时间戳类型声明你的列,你就在三叶草中:

    >>> db = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
    >>> c = db.cursor()
    >>> c.execute('create table foo (bar integer, baz timestamp)')
    <sqlite3.Cursor object at 0x40fc50>
    >>> c.execute('insert into foo values(?, ?)', (23, datetime.datetime.now()))
    <sqlite3.Cursor object at 0x40fc50>
    >>> c.execute('select * from foo')
    <sqlite3.Cursor object at 0x40fc50>
    >>> c.fetchall()
    [(23, datetime.datetime(2009, 12, 1, 19, 31, 1, 40113))]
    

    看到了吗? int(对于声明为整数的列)和 datetime(对于声明为时间戳的列)都可以在类型完整的情况下进行往返。

    【讨论】:

    • 谢谢,亚历克斯,它有效!我对此感到惊讶,因为在 sqlite.org/datatype3.html 上根本没有提到 TIMESTAMP 类型
    • @Evgeny,见docs.python.org/library/…——它没有在 sqlite.org 中记录,因为它实际上是在 Python 层中实现的,而不是在 sqlite 本身中!
    • 我刚刚发现是连接函数的 detect_types=sqlite3.PARSE_DECLTYPES 参数使 fetchall 返回日期时间。如果你省略它,你将有一个 unicode 对象。
    • 对于像u'2012-01-01 18:35:24.617954-02:00'这样的时区感知值来说,这似乎失败了
    • TIMESTAMP 有效但 DATETIME 无效的原因是什么?
    【解决方案3】:

    注意:在 Python3 中,我必须将 SQL 更改为:

    SELECT jobid, startedTime as "st [timestamp]" FROM job

    (我必须明确命名该列。)

    【讨论】:

    • 正如@AdamBaxter 所说,真正重要的是双引号字符,既不是您明确指定的别名也不是as 关键字。例如,这很好用:SELECT jobid, startedTime "[timestamp]" FROM job
    猜你喜欢
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    相关资源
    最近更新 更多