2010-11-25 72 views
12

我有使用Python和SQLite日期存储/检索的设计问题。SQLite日期存储和转换

我知道SQLite日期列以ISO格式 (即'2010-05-25')作为文本存储日期。所以,当我显示英国的日期(例如,一个网页上)我 转换使用

datetime.datetime.strptime(mydate,'%Y-%m-%d').strftime('%d/%m/%Y') 

然而,迄今为止,当它涉及到的回写数据表,SQLite是非常 宽容,是很高兴来存储'25/06/2003'在日期字段,但是这 并不理想,因为

  • 我可以留下的在同一 列日期格式混合物,

  • SQLite的日期函数只能用于ISO格式。

所以我需要将日期字符串转换回ISO格式 提交之前,但我需要一个通用的功能,检查即将 被写入所有日期字段,并在必要时转换成ISO数据。这听起来有点乏味,但也许是不可避免的。

有更简单的解决方案吗?将日期字段更改为 10个字符的字段并将'dd/mm/yyyy'存储在整个表中会更容易吗?这样,在从表格读取或写入时不需要 转换,如果需要执行任何日期算术,我可以使用datetime()函数 。

其他开发者如何克服这个问题?任何帮助,将不胜感激。 为了记录,我在Python 3.1中使用了SQLite3。

回答

14

如果您在sqlite3.connect设置detect_types=sqlite3.PARSE_DECLTYPES, 则连接将尝试SQLite的数据类型,当你画数据从数据库转换为Python数据类型 。

这是因为一件非常好的事情它好得多与datetime对象的工作比 随机日期字符串一样,你再有 datetime.datetime.strptimedateutil.parser.parse解析。

不幸的是,使用detect_types不会接受 字符串作为DATE数据停止sqlite的,但你会得到一个错误,当您尝试 提取数据从数据库中(如果它是在比其他一些格式的插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() 

但至少该错误会提醒你一个事实,即您插入 字符串的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),) 

只要使用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)) 

所以,如果你有纪律有关将只datetime.date对象到DATE场,然后你就会绘制时没有问题后数据输出。

如果您的用户正在输入各种格式的日期数据,请查看dateutil.parser.parse。它可以帮助您将这些不同的字符串转换为datetime.datetime对象。

+0

Thanks unutbu - 看起来像日期对象是要走的路。问候。 – 2010-11-26 01:17:50

5

请注意,SQLite本身不具有本机日期/时间类型。正如@unutbu回答的那样,你可以让pysqlite/sqlite3模块尝试猜测(并且注意它确实是猜测),哪些列/值是日期/时间。 SQL表达式很容易混淆它。

SQLite确实有各种日期时间函数,并且可以使用各种字符串,unixepoch和julian格式的数字,并且可以进行转换。请参阅文档:

http://www.sqlite.org/lang_datefunc.html

您可能会发现更方便地获得的SQLite做的日期/时间的工作,你需要的,而不是导入值到Python和使用Python库来做到这一点。请注意,您可以将约束条件放在SQL表定义中,例如要求字符串值存在,具有一定的长度等。

+0

感谢Roger的回复。我将检出这些SQLite日期函数。问候。 – 2010-11-26 01:28:00