我在使用Python和SQLite进行日期存储/检索时遇到了设计问题.
我知道SQLite日期列将日期存储为ISO格式的文本(即'2010-05-25').因此,当我显示英国日期(例如,在网页上)时,我使用转换日期
datetime.datetime.strptime(mydate,'%Y-%m-%d').strftime('%d/%m/%Y')
Run Code Online (Sandbox Code Playgroud)
然而,当谈到将数据写回到表中时,SQLite非常宽容并且非常乐意存储'25/06/2003'在日期字段中,但这并不理想,因为
我可以在同一列中留下混合的日期格式,
SQLite的日期函数仅适用于ISO格式.
因此,我需要在提交之前将日期字符串转换回ISO格式,但是我需要一个通用函数来检查要在所有日期字段中写入的数据,并在必要时转换为ISO.这对我来说听起来有点乏味,但也许这是不可避免的.
有更简单的解决方案吗?是否更容易将日期字段更改为10个字符的字段并存储'dd/mm/yyyy'在整个表中?这样在从表中读取或写入时不需要转换,如果我需要执行任何日期算术,我可以使用datetime()函数.
其他开发人员如何克服这个问题?任何帮助,将不胜感激.为了记录,我在Python 3.1中使用SQLite3.
unu*_*tbu 14
如果您设置detect_types=sqlite3.PARSE_DECLTYPES的sqlite3.connect,则连接将尝试SQLite的数据类型,当你画数据从数据库转换为Python数据类型.
这是因为一件非常好的事情它好得多比随机日期字符串一样,你再有解析datetime对象工作
datetime.datetime.strptime或dateutil.parser.parse.
不幸的是,使用detect_types不会阻止sqlite 接受
字符串作为DATE数据,但是当您尝试从数据库中绘制数据时(如果它是以YYYY-MM-DD以外的某种格式插入),您将收到错误,因为连接将无法将其转换为datetime.date对象:
conn=sqlite3.connect(':memory:',detect_types=sqlite3.PARSE_DECLTYPES)
cur=conn.cursor()
cur.execute('CREATE TABLE foo(bar DATE)')
# Unfortunately, this is still accepted by sqlite
cur.execute("INSERT INTO foo(bar) VALUES (?)",('25/06/2003',))
# But you won't be able to draw the data out later because parsing will fail
try:
cur.execute("SELECT * FROM foo")
except ValueError as err:
print(err)
# invalid literal for int() with base 10: '25/06/2003'
conn.rollback()
Run Code Online (Sandbox Code Playgroud)
但至少错误会提醒您,当您真正应该插入datetime.date对象时,您已为DATE插入了一个字符串:
cur.execute("INSERT INTO foo(bar) VALUES (?)",(datetime.date(2003,6,25),))
cur.execute("SELECT ALL * FROM foo")
data=cur.fetchall()
data=zip(*data)[0]
print(data)
# (datetime.date(2003, 6, 25),)
Run Code Online (Sandbox Code Playgroud)
只要使用YYYY-MM-DD格式,您也可以将字符串作为DATE数据插入.请注意,虽然您插入了一个字符串,但它会以datetime.date对象的形式返回:
cur.execute("INSERT INTO foo(bar) VALUES (?)",('2003-06-25',))
cur.execute("SELECT ALL * FROM foo")
data=cur.fetchall()
data=zip(*data)[0]
print(data)
# (datetime.date(2003, 6, 25), datetime.date(2003, 6, 25))
Run Code Online (Sandbox Code Playgroud)
因此,如果您对仅在datetime.date对象中插入对象进行训练DATE,那么在以后绘制数据时您将没有任何问题.
如果您的用户以各种格式输入日期数据,请查看dateutil.parser.parse.它可能能够帮助您将各种字符串转换为datetime.datetime对象.
请注意,SQLite本身没有本机日期/时间类型.正如@unutbu回答的那样,你可以让pysqlite/sqlite3模块尝试猜测(并注意它确实是猜测)哪些列/值是日期/时间.SQL表达式很容易混淆它.
SQLite确实有各种日期时间函数,可以使用各种字符串,unixepoch和julian格式的数字,并且可以进行转换.查看文档:
http://www.sqlite.org/lang_datefunc.html
您可能会发现让SQLite更方便地完成您需要的日期/时间工作,而不是将值导入Python并使用Python库来完成.请注意,您可以在SQL表定义中放置约束,例如要求存在字符串值,具有一定长度等.
| 归档时间: |
|
| 查看次数: |
20233 次 |
| 最近记录: |