There is a general recipe for storing any serializable Python object in an sqlite table.
Here is what the code look might look like for datetime.time objects:
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. 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.
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
. It is simpler, but storing the data as a int
is faster and more memory efficient.