我正在尝试用python + sqlite3替换我对SAS的使用;我正在尝试将数据从SAS数据集移动到SQLite数据库。我有很多时间字段在python中正确表示为datetime.time对象。由于SQLite是“轻微键入”,我正在寻找有关用于在列中存储时间的格式的建议。 (我知道我必须编写python适配器等来读取和写入列中的对象。)这些是我需要考虑的功能:
有没有人满意地解决了这个问题?
答案 0 :(得分:8)
在sqlite表中存储任何可序列化的Python对象的一般方法。
sqlite3.register_adapter
注册转换功能
Python对象为int,long,float,str(UTF-8编码),unicode或缓冲区。sqlite3.register_converter
注册函数
将文本转换为Python对象。输入始终是文本,因为internally, sqlite stores everything as text. 以下是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_timeobj
和convert_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时间。但是将时间存储在本地时区可能更方便,因此您可以更轻松地阅读它们。