Pythonで部分的な日付をモデル化するにはどうすればよいですか?未知の年、または未知の月の日?


11

Bob was born in 2000やのような事実をキャプチャできるようにしたいですBill's birthday is May 7th

両方の例で、私たちはその人の生年月日の一部のみを知っています。1つのケースでは、年のみを知っています。他の場合、月と日は知っていますが、年はわかりません。

この情報を取得するにはどうすればよいですか?

これがどのように機能するかのいくつかの例:

フィールドでNoneが未知を表すことを許可したdatetimeのようなライブラリを想像してください。次のようなコードがあります。

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あなたの提案は使えません。ボブが2000年1月1日に生まれたことがわかれば、これが正確に何を意味するのかわかりません。彼が2000年の初日に生まれたのか、それとも2000年のどの日に生まれたのかはわかりません。違いを知る必要があります。
Buttons840

@RobertHarvey私はそれが一般的であることを知っていますが、そのような信号値の悪い選択のために多くの悪い失敗を見てきました。(プラスは、私はOPだけに対処する必要があるとして、それは質問に答えるとは思わない、いくつかの日付が不明であること、そのようなケースでは1月1日に設定あなたは、未知数から実際の1月1日の日付を区別することはできません。。
ゴートロボット

5
@ Buttons840:次に、必要な動作をカプセル化するクラスを作成する必要があります。既存の日付クラスをラップして、目的の動作を追加する必要があります。
ロバートハーヴェイ

回答:


3

まず、日付を構成要素に分解し始めると、日付ではなくなります。

OOPを壊さずにサブクラスを介して機能を削除することができないのと同じように、混乱を引き起こさずに(またはさらに悪いことに)日付と日付の端数を混在させることはできません。

1年をキャプチャする場合、単純な整数を含むオブジェクトの何が問題になっていますか?月と日をキャプチャする場合、月の列挙と整数の日をキャプチャしてみませんか?たぶん、それらを日付オブジェクトに内部的に保存して、適切な境界チェックを取得することもできます(2月31日は意味がありません)。ただし、別のインターフェイスを公開します。

日付を1年と比較して、それらが同じであるか、大きいか、小さいかを確認するのはなぜですか 意味がありません。その比較を行うのに十分な情報がありません。ただし、意味のある他の比較があります(これは擬似コードです)。

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

2

Robert Harveyの2番目のコメントには正しい答えが含まれていますが、少し詳しく説明します。

人の生年と生年月日は完全に異なるエンティティであるため、両方に同じメカニズムを使用する必要はありません(実際には使用すべきではありません)。

生年月日については、慣例により2000年のように、一定の年のa のみを含むBirthDateデータ型(または、おそらくYearlyRecurringDate今のところ適切な名前を思い付くことができませんが)を考案できますdate。2000年は飛躍したため良い選択です。したがって、誕生日が2月28日である人が失敗することはありません。

誕生年の間、あなたが考案することができるBirthYearデータ型(あるいはApproximateDateデータタイプ)が含まれていますdate、と精度の指標を:YearMonthFull

これらのアプローチの利点は、今でも維持してdateいることの中心にあるので、日付の算術演算を実行できることです。


1

あなたが説明しdatetimeているのは、datetime.datetime属性(年、月など)を(単なる値ではなく)不確実性測定値として実装するモジュールのドロップイン置換品だと思います。

Pythonパッケージは不確実な数値を支援するために存在し(例:不確実性パッケージ)、おそらくdatetime各属性に不確実性を使用するフォークを作成するのはそれほど難しくないでしょう。私も1つを見たいですし、それを使うことさえできるかもしれません。udatetime前述の不確実性パッケージにa を含めることについて、確かに議論をすることができます。

あなたの例は次のようになります:

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

from to構造を実装する「期間」クラスを作成してみませんか。

「ボブは2000年に生まれた」->

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

その後、from to日付を括弧で囲むことにより、さまざまな検索方法を実装できます。fuzz属性は、日付の正確さを示す有用な指標を提供するため、完全に一致する場合はfuzz == 1、1か月以内の場合はfuzz == 31を指定できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.