我试图用python +sqlite3取代我对SAS的使用;我试图将数据从SAS数据集中移到SQLite数据库。我有许多在python中正确表示为datetime.time对象的时间域。由于SQLite是“轻描淡写的”,我正在寻找关于在列中存储时间的格式的建议。(我知道我必须编写python适配器等,才能将对象读写到列中。)以下是我需要考虑的特性:
有人满意地解决了这个问题吗?
发布于 2014-12-24 18:53:05
有一个通用的方法可以将任何可序列化的Python对象存储在sqlite表中。
sqlite3.register_adapter
注册一个函数,用于将Python对象转换为int、long、float、str (UTF-8编码)、unicode或缓冲区。sqlite3.register_converter
注册用于将文本转换为Python对象的函数。输入总是文本,因为在内部,sqlite将所有内容存储为文本。下面是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
。它更简单,但将数据存储为int
更快,内存效率更高。
发布于 2014-12-24 19:18:55
我非常喜欢回答的@unutbu,但是这里有一个简单的存储时间戳的方法。
RFC 3339是一种非常明确的时间戳格式,便于计算机解析和人类阅读。您可以将时间戳存储为字符串。
RFC 3339的一个很好的特性是:一个简单的ASCII排序也按时间顺序排序。
但是你并不需要这个规范,因为它太简单了。下面是一个例子:
2014-12-24T23:59:59.9999-08:00
这是圣诞节前的最后一秒钟,在我的时区,比UTC落后8小时(因此是-08:00
部分)。年份、月份、日期、字符串T
、小时、分钟、秒、可选小数秒、时区。
时区也可以是Z
,它指示UTC时间。但是,将时间存储在当地时区可能更方便,这样您就可以更容易地阅读它们。
https://stackoverflow.com/questions/27640857
复制相似问题