rogerbinns / apsw

Another Python SQLite wrapper
https://rogerbinns.github.io/apsw/
Other
715 stars 96 forks source link

Datetimes into sqlite via APSW #517

Closed mohmad-null closed 1 month ago

mohmad-null commented 1 month ago

Great module, thanks for the work!

I'm trying to insert a datetime.datetime (apsw 3.43.0), and it's failing with:

TypeError: Bad binding argument type supplied - argument #2: type datetime.datetime

I appreciate this is intentional, however:

a) Feature request: It would be nice if it "just worked" (automagically converted to ISO8601 like sqlite3 does).

b) Documentation "bug" (or a generous definition of "bug"): This isn't spelt out in the differences list: https://rogerbinns.github.io/apsw/pysqlite.html

c) Documentation "bug": https://rogerbinns.github.io/apsw/dbapi.html - hints at it if you squint just so:

None of the date or time methods are available since SQLite 3 does not have a native date or time type. There are functions for manipulating dates and time which are stored as strings or Julian days (floating point number).

But doesn't really offer any suggestions/alternatives of how to solve this. It may be worth pointing to: https://rogerbinns.github.io/apsw/example.html#type-conversion-into-out-of-database - and even throwing in a specific example as I expect it's a fairly popular use-case (i.e. like the one in: https://github.com/rogerbinns/apsw/issues/516 )

rogerbinns commented 1 month ago

The sqlite3 module gets it wrong:

import sqlite3, datetime
con = sqlite3.connect("")
dt = datetime.datetime.now()
print(f"{dt=}")
for row in con.execute("select ?", (dt,)):
    print(f"{row=}")

Produces

dt=datetime.datetime(2024, 5, 4, 6, 40, 5, 697899)
row=('2024-05-04 06:40:05.697899',)

Note how there is no T as required by IS8601. Also note how it left out the timezone adjustment.

And I left out a line of the output:

test.py:7: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes
  for row in con.execute("select ?", (dt,)):

I will add links on how to do conversion on the places you mention. Thanks for spotting that.