From 22d20b20f5032bce9e0604ccec50904f0ad15642 Mon Sep 17 00:00:00 2001 From: rlskoeser Date: Thu, 6 Jun 2024 13:50:12 -0400 Subject: [PATCH 1/4] Add some example usage for undate objects to readme --- README.md | 60 ++++++++++++++++++++++++++++++++++++++++++++ src/undate/undate.py | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dff6a50..d2425e1 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,66 @@ It was initially created as part of a [DH-Tech](https://dh-tech.github.io/) hack Read [Contributors](CONTRIBUTORS.md) for detailed contribution information. +## Example Usage + +Often humanities and cultural data includes imprecise or uncertain temporal information. We want to store that information but also work with it in a structured way, not just treat it as text for display. Different projects may need to work with or convert between different date formats or even different calendars. + +An `undate.Undate` is analogous to python's builtin `datetime.date` object, but with support for varying degrees of precision and unknown information. You can initialize an undate with either strings or numbers for whichever parts of the date are known or partially known. An `Undate` can take an optional label. +```python +from undate.undate import Undate + +november7 = Undate(2000, 11, 7) +november = Undate(2000, 11) +year2k = Undate(2000) +unknown_year = Undate(month=11, day=7) + +partially_known_year = Undate("19XX") +partially_known_month = Undate(2022, "1X") + +easter1916 = Undate(1916, 4, 23, label="Easter 1916") +``` + +If enough of the date is known and the precision supports it, you can check if one date falls within another date: +```python +>>> november7 = Undate(2000, 11, 7) +>>> november = Undate(2000, 11) +>>> year2k = Undate(2000) +>>> ad100 = Undate(100) +>>> november7 in november +True +>>> november in year2k +True +>>> november7 in year2k +True +>>> november in ad100 +False +>>> november7 in ad100 +False +``` + +For dates that are imprecise are partially known, `undate` calculates earliest and latest possible dates for comparison purposes so you can sort dates and compare with greater than or less than. You can also compare with python `datetime.date` objects + +```python +>>> november7_2020 = Undate(2020, 11, 7) +>>> november_2001 = Undate(2001, 11) +>>> year2k = Undate(2000) +>>> ad100 = Undate(100) +>>> sorted([november7_2020, november_2001, year2k, ad100]) +[, , , ] +>>> november7_2020 > november_2001 +True +>>> year2k < ad100 +False +>>> from datetime import date +>>> year2k > date(2001, 1, 1) +False +``` + +When dates cannot be compared due to ambiguity or precision, comparison methods raise a `NotImplementedError`. + + + + ## Documentation Project documentation is available on ReadTheDocs https://undate-python.readthedocs.io/en/latest/ diff --git a/src/undate/undate.py b/src/undate/undate.py index ee94bb6..971ded7 100644 --- a/src/undate/undate.py +++ b/src/undate/undate.py @@ -20,7 +20,7 @@ class DatePrecision(IntEnum): of the date is known.""" # numbers should be set to allow logical greater than / less than - # comparison, e.g. year precision > month + # comparison, e.g. year precision < month #: day DAY = 1 From ed93bfd5a5fe22fe6a54a6d743a70865093b6e3c Mon Sep 17 00:00:00 2001 From: rlskoeser Date: Thu, 6 Jun 2024 14:39:47 -0400 Subject: [PATCH 2/4] Add example usage for date intervals --- README.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d2425e1..22713a3 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ from undate.undate import Undate november7 = Undate(2000, 11, 7) november = Undate(2000, 11) year2k = Undate(2000) -unknown_year = Undate(month=11, day=7) +november7_some_year = Undate(month=11, day=7) partially_known_year = Undate("19XX") partially_known_month = Undate(2022, "1X") @@ -41,25 +41,48 @@ partially_known_month = Undate(2022, "1X") easter1916 = Undate(1916, 4, 23, label="Easter 1916") ``` +You can convert an `Undate` to string using a date formatter (current default is ISO8601): +```python +>>> [str(d) for d in [november7, november, year2k, november7_some_year]] +['2000-11-07', '2000-11', '2000', '--11-07'] +``` + +If enough information is known, an `Undate` object can report on its duration: +```python +>>> december = Undate(2000, 12) +>>> feb_leapyear = Undate(2024, 2) +>>> feb_regularyear = Undate(2023, 2) +>>> for d in [november7, november, december, year2k, november7_some_year, feb_regularyear, feb_leapyear]: +... print(f"{d} - duration in days: {d.duration().days}") +... +2000-11-07 - duration in days: 1 +2000-11 - duration in days: 30 +2000-12 - duration in days: 31 +2000 - duration in days: 366 +--11-07 - duration in days: 1 +2023-02 - duration in days: 28 +2024-02 - duration in days: 29 +``` + If enough of the date is known and the precision supports it, you can check if one date falls within another date: ```python >>> november7 = Undate(2000, 11, 7) ->>> november = Undate(2000, 11) +>>> november2000 = Undate(2000, 11) >>> year2k = Undate(2000) >>> ad100 = Undate(100) >>> november7 in november True ->>> november in year2k +>>> november2000 in year2k True >>> november7 in year2k True ->>> november in ad100 +>>> november2000 in ad100 False >>> november7 in ad100 False ``` -For dates that are imprecise are partially known, `undate` calculates earliest and latest possible dates for comparison purposes so you can sort dates and compare with greater than or less than. You can also compare with python `datetime.date` objects +For dates that are imprecise are partially known, `undate` calculates earliest and latest possible dates for comparison purposes so you can sort dates and compare with equals, greater than, and less than. You can also compare with python `datetime.date` objects. ```python >>> november7_2020 = Undate(2020, 11, 7) @@ -79,8 +102,54 @@ False When dates cannot be compared due to ambiguity or precision, comparison methods raise a `NotImplementedError`. +```python +>>> november_2020 = Undate(2020, 11) +>>> november7_2020 > november_2020 +Traceback (most recent call last): + File "", line 1, in + File "/Users/rkoeser/workarea/github/undate-python/src/undate/undate.py", line 262, in __gt__ + return not (self < other or self == other) + File "/Users/rkoeser/workarea/github/undate-python/src/undate/undate.py", line 245, in __lt__ + raise NotImplementedError( +NotImplementedError: Can't compare when one date falls within the other +``` +An `UndateInterval` is a date range between two `Undate` objects. Intervals can be open-ended, allow for optional labels, and can calculate duration if enough information is known +```python +>>> from undate.undate import UndateInterval +>>> UndateInterval(Undate(1900), Undate(2000)) + +>>> UndateInterval(Undate(1900), Undate(2000), label="19th century") +>>> UndateInterval(Undate(1900), Undate(2000), label="19th century").duration().days +36890 + +>>> UndateInterval(Undate(1900), Undate(2000), label="20th century") + +>>> UndateInterval(latest=Undate(2000)) # before 2000 + +>>> UndateInterval(Undate(1900)) # after 1900 + +>>> UndateInterval(Undate(1900), Undate(2000), label="19th century").duration().days +36890 +>>> UndateInterval(Undate(2000, 1, 1), Undate(2000, 1,31)).duration().days +31 +``` +You can initialize `Undate` or `UndateInterval` objects by parsing a date string with a specific formatter. +```python +>>> from undate.dateformat.iso8601 import ISO8601DateFormat +>>> isoformatter = ISO8601DateFormat() +>>> isoformatter.parse("2002") + +>>> isoformatter.parse("2002-05") + +>>> isoformatter.parse("--05-03") + +>>> isoformatter.parse("--05-03") + +>>> isoformatter.parse("1800/1900") + +``` ## Documentation From b4d28d68ceddc177802f3418fcc88bc5388340d0 Mon Sep 17 00:00:00 2001 From: Rebecca Sutton Koeser Date: Thu, 11 Jul 2024 11:33:28 -0400 Subject: [PATCH 3/4] Update README.md Co-authored-by: Julia Damerow --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22713a3..5853c05 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Read [Contributors](CONTRIBUTORS.md) for detailed contribution information. ## Example Usage -Often humanities and cultural data includes imprecise or uncertain temporal information. We want to store that information but also work with it in a structured way, not just treat it as text for display. Different projects may need to work with or convert between different date formats or even different calendars. +Often humanities and cultural data include imprecise or uncertain temporal information. We want to store that information but also work with it in a structured way, not just treat it as text for display. Different projects may need to work with or convert between different date formats or even different calendars. An `undate.Undate` is analogous to python's builtin `datetime.date` object, but with support for varying degrees of precision and unknown information. You can initialize an undate with either strings or numbers for whichever parts of the date are known or partially known. An `Undate` can take an optional label. ```python From 9614cb82d34f2b4d520c7806871445eada509412 Mon Sep 17 00:00:00 2001 From: Rebecca Sutton Koeser Date: Thu, 11 Jul 2024 11:33:38 -0400 Subject: [PATCH 4/4] Update README.md Co-authored-by: Julia Damerow --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5853c05..3a091bf 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ False False ``` -For dates that are imprecise are partially known, `undate` calculates earliest and latest possible dates for comparison purposes so you can sort dates and compare with equals, greater than, and less than. You can also compare with python `datetime.date` objects. +For dates that are imprecise or partially known, `undate` calculates earliest and latest possible dates for comparison purposes so you can sort dates and compare with equals, greater than, and less than. You can also compare with python `datetime.date` objects. ```python >>> november7_2020 = Undate(2020, 11, 7)