如何处理Django中MySQL的“部分”日期(2010-00-00)?


问题内容

在我的一个使用MySQL作为数据库的Django项目中,我需要有一个 日期
字段,该字段还必须接受“部分”日期,例如仅年份(YYYY)和年份和月份(YYYY-MM)以及正常日期(YYYY-MM- DD)。

MySQL中的 date 字段可以通过接受 00 作为月份和 日期 来处理 日期 字段。因此, 2010-00-00
在MySQL中有效,它表示2010。对于 2010-05-00 ,表示2010年5月也是如此。

因此,我开始创建一个PartialDateField支持此功能的工具。但是我碰壁了,因为默认情况下,Django使用默认值MySQLdb(MySQL的python驱动程序)MySQLdb返回
日期 字段的datetime.date对象,并且仅支持真实日期。因此,可以修改MySQLdb使用的 date 字段的转换器,并仅返回格式为
‘YYYY-MM-DD’ 的字符串。不幸的是,MySQLdb使用的转换器是在连接级别设置的,因此它用于所有MySQL 日期
字段。但是Django依靠数据库返回对象这一事实,因此,如果我将转换器更改为返回字符串,那么Django根本就不高兴。
datetime.date() DateField``datetime.date

有人有解决此问题的想法或建议吗?如何PartialDateField在Django中创建一个?

编辑

我还应该补充一点,我已经想到了2个解决方案,分别为年,月和日创建3个整数字段(如 Alison R.所述 ),或使用 varchar 字段以
YYYY-MM-DD 格式将日期保留为字符串。

但是在这两种解决方案中,如果我都没错,我都会松散 日期 字段的 特殊 属性,就像对它们进行此类查询一样: 获取此date之后的所有条目
。我可能可以在客户端上重新实现此功能,但是对于我来说这不是一个有效的解决方案,因为可以从其他系统(mysql客户端,MS Access等)查询该数据库。



问题答案:

首先,感谢您的所有回答。就目前而言,它们都不是解决我的问题的好方法,但是,为了您的辩护,我应该补充一点,我没有给出所有要求。但是每个人都可以帮助我思考问题,您的一些想法是我最终解决方案的一部分。

因此,在数据库方面,我的最终解决方案是使用 varchar 字段(限制为10个字符),并将日期作为字符串以ISO格式(YYYY-MM-
DD)的形式存储在字符串中,其中月份和日期为 00 没有月份和/或日期(例如MySQL中的 日期
字段)时。这样,该字段可以与任何数据库一起使用,并且人类可以使用简单的客户端(例如mysql客户端,phpmyadmin等)直接轻松地读取,理解和编辑数据。那是一个要求。也可以将其导出到Excel
/ CSV,而无需进行任何转换等。缺点是格式不强制(在Django中除外)。有人可能会写 “不是日期”
或格式有误,数据库就会接受(如果您对此问题有想法…)。

这样,还可以相对轻松地执行 日期 字段的所有 特殊 查询。对于带有WHERE的查询:<,>,<=,>
=和=直接起作用。IN和BETWEEN查询也直接起作用。要按天或月查询,只需使用EXTRACT(DAY | MONTH
…)。订购工作也直接进行。因此,我认为它可以满足所有查询需求,并且几乎没有复杂性。 __

在Django方面,我做了两件事。首先,我创建了一个PartialDate看起来像datetime.date但支持日期但没有月份和/或日期的对象。在此对象内,我使用datetime.datetime对象保留日期。我使用小时和分钟作为标记,以指示将月和日设置为1时是否有效
。steveha 提出的想法 与之
相同,但实现方式不同(且仅在客户端)。使用datetime.datetime对象给我很多处理日期的好功能(验证,比较等)。

其次,我创建了一个PartialDateField主要处理PartialDate对象和数据库之间转换的对象。

到目前为止,它运行良好(我已经完成了广泛的单元测试)。