Làm cách nào để mô hình hóa một phần ngày trong Python? Giống như một năm chưa biết, hoặc ngày chưa biết trong tháng?


11

Tôi muốn có thể nắm bắt sự thật như Bob was born in 2000Bill's birthday is May 7th.

Trong cả hai ví dụ, chúng tôi chỉ biết một phần ngày sinh của người đó. Trong một trường hợp chúng ta chỉ biết năm; trong trường hợp khác, chúng ta biết tháng và ngày, nhưng không phải năm.

Làm thế nào để tôi nắm bắt thông tin này?

Một vài ví dụ về cách thức này có thể hoạt động:

Hãy tưởng tượng một thư viện như datetime cho phép Không có trong các trường đại diện cho ẩn số. Tôi có thể có mã như sau:

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

Đây chỉ là một ví dụ về cách nó có thể cư xử. Tôi không nhất thiết muốn hành vi chính xác này.


Nói chung, cách bạn xử lý những thứ như thế này là sử dụng, ví dụ, năm 0001 trong .NET cho những ngày không có một năm và ngày 1 tháng 1 trong nhiều năm mà không có tháng và ngày.
Robert Harvey

Tôi đã chỉnh sửa câu hỏi của bạn để xóa yêu cầu cho một thư viện. Những câu hỏi như vậy là lạc đề trên trang web này.

@RobertHarvey Tôi không thể sử dụng đề xuất của bạn. Nếu chúng ta thấy Bob sinh ngày 1 tháng 1 năm 2000, chúng ta không biết chính xác điều này có nghĩa là gì. Chúng ta không thể biết anh ta được sinh ra vào ngày đầu tiên của năm 2000, hay anh ta sinh vào bất kỳ ngày nào trong năm 2000. Chúng ta cần biết sự khác biệt.
Nút840

@RobertHarvey Tôi biết điều đó là phổ biến, nhưng tôi đã thấy nhiều thất bại xấu vì lựa chọn xấu của các giá trị tín hiệu như vậy. (Thêm vào đó, tôi không nghĩ rằng nó trả lời câu hỏi như nhu cầu OP để đối phó với chỉ một số ngày là chưa biết Setting để 1 tháng 1 trong những trường hợp như vậy không cho phép bạn để phân biệt ngày 1st thực Jan từ ẩn số..
Gort Robot

5
@ Nút840: Sau đó, bạn sẽ phải viết một lớp gói gọn các hành vi bạn muốn. Bạn nên bọc lớp ngày hiện tại và thêm các hành vi mong muốn của bạn.
Robert Harvey

Câu trả lời:


3

Trước hết, một khi bạn bắt đầu phân tách ngày thành các thành phần cấu thành của chúng, chúng không còn là ngày.

Theo cùng một cách mà không thể loại bỏ chức năng thông qua các lớp con mà không phá vỡ OOP, không thể trộn lẫn các phân số ngày và ngày mà không gây nhầm lẫn (hoặc tệ hơn) làm cho chúng tương thích như trong ví dụ mã của bạn mà không phá vỡ thứ gì khác.

Nếu bạn muốn chụp một năm, có gì sai với một đối tượng chứa một số nguyên đơn giản? Nếu bạn muốn chụp một tháng và một ngày, tại sao không chụp một bảng liệt kê một tháng và một ngày nguyên? Thậm chí có thể lưu trữ chúng bên trong một đối tượng ngày để bạn có thể kiểm tra giới hạn phù hợp (ví dụ: ngày 31 tháng 2 không có ý nghĩa gì). Tuy nhiên, một giao diện khác nhau.

Tại sao bạn muốn so sánh một ngày với một năm để xem liệu chúng giống nhau, lớn hơn hoặc ít hơn? Nó không có ý nghĩa: không có đủ thông tin để thực hiện so sánh đó. Tuy nhiên, có những so sánh khác có thể có ý nghĩa (đây là mã giả):

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

2

Nhận xét thứ hai của Robert Harvey chứa câu trả lời đúng, nhưng hãy để tôi mở rộng về nó một chút.

Năm sinh của mọi người và ngày sinh của mọi người là hai thực thể hoàn toàn khác nhau, vì vậy bạn không cần (và thực tế bạn không nên) sử dụng cùng một cơ chế cho cả hai.

Đối với ngày sinh, bạn có thể tạo ra một BirthDateloại dữ liệu (hoặc có thể là YearlyRecurringDatemặc dù tôi không thể đưa ra một tên hay ngay bây giờ) mà chỉ chứa một datenăm không đổi, như năm 2000 theo quy ước. Năm 2000 là một lựa chọn tốt vì nó là một bước nhảy vọt, vì vậy nó sẽ không làm thất bại những người có ngày sinh nhật vào ngày 28 tháng 2.

Trong nhiều năm sinh, bạn có thể nghĩ ra một BirthYearkiểu dữ liệu (hoặc có thể là một ApproximateDatekiểu dữ liệu) trong đó sẽ chứa một date, và một chỉ số về độ chính xác: Year, Month, Full.

Lợi ích của các phương pháp này là ở trung tâm của những thứ bạn vẫn duy trì dateđể bạn vẫn có thể thực hiện số học ngày.


1

Tôi tin rằng những gì bạn đang mô tả sẽ là sự thay thế thả xuống cho datetimemô-đun thực hiện các datetime.datetimethuộc tính (năm, tháng, v.v.) dưới dạng các giá trị với phép đo không chắc chắn (thay vì chỉ là các giá trị).

Các gói Python tồn tại để giúp với các số không chắc chắn (ví dụ: gói không chắc chắn ) và có lẽ sẽ không quá khó để tạo ra một ngã ba datetimesử dụng độ không chắc chắn trên mỗi thuộc tính. Tôi cũng muốn thấy một và thậm chí có thể sử dụng nó. Một cuộc tranh luận chắc chắn có thể được đưa ra để đưa vào một udatetimegói không chắc chắn liên quan đến afor.

Ví dụ của bạn sẽ là một cái gì đó như:

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

"Giá trị tín hiệu" có rất nhiều vấn đề, nhưng ngoài ra, bạn có thể đại diện cho những điều không chắc chắn rằng giá trị tín hiệu không thể:

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

Một xem xét khác là để chính xác hơn, sự không chắc chắn ở đây nên thực sự là loại timedelta. Tôi để nó như một bài tập cho người đọc để tìm ra một nhà xây dựng súc tích và đầy đủ cho udatetimeviệc sử dụng các yếu tố timedeltakhông chắc chắn.

Vì vậy, cuối cùng tôi sẽ nói rằng những gì bạn mô tả là "dễ dàng" được mô hình hóa với sự không chắc chắn, nhưng thực hiện một udatetimethực tế là khá khó khăn. Hầu hết sẽ đi theo con đường "dễ dàng" và chia thời gian thành các thành phần và theo dõi sự không chắc chắn trên chúng một cách độc lập, nhưng nếu bạn cảm thấy tham vọng thì uncertaintiesgói (hoặc cái khác) có thể quan tâm đến yêu cầu kéo udatetime.


0

Tại sao không tạo một lớp "thời gian" thực hiện một từ đến cấu trúc.

"Bob sinh năm 2000" ->

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

Sau đó, bạn có thể thực hiện các phương pháp tìm kiếm khác nhau bằng cách đặt dấu ngoặc từ ngày đến ngày. Thuộc tính fuzz cung cấp một dấu hiệu hữu ích về mức độ chính xác của ngày để bạn có thể chỉ định fuzz == 1 cho các kết quả khớp chính xác hoặc fuzz == 31 trong vòng một tháng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.