如何在Python中为部分日期建模?像是未知的年份或月的未知日期?


11

我希望能够捕获诸如Bob was born in 2000和的事实Bill's birthday is May 7th

在这两个示例中,我们仅知道该人的生日的一部分。在一种情况下,我们只知道年份;在其他情况下,我们知道月份和日期,但不知道年份。

如何捕获此信息?

有关如何工作的一些示例:

想象一下像datetime这样的库,它允许字段中的None代表未知数。我可能有如下代码:

date_a = date(2000, 5, None)
date_b = date(2000, 6, None)
difference = date_b - date_a
assert difference.min.days == 1
assert difference.max.days == 60  # Or something close to 60.
assert equal(date_a, date_b) == False

date_c = date(2000, 5, None)
assert equal(date_a, date_c) == Maybe

这只是其行为方式的一个示例。我不一定想要这种精确的行为。


通常,处理这种情况的方式是,例如,使用.NET中的0001年表示没有年份的日期,使用1月1日表示没有月份和日期的年份。
罗伯特·哈维

我编辑了您的问题,以删除对图书馆的要求。这些问题不在本网站上。

@RobertHarvey我不能使用您的建议。如果我们看到鲍勃(Bob)出生于2000年1月1日,我们不知道这到底意味着什么。我们无法确定他是在2000年的第一天出生还是在2000年的任何一天出生。我们需要知道两者之间的区别。
Buttons840 2015年

@RobertHarvey我知道这很常见,但是由于选择不正确的信号值,我看到了很多严重的失败。(另外,我不认为它回答了这个问题作为OP需要只处理一些日期暂时未知在这种情况下设置为1月1日不允许你从未知区分真正的1月1日的日期。。
戈特机器人

5
@ Buttons840:然后,您必须编写一个封装所需行为的类。您应该包装现有的date类并添加所需的行为。
罗伯特·哈维

Answers:


3

首先,一旦开始将日期分解成它们的组成部分,它们就不再是日期。

与无法通过子类删除功能而不破坏OOP的方式相同,也无法混合日期和日期分数而不会引起混淆(或更糟糕的是),如代码示例中那样使它们兼容而不破坏其他内容。

如果要捕获一年,则包含简单整数的对象怎么了?如果要捕获一个月和一天,为什么不捕获一个月枚举和一个整数天?甚至可以将它们内部存储在date对象中,以便进行正确的边界检查(例如2月31日没有意义)。但是,公开一个不同的界面。

您为什么要比较日期和年份以查看它们是相同,更大还是较小?这没有任何意义:没有足够的信息进行比较。但是,还有其他比较可能有意义(这是伪代码):

Year y = Year(2015)
Date d = Date(2015, 01, 01)
assert y.contains(d) == True

2

罗伯特·哈维(Robert Harvey)的第二条评论包含了正确的答案,但让我对其进行扩展。

人们的出生年份和人们的出生日期是完全不同的实体,因此您不需要(实际上您不应该)对两者使用相同的机制。

对于生日,您可以设计一个BirthDate数据类型(或者可能是YearlyRecurringDate我现在无法提出一个体面的名称),该数据类型将仅包含date一个常量年份,例如约定为2000年。2000年是一个不错的选择,因为它是飞跃的,因此它不会使生日在2月28日的人失败。

对于出生年,你可以设计一个BirthYear数据类型(或可能的ApproximateDate数据类型),其中将包括一个date和精度的指标:YearMonthFull

这些方法的好处是,在事情的核心,您仍然维护a,date因此您仍然可以执行日期算术。


1

我相信您所描述的将是datetimedatetime.datetime属性(年,月等)实现为具有不确定性度量值(而不只是值)的模块的直接替代。

Python程序包可以帮助处理不确定的数字(例如,不确定性程序包),也许datetime对每个属性使用不确定性的派生类并不难。我也很想看到一个,甚至可能会用到它。当然可以提出一个论点,将a包含在之前udatetime关联的不确定性包中。

您的示例如下所示:

bob_bday = udatetime(2000, (6,6))  # 2000-06 +/- 6mo
>>> 2000-??-?? T??:??:??
bil_bday = udatetime((1970, 50), 3, 7)  # assume bill is ~40 +/- 40 
>>> [1970+/-40]-03-07 T??:??:??

“信号值”有很多问题,但是除此之外,您还可以不确定地表示信号值不能做到的事情:

# ali was born in spring
ali_bday = udatetime((), (4.5, 1.5))
>>> [1970+/-40]-[4.5+/-1.5]-?? T??:??:??

另一个考虑是,更确切地说,这里的不确定性实际上应该是类型timedelta。我将其作为练习让读者找出udatetime使用timedelta不确定性的简洁完整的构造方法。

因此,最终我想说的是,您所描述的内容是“容易地”用不确定性建模的,但是a的实现udatetime实际上是相当困难的。大多数人会采取“简单”的方法,将日期时间分解为各个部分,并独立跟踪它们的不确定性,但是,如果您有雄心勃勃,则该uncertainties包装(或其他包装)可能会对的拉取请求感兴趣udatetime


0

为什么不创建一个实现从到结构的“ period”类。

“鲍勃出生于2000年”->

period {
   from  {
      yy = 2000;
      mm = 01;
      dd = 01; 
   }
   to {
     yy = 2000;
     mm = 12;
     dd = 31;
   }
   fuzz = 365;
}

然后,您可以实施各种搜索方法,例如,将起始日期到日期放在方括号中。fuzz属性可以有效指示日期的准确性,因此您可以为完全匹配指定fuzz == 1,或者在一个月左右的时间内指定fuzz == 31。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.