Python'da kısmi tarihleri ​​nasıl modelleyebilirim? Bilinmeyen bir yıl mı yoksa ayın bilinmeyen günü gibi mi?


11

Ben gibi gerçekleri yakalamak isterler Bob was born in 2000ve Bill's birthday is May 7th.

Her iki örnekte de kişinin doğum tarihinin sadece bir kısmını biliyoruz. Bir durumda sadece yılı biliyoruz; diğer durumda ayı ve günü biliyoruz, yılı değil.

Bu bilgileri nasıl yakalarım?

Bunun nasıl çalışabileceğine dair birkaç örnek:

Alanlarda Hiçbirinin bilinmeyenleri temsil etmesine izin veren datetime gibi bir kütüphane düşünün. Aşağıdaki gibi bir kod olabilir:

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

Bu sadece nasıl davranabileceğinin bir örneğidir. Bu kesin davranışı mutlaka istemiyorum.


Genel olarak, bunun gibi şeylerle başa çıkma şekliniz, örneğin, bir yıl olmayan tarihler için .NET'te 0001 yılını ve bir ay ve gün olmadan yıllarca 1 Ocak'ı kullanmaktır.
Robert Harvey

Bir kütüphane isteğini kaldırmak için sorunuzu düzenledim. Bu tür sorular bu sitede konu dışıdır.

@RobertHarvey Önerinizi kullanamıyorum. Bob'un 1 Ocak 2000'de doğduğunu görürsek, bunun tam olarak ne anlama geldiğini bilmiyoruz. 2000'in ilk gününde doğup doğmadığını veya 2000'in herhangi bir gününde doğup doğmadığını söyleyemeyiz. Farkı bilmemiz gerekir.
Buttons840

@RobertHarvey Bunun yaygın olduğunu biliyorum, ancak bu sinyal değerlerinin kötü seçimleri nedeniyle birçok kötü hata gördüm. (Ayrıca, OP'nin sadece bazı tarihlerin bilinmemesi ile ilgilenmesi gerektiği için soruyu cevapladığını sanmıyorum. Bu gibi durumlarda 1 Ocak'a ayarlamak, gerçek 1 Ocak tarihlerini bilinmeyenlerden ayırmanıza izin vermez.
Robot Gort

5
@ Buttons840: O zaman istediğiniz davranışları kapsayan bir sınıf yazmanız gerekecek. Varolan tarih sınıfını sarmalı ve istediğiniz davranışları eklemelisiniz.
Robert Harvey

Yanıtlar:


3

Her şeyden önce, tarihleri ​​bileşen bileşenlerine ayırmaya başladığınızda, bunlar artık tarih değildir.

OOP'yi bozmadan alt sınıflar aracılığıyla işlevselliği kaldırmak mümkün olmadığı gibi, tarih ve tarih bölümlerini karışıklığa neden olmadan (veya daha kötüsü) kod örneğinizde olduğu gibi başka bir şey kırmadan uyumlu hale getirmeden karıştırmak mümkün değildir.

Bir yılı yakalamak istiyorsanız, basit bir tamsayı içeren bir nesnede sorun nedir? Bir ay ve gün yakalamak istiyorsanız, neden bir aylık numaralandırma ve tamsayı bir gün yakalamıyorsunuz? Belki de bunları bir tarih nesnesinde dahili olarak saklayın, böylece uygun sınır kontrolü elde edersiniz (örneğin 31 Şubat mantıklı değil). Ancak farklı bir arayüz ortaya çıkarın.

Aynı, daha büyük veya daha küçük olup olmadığını görmek için bir tarihi neden bir yıl ile karşılaştırmak istesiniz? Bu bir anlam ifade etmiyor: bu karşılaştırmayı yapmak için yeterli bilgi yok. Bununla birlikte, mantıklı olabilecek başka karşılaştırmalar da vardır (bu sahte koddur):

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

2

Robert Harvey'nin ikinci yorumu doğru cevabı içeriyor, ama biraz daha genişletmeme izin verin.

İnsanların doğum yılı ve insanların doğum tarihleri ​​tamamen farklı varlıklardır, bu nedenle her ikisi için de aynı mekanizmayı kullanmanız gerekmez (ve aslında kullanmamalısınız).

Doğum günleri için, kongre ile 2000 gibi sadece sabit bir yıl içeren bir BirthDateveri türü (ya da muhtemelen YearlyRecurringDateşu anda iyi bir isim bulamıyorum) tasarlayabilirsiniz date. 2000 yılı iyi bir seçim çünkü sıçrama oldu, bu yüzden doğum günü 28 Şubat'ta olan insanlar başarısız olmayacak.

Doğum yıl, bir Tasarlayabileceğiniz BirthYearveri türü (ya da muhtemelen bir ApproximateDateveri türü) bir içerecektir dateve hassas bir gösterge: Year, Month, Full.

Bu yaklaşımların yararı, hâlâ sürdürdüğünüz şeylerin merkezinde datetarih aritmetiği yapabilmenizdir.


1

Açıkladığınız şeyin datetime, datetime.datetimenitelikleri (yıl, ay, vb.) Belirsizlik ölçümüne (sadece değerlerden ziyade) sahip değerler olarak uygulayan modül için bir yedek değiştirme olacağına inanıyorum .

Belirsiz sayılara yardımcı olmak için Python paketleri mevcuttur (örneğin: belirsizlik paketi) ve belki de datetimeher özellik üzerinde belirsizlik kullanan bir çatal yapmak çok zor olmaz . Ben de bir tane görmek istiyorum ve hatta bunun için kullanabilirsiniz. udatetimeÖnceden bağlantılı belirsizlikler paketine a'nın dahil edilmesi için kesinlikle bir tartışma yapılabilir .

Örnekleriniz şuna benzer:

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??:??:??

"Sinyal değerleri" nin birçok sorunu vardır, ancak buna ek olarak sinyal değerlerinin yapamayacağı belirsizliği olan şeyleri temsil edebilirsiniz:

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

Diğer bir husus, buradaki belirsizliğin daha açık olmak için aslında türünde olması gerektiğidir timedelta. Ben okuyucu için bir özlü ve tam yapıcı anlamaya yönelik bir egzersiz olarak bırakın udatetimekullanarak timedeltabelirsizlikleri.

Sonuçta açıkladığınız şeyin belirsizliklerle "kolayca" modellenmiş olduğunu söyleyebilirim, ancak a'nın uygulanması udatetimeneredeyse oldukça zordur. Çoğu "kolay" rotayı alacak ve tarih saatini bileşenlere ayıracak ve bağımsız olarak üzerlerindeki belirsizliği izleyecektir, ancak hırslı hissediyorsanız uncertaintiespaket (veya başka bir) için bir çekme isteği ile ilgilenebilir udatetime.


0

Neden bir 'den yapıya uygulayan bir "dönem" sınıfı oluşturmuyorsunuz?

"Bob 2000 yılında doğdu" ->

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

Daha sonra, tarihleri ​​arasında tarihler bastırarak çeşitli arama yöntemleri uygulayabilirsiniz. Fuzz özelliği, kesin eşleşmeler için fuzz == 1 veya bir ay içinde fuzz == 31 belirtebileceğiniz şekilde tarihin ne kadar doğru olduğuna dair yararlı bir gösterge verir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.