undate


Nameundate JSON
Version 0.3.0 PyPI version JSON
download
home_pageNone
Summarylibrary for working with uncertain, fuzzy, or partially unknown dates and date intervals
upload_time2024-11-18 22:33:12
maintainerNone
docs_urlNone
authorRebecca Sutton Koeser, Cole Crawford, Julia Damerow, Robert Casties, Malte Vogl
requires_python>=3.9
licenseApache-2
keywords dates dating digital-humanities partially-known uncertain-dates uncertainty unknown
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # undate overview

![undate](_static/undate_logo.png)

**undate** is a python library for working with uncertain or partially known dates.

> [!WARNING]
> This is pre-alpha software and is **NOT** feature complete! Use with caution.
> Currently it only supports parsing and formatting dates in ISO8601 format and
> some portions of EDTF (Extended Date Time Format).

*Undate was initially created as part of a [DH-Tech](https://dh-tech.github.io/) hackathon in November 2022.*

---

[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11068867.svg)](https://doi.org/10.5281/zenodo.11068867)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Documentation Status](https://readthedocs.org/projects/undate-python/badge/?version=latest)](https://undate-python.readthedocs.io/en/latest/?badge=latest)
[![unit tests](https://github.com/dh-tech/undate-python/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/dh-tech/undate-python/actions/workflows/unit_tests.yml)
[![codecov](https://codecov.io/gh/dh-tech/undate-python/branch/main/graph/badge.svg?token=GE7HZE8C9D)](https://codecov.io/gh/dh-tech/undate-python)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](CONTRIBUTORS.md)
<!-- ALL-CONTRIBUTORS-BADGE:END -->

Read [Contributors](CONTRIBUTORS.md) for detailed contribution information.

## Example Usage

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 undate.undate import Undate

november7 = Undate(2000, 11, 7)
november = Undate(2000, 11)
year2k = Undate(2000)
november7_some_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")
```

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)
>>> november2000 = Undate(2000, 11)
>>> year2k = Undate(2000)
>>> ad100 = Undate(100)
>>> november7 in november
True
>>> november2000 in year2k
True
>>> november7 in year2k
True
>>> november2000 in ad100
False
>>> november7 in ad100
False
```

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)
>>> november_2001 = Undate(2001, 11)
>>> year2k = Undate(2000)
>>> ad100 = Undate(100)
>>> sorted([november7_2020, november_2001, year2k, ad100])
[<Undate 0100>, <Undate 2000>, <Undate 2001-11>, <Undate 2020-11-07>]
>>> 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`.

```python
>>> november_2020 = Undate(2020, 11)
>>> november7_2020 > november_2020
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  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 1900/2000>
>>> UndateInterval(Undate(1900), Undate(2000), label="19th century")
>>> UndateInterval(Undate(1900), Undate(2000), label="19th century").duration().days
36890
<UndateInterval '19th century' (1900/2000)>
>>> UndateInterval(Undate(1900), Undate(2000), label="20th century")
<UndateInterval '20th century' (1900/2000)>
>>> UndateInterval(latest=Undate(2000))  # before 2000
<UndateInterval ../2000>
>>> UndateInterval(Undate(1900))  # after 1900
<UndateInterval 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 converter, and you can also output an `Undate` object in those formats.
Available converters are "ISO8601" and "EDTF" (but only)

```python
>>> from undate import Undate
>>> Undate.parse("2002", "ISO8601")
<Undate 2002>
>>> Undate.parse("2002-05", "EDTF")
<Undate 2002-05>
>>> Undate.parse("--05-03", "ISO8601")
<Undate --05-03>
>>> Undate.parse("--05-03", "ISO8601").format("EDTF")
'XXXX-05-03'
>>> Undate.parse("1800/1900")
<UndateInterval 1800/1900>
```

For more examples, refer to the [example notebooks](https://github.com/dh-tech/undate-python/tree/main/examples/notebooks/) included in this repository.

## Documentation

Project documentation is [available on ReadTheDocs](https://undate-python.readthedocs.io/en/latest/).

For instructions on setting up for local development, see [Developer Notes](DEVELOPER_NOTES.md).

## License

This software is licensed under the [Apache 2.0 License](LICENSE.md).

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "undate",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "dates, dating, digital-humanities, partially-known, uncertain-dates, uncertainty, unknown",
    "author": "Rebecca Sutton Koeser, Cole Crawford, Julia Damerow, Robert Casties, Malte Vogl",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/ea/a2/0b89c80acff3ca21a7ba3fba00bee7b16bd33b9ff0cc6cbf2858d8286c35/undate-0.3.0.tar.gz",
    "platform": null,
    "description": "# undate overview\n\n![undate](_static/undate_logo.png)\n\n**undate** is a python library for working with uncertain or partially known dates.\n\n> [!WARNING]\n> This is pre-alpha software and is **NOT** feature complete! Use with caution.\n> Currently it only supports parsing and formatting dates in ISO8601 format and\n> some portions of EDTF (Extended Date Time Format).\n\n*Undate was initially created as part of a [DH-Tech](https://dh-tech.github.io/) hackathon in November 2022.*\n\n---\n\n[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11068867.svg)](https://doi.org/10.5281/zenodo.11068867)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Documentation Status](https://readthedocs.org/projects/undate-python/badge/?version=latest)](https://undate-python.readthedocs.io/en/latest/?badge=latest)\n[![unit tests](https://github.com/dh-tech/undate-python/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/dh-tech/undate-python/actions/workflows/unit_tests.yml)\n[![codecov](https://codecov.io/gh/dh-tech/undate-python/branch/main/graph/badge.svg?token=GE7HZE8C9D)](https://codecov.io/gh/dh-tech/undate-python)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](CONTRIBUTORS.md)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\nRead [Contributors](CONTRIBUTORS.md) for detailed contribution information.\n\n## Example Usage\n\nOften 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.\n\nAn `undate.Undate` is analogous to python\u2019s 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.\n\n```python\nfrom undate.undate import Undate\n\nnovember7 = Undate(2000, 11, 7)\nnovember = Undate(2000, 11)\nyear2k = Undate(2000)\nnovember7_some_year = Undate(month=11, day=7)\n\npartially_known_year = Undate(\"19XX\")\npartially_known_month = Undate(2022, \"1X\")\n\neaster1916 = Undate(1916, 4, 23, label=\"Easter 1916\")\n```\n\nYou can convert an `Undate` to string using a date formatter (current default is ISO8601):\n```python\n>>> [str(d) for d in [november7, november, year2k, november7_some_year]]\n['2000-11-07', '2000-11', '2000', '--11-07']\n```\n\nIf enough information is known, an `Undate` object can report on its duration:\n```python\n>>> december = Undate(2000, 12)\n>>> feb_leapyear = Undate(2024, 2)\n>>> feb_regularyear = Undate(2023, 2)\n>>> for d in [november7, november, december, year2k, november7_some_year, feb_regularyear, feb_leapyear]:\n...    print(f\"{d}  - duration in days: {d.duration().days}\")\n...\n2000-11-07  - duration in days: 1\n2000-11  - duration in days: 30\n2000-12  - duration in days: 31\n2000  - duration in days: 366\n--11-07  - duration in days: 1\n2023-02  - duration in days: 28\n2024-02  - duration in days: 29\n```\n\nIf enough of the date is known and the precision supports it, you can check if one date falls within another date:\n```python\n>>> november7 = Undate(2000, 11, 7)\n>>> november2000 = Undate(2000, 11)\n>>> year2k = Undate(2000)\n>>> ad100 = Undate(100)\n>>> november7 in november\nTrue\n>>> november2000 in year2k\nTrue\n>>> november7 in year2k\nTrue\n>>> november2000 in ad100\nFalse\n>>> november7 in ad100\nFalse\n```\n\nFor 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.\n\n```python\n>>> november7_2020 = Undate(2020, 11, 7)\n>>> november_2001 = Undate(2001, 11)\n>>> year2k = Undate(2000)\n>>> ad100 = Undate(100)\n>>> sorted([november7_2020, november_2001, year2k, ad100])\n[<Undate 0100>, <Undate 2000>, <Undate 2001-11>, <Undate 2020-11-07>]\n>>> november7_2020 > november_2001\nTrue\n>>> year2k < ad100\nFalse\n>>> from datetime import date\n>>> year2k > date(2001, 1, 1)\nFalse\n```\n\nWhen dates cannot be compared due to ambiguity or precision, comparison methods raise a `NotImplementedError`.\n\n```python\n>>> november_2020 = Undate(2020, 11)\n>>> november7_2020 > november_2020\nTraceback (most recent call last):\n  File \"<stdin>\", line 1, in <module>\n  File \"/Users/rkoeser/workarea/github/undate-python/src/undate/undate.py\", line 262, in __gt__\n    return not (self < other or self == other)\n  File \"/Users/rkoeser/workarea/github/undate-python/src/undate/undate.py\", line 245, in __lt__\n    raise NotImplementedError(\nNotImplementedError: Can't compare when one date falls within the other\n```\n\nAn `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\n```python\n>>> from undate.undate import UndateInterval\n>>> UndateInterval(Undate(1900), Undate(2000))\n<UndateInterval 1900/2000>\n>>> UndateInterval(Undate(1900), Undate(2000), label=\"19th century\")\n>>> UndateInterval(Undate(1900), Undate(2000), label=\"19th century\").duration().days\n36890\n<UndateInterval '19th century' (1900/2000)>\n>>> UndateInterval(Undate(1900), Undate(2000), label=\"20th century\")\n<UndateInterval '20th century' (1900/2000)>\n>>> UndateInterval(latest=Undate(2000))  # before 2000\n<UndateInterval ../2000>\n>>> UndateInterval(Undate(1900))  # after 1900\n<UndateInterval 1900/>\n>>> UndateInterval(Undate(1900), Undate(2000), label=\"19th century\").duration().days\n36890\n>>> UndateInterval(Undate(2000, 1, 1), Undate(2000, 1,31)).duration().days\n31\n```\n\nYou can initialize `Undate` or `UndateInterval` objects by parsing a date string with a specific converter, and you can also output an `Undate` object in those formats.\nAvailable converters are \"ISO8601\" and \"EDTF\" (but only)\n\n```python\n>>> from undate import Undate\n>>> Undate.parse(\"2002\", \"ISO8601\")\n<Undate 2002>\n>>> Undate.parse(\"2002-05\", \"EDTF\")\n<Undate 2002-05>\n>>> Undate.parse(\"--05-03\", \"ISO8601\")\n<Undate --05-03>\n>>> Undate.parse(\"--05-03\", \"ISO8601\").format(\"EDTF\")\n'XXXX-05-03'\n>>> Undate.parse(\"1800/1900\")\n<UndateInterval 1800/1900>\n```\n\nFor more examples, refer to the [example notebooks](https://github.com/dh-tech/undate-python/tree/main/examples/notebooks/) included in this repository.\n\n## Documentation\n\nProject documentation is [available on ReadTheDocs](https://undate-python.readthedocs.io/en/latest/).\n\nFor instructions on setting up for local development, see [Developer Notes](DEVELOPER_NOTES.md).\n\n## License\n\nThis software is licensed under the [Apache 2.0 License](LICENSE.md).\n",
    "bugtrack_url": null,
    "license": "Apache-2",
    "summary": "library for working with uncertain, fuzzy, or partially unknown dates and date intervals",
    "version": "0.3.0",
    "project_urls": {
        "Changelog": "https://github.com/dh-tech/undate-python/blob/main/CHANGELOG.md",
        "Documentation": "https://undate-python.readthedocs.io/en/latest/",
        "Homepage": "https://github.com/dh-tech/undate-python",
        "Issues": "https://github.com/dh-tech/undate-python/issues",
        "Repository": "https://github.com/dh-tech/undate-python.git"
    },
    "split_keywords": [
        "dates",
        " dating",
        " digital-humanities",
        " partially-known",
        " uncertain-dates",
        " uncertainty",
        " unknown"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3977ff1446a50e1ffee95447ee9dfc287f6199e7cd77813f5500b332d095432a",
                "md5": "c124f0df70a4df1834c85951019d567d",
                "sha256": "5a4d26f4e24d51e37953f09e6929d3948121b63ad5e48679e25e35a503c26e2c"
            },
            "downloads": -1,
            "filename": "undate-0.3.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c124f0df70a4df1834c85951019d567d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 24494,
            "upload_time": "2024-11-18T22:33:10",
            "upload_time_iso_8601": "2024-11-18T22:33:10.525422Z",
            "url": "https://files.pythonhosted.org/packages/39/77/ff1446a50e1ffee95447ee9dfc287f6199e7cd77813f5500b332d095432a/undate-0.3.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "eaa20b89c80acff3ca21a7ba3fba00bee7b16bd33b9ff0cc6cbf2858d8286c35",
                "md5": "1ca64475588b3840297587df877caa8b",
                "sha256": "8e328c7c93f0f0f85c38e76503f27315e44908b5fa9f96239e049c1b38f67b96"
            },
            "downloads": -1,
            "filename": "undate-0.3.0.tar.gz",
            "has_sig": false,
            "md5_digest": "1ca64475588b3840297587df877caa8b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 27601,
            "upload_time": "2024-11-18T22:33:12",
            "upload_time_iso_8601": "2024-11-18T22:33:12.636321Z",
            "url": "https://files.pythonhosted.org/packages/ea/a2/0b89c80acff3ca21a7ba3fba00bee7b16bd33b9ff0cc6cbf2858d8286c35/undate-0.3.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-18 22:33:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "dh-tech",
    "github_project": "undate-python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "undate"
}
        
Elapsed time: 0.45484s