[英]Best way to store python datetime.time in a sqlite3 column?
I'm trying to replace my use of SAS with python + sqlite3; 我试图用python + sqlite3替换我对SAS的使用; I'm trying to move my data from SAS datasets to SQLite databases.
我正在尝试将数据从SAS数据集移动到SQLite数据库。 I have many time fields that are properly represented in python as datetime.time objects.
我有很多时间字段在python中正确表示为datetime.time对象。 Since SQLite is "lightly typed", I'm looking for advice about what format to use to store times in columns.
由于SQLite是“轻微键入”,我正在寻找有关用于在列中存储时间的格式的建议。 (I know I have to write python adapters etc. to read and write the objects to and from the column.) These are the features I need to consider:
(我知道我必须编写python适配器等来读取和写入列中的对象。)这些是我需要考虑的功能:
Has anyone solved this problem to their satisfaction? 有没有人解决这个问题令他们满意?
There is a general recipe for storing any serializable Python object in an sqlite table. 有一个通用的方法可以在sqlite表中存储任何可序列化的Python对象。
sqlite3.register_adapter
to register a function for converting the Python object to int, long, float, str (UTF-8 encoded), unicode or buffer. sqlite3.register_adapter
注册一个函数,用于将Python对象转换为int,long,float,str(UTF-8编码),unicode或buffer。 sqlite3.register_converter
to register a function for converting text to the Python object. sqlite3.register_converter
注册一个函数,用于将文本转换为Python对象。 The input is always text because internally, sqlite stores everything as text. Here is what the code look might look like for datetime.time objects: 以下是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),) ])
You can use inequalities in the SQL, but note that the values being compared are those returned by adapt_timeobj
, not the datetime.time
objects. 您可以在SQL中使用不等式,但请注意,要比较的值是
adapt_timeobj
返回的adapt_timeobj
, 而不是 datetime.time
对象。 Fortunately, if the adapt_timeobj
function returns integers that are orderable in the same order as the corresponding datetime.time
objects (as they do above), then inequalities in the SQL will work as desired. 幸运的是,如果
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()
Note: If you look in the edit history, you'll see a simpler alternative for adapt_timeobj
and convert_timeobj
that stores the data as a str
instead of as a int
. 注意:如果查看编辑历史记录,您将看到
adapt_timeobj
和convert_timeobj
的更简单的替代方法, adapt_timeobj
数据存储为str
而不是int
。 It is simpler, but storing the data as a int
is faster and more memory efficient. 它更简单,但将数据存储为
int
更快,内存效率更高。
I really like the answer by @unutbu but here's a simple way to store a timestamp. 我非常喜欢@unutbu的答案 ,但这是一种存储时间戳的简单方法。
RFC 3339 is a very unambiguous timestamp format, easy for computers to parse and easy for humans to read. RFC 3339是一种非常明确的时间戳格式,便于计算机解析,便于人类阅读。 You could store timestamps as strings.
您可以将时间戳存储为字符串。
One nice property of RFC 3339: a simple ASCII sort also sorts chronologically. RFC 3339的一个不错的属性:简单的ASCII排序也按时间顺序排序。
But you don't really need the spec because it is so simple. 但你真的不需要这个规范,因为它很简单。 Here's an example:
这是一个例子:
2014-12-24T23:59:59.9999-08:00
That is the last fraction of a second before Christmas day in my time zone, which is 8 hours behind UTC (thus the -08:00
part). 这是我的时区圣诞节前一秒钟的最后一小部分,比UTC晚8小时(因此
-08:00
部分)。 Year, month, date, the string T
, hour, minute, seconds, optional fractional second, timezone. 年,月,日,字符串
T
,小时,分钟,秒,可选小数秒,时区。
The timezone may also be Z
which indicates UTC time. 时区也可以是
Z
,表示UTC时间。 But it's probably more convenient to store the times in the local time zone so you can read them more easily. 但是将时间存储在本地时区可能更方便,因此您可以更轻松地阅读它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.