在sqlite3列中存储python datetime.time的最佳方法?

时间:2014-12-24 18:21:22

标签: python datetime sqlite

我正在尝试用python + sqlite3替换我对SAS的使用;我正在尝试将数据从SAS数据集移动到SQLite数据库。我有很多时间字段在python中正确表示为datetime.time对象。由于SQLite是“轻微键入”,我正在寻找有关用于在列中存储时间的格式的建议。 (我知道我必须编写python适配器等来读取和写入列中的对象。)这些是我需要考虑的功能:

  • SQLite能够处理查询中的列。 (例如,我可以选择两次之间出现的行吗?)
  • 场地的大小。 (我的表通常是数亿行。)
  • 人类可读性。 (我正在考虑将时间存储为整数:自午夜以来的微秒。但是这会让数据更加难以理解。)

有没有人满意地解决了这个问题?

2 个答案:

答案 0 :(得分:8)

在sqlite表中存储任何可序列化的Python对象的一般方法。

以下是datetime.time对象的代码外观:

import sqlite3
import datetime as DT

def adapt_timeobj(timeobj):
    return ((3600*timeobj.hour + 60*timeobj.minute + timeobj.second)*10**6 
            + timeobj.microsecond)

def convert_timeobj(val):
    val = int(val)
    hour, val = divmod(val, 3600*10**6)
    minute, val = divmod(val, 60*10**6)
    second, val = divmod(val, 10**6)
    microsecond = int(val)
    return DT.time(hour, minute, second, microsecond)


# Converts DT.time to TEXT when inserting
sqlite3.register_adapter(DT.time, adapt_timeobj)

# Converts TEXT to DT.time when selecting
sqlite3.register_converter("timeobj", convert_timeobj)

con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
cur = con.cursor()

# declare timecol to be of type timeobj
cur.execute("create table test (timecol timeobj)")

cur.executemany("insert into test (timecol) values (?)", 
                [(DT.time(1,2,3,4), ), (DT.time(5,6,7,8),) ])

您可以在SQL中使用不等式,但请注意,要比较的值是adapt_timeobj而不是 datetime.time个对象返回的值。幸运的是,如果adapt_timeobj函数返回的订阅整数与相应的datetime.time对象的订购顺序相同(如上所述),那么SQL中的不等式将按预期工作。

cur.execute("select timecol from test where timecol < ?",
            [DT.time(4,5,6)])
print(cur.fetchall())
# [(datetime.time(1, 2, 3, 4),)]

cur.execute("select timecol from test where timecol < ?",
            [DT.time(8,0,0)])
print(cur.fetchall())
# [(datetime.time(1, 2, 3, 4),), (datetime.time(5, 6, 7, 8),)]

con.commit()
cur.close()
con.close()

注意:如果您查看修改历史记录,您会看到adapt_timeobjconvert_timeobj的更简单的替代方案,它将数据存储为str而不是int {1}}。它更简单,但将数据存储为int更快,内存效率更高。

答案 1 :(得分:6)

我非常喜欢answer @unutbu,但这是一种存储时间戳的简单方法。

RFC 3339是一种非常明确的时间戳格式,便于计算机解析,便于人类阅读。您可以将时间戳存储为字符串。

RFC 3339的一个不错的属性:简单的ASCII排序也按时间顺序排序。

但是你并不真正需要这个规范,因为它非常简单。这是一个例子:

2014-12-24T23:59:59.9999-08:00

这是我的时区圣诞节前一秒的最后一小部分,比UTC晚8小时(因此-08:00部分)。年,月,日,字符串T,小时,分钟,秒,可选小数秒,时区。

时区也可以是Z,表示UTC时间。但是将时间存储在本地时区可能更方便,因此您可以更轻松地阅读它们。