SQLite3中的Python日期时间

4 投票
2 回答
4459 浏览
提问于 2025-04-17 12:42

我在使用Python 2.7的sqlite3日期时间对象时遇到了一个奇怪的问题。运行这个例子:

import sqlite3
import datetime

con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
cur = con.cursor()
cur.execute("create table test(d date, ts timestamp)")

today = datetime.date.today()
now = datetime.datetime.now()

cur.execute("insert into test(d, ts) values (?, ?)", (today, now))
cur.execute("select d, ts from test")
row = cur.fetchone()
print today, "=>", row[0], type(row[0])
print now, "=>", row[1], type(row[1])

cur.execute('select current_date as "d [date]", current_timestamp as "ts [timestamp]"')
row = cur.fetchone()
print today, "=>", row[0], type(row[0])
print now, "=>", row[1], type(row[1])

我得到的输出是:

2012-02-10 => 2012-02-10 <type 'datetime.date'>
2012-02-10 08:17:10.222291 => 2012-02-10 08:17:10.222291 <type 'datetime.datetime'>
2012-02-10 => 2012-02-09 <type 'datetime.date'>
2012-02-10 08:17:10.222291 => 2012-02-09 19:17:10 <type 'datetime.datetime'>

使用PARSE_COLNAMES方法获取的日期时间似乎是错误的。为什么会这样呢?

请注意,这个例子来自于Python文档

2 个回答

0

这和detect_types这个参数没有关系。即使你不写这个参数,结果也会是一样的。(不过在这种情况下,返回的类型会是'str',而不是'date'或者'datetime'。)

2

从你展示的输出结果来看,你似乎是在新西兰的时区(UTC-12 或者在夏令时期间是 UTC-11)。问题在于 PARSE_COLNAMES 是如何使用转换器将数据转成 Python 类型的——一个是以 UTC 时间为基础,另一个是使用你本地时间的时区信息(是的,我认为这在转换器中算是个 bug)。

下面是我用来处理股票价格数据的适配器,这样可以确保数据在我知道的时区内一致转换(你可以调整它以匹配你的时区,或者添加一些代码来适应检测到的时区):

def adapt_datetime(dt):
    # Get the datetime for the POSIX epoch.
    epoch = datetime.datetime.utcfromtimestamp(0.0)
    elapsedtime = dt - epoch
    # Calculate the number of milliseconds.
    seconds = float(elapsedtime.days)*24.*60.*60. + float(elapsedtime.seconds) + float(elapsedtime.microseconds)/1000000.0
    return seconds


def convert_datetime(tf):
    # Note: strange math is used to account for daylight savings time and 
    #    times in the Eastern (US) time zone (e.g. EDT)
    tf = float(tf)
    edt_adjustment = 6 * 60. * 60.
    if time.localtime(tf).tm_isdst:
        edt_adjustment = 5 * 60. * 60.
    return datetime.datetime.fromtimestamp(tf+edt_adjustment)

sqlite3.register_adapter(datetime.datetime, adapt_datetime)
sqlite3.register_converter("datetime", convert_datetime)

你可以在 这段代码 的 GitHub 页面上看到这些内容是如何运作的。

撰写回答