How can I stop python from converting a mySQL DATETIME to a datetime.date when the time is 00:00:00?
我正在从MySQL数据库中读取各种数据类型。第五列在数据库中的类型为"datetime"。我用它作为"血脉追踪"对象的输入日期。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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) |
血迹记录类别:
1 2 3 4 5 6 7 8 9 10 11 | 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服务器中如下所示:
1 | '2008-11-14 13:28:00' |
除非数据库中的时间是午夜,否则代码将按预期运行,如下所示:
1 | '2014-05-18 00:00:00' |
在这种情况下,仅在这种情况下,当将记录的条目_date.date()与代码后面的另一个datetime.date进行比较时,我会得到此错误:
1 2 3 4 | # '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确认此案例的时间属性已不存在:
1 | '2014-05-18' |
我有一种方法可以通过检查对象的类型来解决这个问题,并且只有当对象是日期时间时才调用日期属性,但是我想知道是否有比这更好的解决方法。
我也不明白为什么当日期时间是00:00:00时,python会立即将mysql日期时间转换为date time.date。
谢谢你的帮助!
一旦从数据库中提取了一个日期时间对象,我将确保您拥有它。那以后你就不用做任何检查了。所以你可以说:
1 | entryDate = ensure_datetime(result[5]) |
这只是一点额外的代码,而且还具有这样的优点:如果查询发生更改,并且在代码发生错误后不正确地更新代码,则会立即捕获类型错误。下面是一个示例实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) |
演示:
1 2 3 4 | for x in [date(2016, 5, 12), datetime(2016, 5, 12, 9, 32, 57, 345), 'a string']: print(ensure_datetime(x)) |
输出:
1 2 3 4 5 6 7 8 | 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, in <module> print(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 |
但我觉得你不想这样做,所以我会用下面的话来美化它:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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)] |
现在您的代码可以缩短为:
1 2 | for result in resultsForOneTrait: record = BloodTraitRecord(*clean_types(result)) |
你不必记住做任何事。