我该如何阻止Python在时间为00:00:00时将mySQL DATETIME转换为datetime.date?
我该如何阻止Python在时间为00:00:00时将mySQL DATETIME转换为datetime.date?
我从mysql数据库中读取多种数据类型。第五列在数据库中的类型为\'DATETIME\',我将其用作\'BloodTraitRecord\'对象的entry_date。
import mysql.connector from datetime import timedelta from datetime import datetime show_DB = """select RUID, test_sname, test_value, units, ref_range, entry_date from %s where RUID=%%s and test_sname=%%s order by RUID, test_sname, entry_date Limit 5;""" % (tableToUse,) cursor.execute(show_DB, (ruid, traitPair[0])) resultsForOneTrait = cursor.fetchall() for result in resultsForOneTrait: ruid = result[0] s_name = result[1].decode("UTF-8") value = result[2] units = result[3].decode("UTF-8") ref_range = result[4].decode("UTF-8") # Need assistance here entryDate = result[5] record = BloodTraitRecord(ruid, s_name, value, units, ref_range, entryDate)
BloodTraitRecord类:
class BloodTraitRecord: def __init__(self, ruid, test_sname, test_value, units, ref_range, entry_date): self.RUID = ruid self.test_sname = test_sname self.test_value = test_value self.units = units self.ref_range = ref_range self.entry_date = entry_date
从数据库中获取的DATETIME对象在mysql服务器中如下所示:
'2008-11-14 13:28:00'
代码按预期运行,除非数据库中的时间是午夜,就像这样:
'2014-05-18 00:00:00'
在这种情况下,当在代码的后面将记录的entry_date.date()与另一个datetime.date进行比较时,就会出现以下错误:
# 'cancerCutoff' is consistently a datetime.date cancerCutoff = firstCancerAnemiaCodeDate[ruidkey] - timedelta(days=180) if cancerCutoff < record.entry_date.date(): AttributeError: 'datetime.date' object has no attribute 'date'
打印record.entry_date可以确认对于这种情况,时间属性已经消失了:
'2014-05-18'
我有一种方法可以通过检查对象的类型来修复它,只有当对象是datetime时才调用date属性,但我想知道是否有比这更好的修复方法。
我也不明白为什么python在MySQL DATETIME时间为00:00:00时立即将其转换为datetime.date。
谢谢您的帮助!
我最近遇到了类似的问题。
我通过执行 db_cursor = db_con.cursor(raw=True)
解决了这个问题,
根据MySQL Python 连接器参考文档.
但是结果被返回为一个或多个列表,元素为 bytearray(b'data')
,
因此要将数据转换为可用的友好格式,我必须:
db_cursor.execute(some_sql)
query_result = db_cursor.fetchall()
...
for data_row in query_result: tempList = [x.decode('utf-8') if x != None else x for x in data_row]
然后对 tempList
进行操作,但是可以保证数据库中的 datetime
数据类型按照我的预期返回,例如,我有两个带有预期值 '2020-10-30', '03:09:03', 'AM'
的列。
进一步阅读参考文档网站可以了解为什么有开关数据类型转换的选项。
我希望这可以为更可行的解决方案敞开大门。
我建议你从数据库中提取数据后尽快将其转换为datetime对象。这样你将来就不需要进行任何检查了。你可以这样写:
entryDate = ensure_datetime(result[5])
这只是稍微多写了一些代码,但它也有一个好处,即如果你的查询变化了,而你没有正确更新代码,它将立即捕捉到类型错误。下面是一个示例实现:
from datetime import datetime, date # Thanks to http://stackoverflow.com/a/1937636/2482744 def date_to_datetime(d): return datetime.combine(d, datetime.min.time()) def ensure_datetime(d): if isinstance(d, datetime): return d elif isinstance(d, date): return date_to_datetime(d) else: raise TypeError('%s is neither a date nor a datetime' % d)
演示:
for x in [date(2016, 5, 12), datetime(2016, 5, 12, 9, 32, 57, 345), 'a string']: print(ensure_datetime(x))
输出:
2016-05-12 00:00:00 2016-05-12 09:32:57.000345 Traceback (most recent call last): File "/Users/alexhall/Dropbox/python/sandbox/sandbox.py", line 14, inprint(ensure_datetime(x)) File "/Users/alexhall/Dropbox/python/sandbox/sandbox.py", line 9, in ensure_datetime raise TypeError('%s is neither a date nor a datetime' % d) TypeError: a string is neither a date nor a datetime
但我想你不希望这样做,所以我会给你提供一个更方便的方法:
def clean_types(row): new_row = [] for item in row: if isinstance(item, date) and not isinstance(item, datetime): item = date_to_datetime(item) elif isinstance(item, str): item = item.decode("UTF-8") new_row.append(item) return new_row # Demo print(clean_types([3, 'abc', u'def', date.today(), datetime.now()])) # [3, u'abc', u'def', datetime.datetime(2016, 5, 12, 0, 0), datetime.datetime(2016, 5, 12, 17, 22, 7, 519604)]
现在,你的代码可以简化为:
for result in resultsForOneTrait: record = BloodTraitRecord(*clean_types(result))
这样你就不必记得要做任何事情了。