timefhuman


Nametimefhuman JSON
Version 0.1.2 PyPI version JSON
download
home_pagehttps://github.com/alvinwan/timefhuman
SummaryExtract datetimes, datetime ranges, and datetime lists from natural language text
upload_time2025-02-09 23:39:30
maintainerNone
docs_urlNone
authorAlvin Wan
requires_pythonNone
licenseApache 2.0
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # timefhuman

[![PyPi Downloads per Month](https://img.shields.io/pypi/dm/timefhuman.svg)](https://pypi.python.org/pypi/timefhuman/)
[![Coverage Status](https://coveralls.io/repos/github/alvinwan/timefhuman/badge.svg?branch=master)](https://coveralls.io/github/alvinwan/timefhuman?branch=master)

Extract datetimes, datetime ranges, and datetime lists from natural language text. Supports Python3+[^1]

[^1]: https://github.com/alvinwan/timefhuman/issues/3

----

## Getting Started

Install with pip using

```python
pip install timefhuman
```

Then, find natural language dates and times in any text.

```python
>>> from timefhuman import timefhuman

>>> timefhuman("How does 5p mon sound? Or maybe 4p tu?")
[datetime.datetime(2018, 8, 6, 17, 0), datetime.datetime(2018, 8, 7, 16, 0)]
```

The text can contain not only datetimes but also ranges of datetimes or lists of datetimes.

```python
>>> timefhuman('3p-4p')  # time range
(datetime.datetime(2018, 7, 17, 15, 0), datetime.datetime(2018, 7, 17, 16, 0))

>>> timefhuman('7/17 4PM to 7/17 5PM')  # range of datetimes
(datetime.datetime(2018, 7, 17, 16, 0), datetime.datetime(2018, 7, 17, 17, 0))

>>> timefhuman('Monday 3 pm or Tu noon')  # list of datetimes
[datetime.datetime(2018, 8, 6, 15, 0), datetime.datetime(2018, 8, 7, 12, 0)]

>>> timefhuman('7/17 4-5 or 5-6 PM')  # list of ranges of datetimes!
[(datetime.datetime(2018, 7, 17, 16, 0), datetime.datetime(2018, 7, 17, 17, 0)),
 (datetime.datetime(2018, 7, 17, 17, 0), datetime.datetime(2018, 7, 17, 18, 0))]
```

Durations are also supported.

```python
>>> timefhuman('30 minutes')  # duration
datetime.timedelta(seconds=1800)

>>> timefhuman('30-40 mins')  # range of durations
(datetime.timedelta(seconds=1800), datetime.timedelta(seconds=2400))

>>> timefhuman('30 or 40m')  # list of durations
[datetime.timedelta(seconds=1800), datetime.timedelta(seconds=2400)]
```

When possible, timefhuman will infer any missing information, using context from other datetimes.

```python
>>> timefhuman('3-4p')  # infer "PM" for "3"
(datetime.datetime(2018, 7, 17, 15, 0), datetime.datetime(2018, 7, 17, 16, 0))

>>> timefhuman('7/17 4 or 5 PM')  # infer "PM" for "4" and infer "7/17" for "5 PM"
[datetime.datetime(2018, 7, 17, 16, 0), datetime.datetime(2018, 7, 17, 17, 0)]

>>> timefhuman('7/17, 7/18, 7/19 at 9')  # infer "9a" for "7/17", "7/18"
[datetime.datetime(2018, 7, 17, 9, 0), datetime.datetime(2018, 7, 18, 9, 0),
 datetime.datetime(2018, 7, 19, 9, 0)]

>>> timefhuman('3p -4p PDT')  # infer timezone "PDT" for "3p"
(datetime.datetime(2018, 8, 4, 15, 0, tzinfo=pytz.timezone('US/Pacific')),
 datetime.datetime(2018, 8, 4, 16, 0, tzinfo=pytz.timezone('US/Pacific')))
```

You can also use natural language descriptions of dates and times.

```python
>>> timefhuman('next Monday')
datetime.datetime(2018, 8, 6, 0, 0)

>>> timefhuman('next next Monday')
datetime.datetime(2018, 8, 13, 0, 0)

>>> timefhuman('last Wednesday of December')
datetime.datetime(2018, 12, 26, 0, 0)

>>> timefhuman('afternoon')
datetime.datetime(2018, 8, 4, 15, 0)
```

See more examples in [`tests/test_e2e.py`](tests/test_e2e.py).

## Advanced Usage

For more configuration options, simply create a `tfhConfig` object.

```python
from timefhuman import tfhConfig
config = tfhConfig()
```

**Return matched text**: You can additionally grab the matched text from the input string. This is useful for modifying the input string, for example.

```python
>>> config = tfhConfig(return_matched_text=True)

>>> timefhuman('We could maybe do 3 PM, if you still have time', config=config)
[('3 PM', datetime.datetime(2018, 8, 4, 15, 0))]
```

**Change 'Now'**: You can configure the default date that timefhuman uses to fill in missing information. This would be useful if you're extracting dates from an email sent a year ago.

```python
>>> config = tfhConfig(now=datetime.datetime(2018, 8, 4, 0, 0))

>>> timefhuman('upcoming Monday noon', config=config)
datetime.datetime(2018, 8, 6, 12, 0)
```

You can also set a default timezone, by again using the config's `now`.

```python
>>> config = tfhConfig(
...     now=datetime.datetime(2018, 8, 4), tzinfo=pytz.timezone('US/Pacific'))

>>> timefhuman('Wed', config=config)
datetime.datetime(2018, 8, 8, 0, 0, tzinfo=pytz.timezone('US/Pacific'))

>>> timefhuman('Wed EST', config=config)  # EST timezone in the input takes precedence
datetime.datetime(2018, 8, 8, 0, 0, tzinfo=pytz.timezone('US/Michigan'))
```

**Use explicit information only**: Say you only want to extract *dates* OR *times*. You don't want the library to infer information. You can disable most inference by setting `infer_datetimes=False`. Instead of always returning a datetime, timefhuman will be able to return date or time objects, depending on what's provided.

```python
>>> config = tfhConfig(infer_datetimes=False)

>>> timefhuman('3 PM', config=config)
datetime.time(15, 0)

>>> timefhuman('12/18/18', config=config)
datetime.date(2018, 12, 18)
```

**Past datetimes**: By default, datetimes are assumed to occur in the future, so if "3pm" today has already passed, the returned datetime will be for *tomorrow*. However, if datetimes are assumed to have occurred in the past (e.g., from an old letter, talking about past events), you can configure the direction.

```python
>>> from timefhuman import Direction
>>> config = tfhConfig(direction=Direction.previous)

>>> timefhuman('3PM')  # the default
datetime.datetime(2018, 8, 5, 15, 0)

>>> timefhuman('3PM', config=config)  # changing direction
datetime.datetime(2018, 8, 4, 15, 0)
```

Here is the full set of supported configuration options:

```python
@dataclass
class tfhConfig:
    # Default to the next valid datetime or the previous one
    direction: Direction = Direction.next
    
    # Always return datetime objects. If no date, use now.date(). If no time, use midnight.
    infer_datetimes: bool = True
    
    # The 'current' datetime, used if infer_datetimes is True. Defaults to datetime.now().
    now: datetime | None = None
    
    # Return the matched text from the input string
    return_matched_text: bool = False
    
    # Return a single object instead of a list when there's only one match
    return_single_object: bool = True
```

## Development

Install the development version.

```shell
$ pip install .e .[test]  # for bash
$ pip install -e .\[test\]  # for zsh
```

To run tests and simultaneously generate a coverage report, use the following commands:

```shell
$ py.test --cov
$ coverage html
$ open htmlcov/index.html
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/alvinwan/timefhuman",
    "name": "timefhuman",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": null,
    "author": "Alvin Wan",
    "author_email": "hi@alvinwan.com",
    "download_url": "https://files.pythonhosted.org/packages/9a/3d/e9d9eb252a80dd47d87d829a068958221ca26cd210df6f989c4eecfcac8e/timefhuman-0.1.2.tar.gz",
    "platform": null,
    "description": "# timefhuman\n\n[![PyPi Downloads per Month](https://img.shields.io/pypi/dm/timefhuman.svg)](https://pypi.python.org/pypi/timefhuman/)\n[![Coverage Status](https://coveralls.io/repos/github/alvinwan/timefhuman/badge.svg?branch=master)](https://coveralls.io/github/alvinwan/timefhuman?branch=master)\n\nExtract datetimes, datetime ranges, and datetime lists from natural language text. Supports Python3+[^1]\n\n[^1]: https://github.com/alvinwan/timefhuman/issues/3\n\n----\n\n## Getting Started\n\nInstall with pip using\n\n```python\npip install timefhuman\n```\n\nThen, find natural language dates and times in any text.\n\n```python\n>>> from timefhuman import timefhuman\n\n>>> timefhuman(\"How does 5p mon sound? Or maybe 4p tu?\")\n[datetime.datetime(2018, 8, 6, 17, 0), datetime.datetime(2018, 8, 7, 16, 0)]\n```\n\nThe text can contain not only datetimes but also ranges of datetimes or lists of datetimes.\n\n```python\n>>> timefhuman('3p-4p')  # time range\n(datetime.datetime(2018, 7, 17, 15, 0), datetime.datetime(2018, 7, 17, 16, 0))\n\n>>> timefhuman('7/17 4PM to 7/17 5PM')  # range of datetimes\n(datetime.datetime(2018, 7, 17, 16, 0), datetime.datetime(2018, 7, 17, 17, 0))\n\n>>> timefhuman('Monday 3 pm or Tu noon')  # list of datetimes\n[datetime.datetime(2018, 8, 6, 15, 0), datetime.datetime(2018, 8, 7, 12, 0)]\n\n>>> timefhuman('7/17 4-5 or 5-6 PM')  # list of ranges of datetimes!\n[(datetime.datetime(2018, 7, 17, 16, 0), datetime.datetime(2018, 7, 17, 17, 0)),\n (datetime.datetime(2018, 7, 17, 17, 0), datetime.datetime(2018, 7, 17, 18, 0))]\n```\n\nDurations are also supported.\n\n```python\n>>> timefhuman('30 minutes')  # duration\ndatetime.timedelta(seconds=1800)\n\n>>> timefhuman('30-40 mins')  # range of durations\n(datetime.timedelta(seconds=1800), datetime.timedelta(seconds=2400))\n\n>>> timefhuman('30 or 40m')  # list of durations\n[datetime.timedelta(seconds=1800), datetime.timedelta(seconds=2400)]\n```\n\nWhen possible, timefhuman will infer any missing information, using context from other datetimes.\n\n```python\n>>> timefhuman('3-4p')  # infer \"PM\" for \"3\"\n(datetime.datetime(2018, 7, 17, 15, 0), datetime.datetime(2018, 7, 17, 16, 0))\n\n>>> timefhuman('7/17 4 or 5 PM')  # infer \"PM\" for \"4\" and infer \"7/17\" for \"5 PM\"\n[datetime.datetime(2018, 7, 17, 16, 0), datetime.datetime(2018, 7, 17, 17, 0)]\n\n>>> timefhuman('7/17, 7/18, 7/19 at 9')  # infer \"9a\" for \"7/17\", \"7/18\"\n[datetime.datetime(2018, 7, 17, 9, 0), datetime.datetime(2018, 7, 18, 9, 0),\n datetime.datetime(2018, 7, 19, 9, 0)]\n\n>>> timefhuman('3p -4p PDT')  # infer timezone \"PDT\" for \"3p\"\n(datetime.datetime(2018, 8, 4, 15, 0, tzinfo=pytz.timezone('US/Pacific')),\n datetime.datetime(2018, 8, 4, 16, 0, tzinfo=pytz.timezone('US/Pacific')))\n```\n\nYou can also use natural language descriptions of dates and times.\n\n```python\n>>> timefhuman('next Monday')\ndatetime.datetime(2018, 8, 6, 0, 0)\n\n>>> timefhuman('next next Monday')\ndatetime.datetime(2018, 8, 13, 0, 0)\n\n>>> timefhuman('last Wednesday of December')\ndatetime.datetime(2018, 12, 26, 0, 0)\n\n>>> timefhuman('afternoon')\ndatetime.datetime(2018, 8, 4, 15, 0)\n```\n\nSee more examples in [`tests/test_e2e.py`](tests/test_e2e.py).\n\n## Advanced Usage\n\nFor more configuration options, simply create a `tfhConfig` object.\n\n```python\nfrom timefhuman import tfhConfig\nconfig = tfhConfig()\n```\n\n**Return matched text**: You can additionally grab the matched text from the input string. This is useful for modifying the input string, for example.\n\n```python\n>>> config = tfhConfig(return_matched_text=True)\n\n>>> timefhuman('We could maybe do 3 PM, if you still have time', config=config)\n[('3 PM', datetime.datetime(2018, 8, 4, 15, 0))]\n```\n\n**Change 'Now'**: You can configure the default date that timefhuman uses to fill in missing information. This would be useful if you're extracting dates from an email sent a year ago.\n\n```python\n>>> config = tfhConfig(now=datetime.datetime(2018, 8, 4, 0, 0))\n\n>>> timefhuman('upcoming Monday noon', config=config)\ndatetime.datetime(2018, 8, 6, 12, 0)\n```\n\nYou can also set a default timezone, by again using the config's `now`.\n\n```python\n>>> config = tfhConfig(\n...     now=datetime.datetime(2018, 8, 4), tzinfo=pytz.timezone('US/Pacific'))\n\n>>> timefhuman('Wed', config=config)\ndatetime.datetime(2018, 8, 8, 0, 0, tzinfo=pytz.timezone('US/Pacific'))\n\n>>> timefhuman('Wed EST', config=config)  # EST timezone in the input takes precedence\ndatetime.datetime(2018, 8, 8, 0, 0, tzinfo=pytz.timezone('US/Michigan'))\n```\n\n**Use explicit information only**: Say you only want to extract *dates* OR *times*. You don't want the library to infer information. You can disable most inference by setting `infer_datetimes=False`. Instead of always returning a datetime, timefhuman will be able to return date or time objects, depending on what's provided.\n\n```python\n>>> config = tfhConfig(infer_datetimes=False)\n\n>>> timefhuman('3 PM', config=config)\ndatetime.time(15, 0)\n\n>>> timefhuman('12/18/18', config=config)\ndatetime.date(2018, 12, 18)\n```\n\n**Past datetimes**: By default, datetimes are assumed to occur in the future, so if \"3pm\" today has already passed, the returned datetime will be for *tomorrow*. However, if datetimes are assumed to have occurred in the past (e.g., from an old letter, talking about past events), you can configure the direction.\n\n```python\n>>> from timefhuman import Direction\n>>> config = tfhConfig(direction=Direction.previous)\n\n>>> timefhuman('3PM')  # the default\ndatetime.datetime(2018, 8, 5, 15, 0)\n\n>>> timefhuman('3PM', config=config)  # changing direction\ndatetime.datetime(2018, 8, 4, 15, 0)\n```\n\nHere is the full set of supported configuration options:\n\n```python\n@dataclass\nclass tfhConfig:\n    # Default to the next valid datetime or the previous one\n    direction: Direction = Direction.next\n    \n    # Always return datetime objects. If no date, use now.date(). If no time, use midnight.\n    infer_datetimes: bool = True\n    \n    # The 'current' datetime, used if infer_datetimes is True. Defaults to datetime.now().\n    now: datetime | None = None\n    \n    # Return the matched text from the input string\n    return_matched_text: bool = False\n    \n    # Return a single object instead of a list when there's only one match\n    return_single_object: bool = True\n```\n\n## Development\n\nInstall the development version.\n\n```shell\n$ pip install .e .[test]  # for bash\n$ pip install -e .\\[test\\]  # for zsh\n```\n\nTo run tests and simultaneously generate a coverage report, use the following commands:\n\n```shell\n$ py.test --cov\n$ coverage html\n$ open htmlcov/index.html\n```\n",
    "bugtrack_url": null,
    "license": "Apache 2.0",
    "summary": "Extract datetimes, datetime ranges, and datetime lists from natural language text",
    "version": "0.1.2",
    "project_urls": {
        "Download": "https://github.com/alvinwan/timefhuman/archive/0.1.2.zip",
        "Homepage": "https://github.com/alvinwan/timefhuman"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f24c6c851ada7009d8d867929c0bd6be274529d7e60f31400c7af0c3624f426c",
                "md5": "fbc85e6e3a8c458060f3ff8b4b09066d",
                "sha256": "9d6c0d3d496088b5c802edbe27a80572d4b5baab378b8aa70f7c16aad20ce92e"
            },
            "downloads": -1,
            "filename": "timefhuman-0.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "fbc85e6e3a8c458060f3ff8b4b09066d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 17418,
            "upload_time": "2025-02-09T23:39:29",
            "upload_time_iso_8601": "2025-02-09T23:39:29.278351Z",
            "url": "https://files.pythonhosted.org/packages/f2/4c/6c851ada7009d8d867929c0bd6be274529d7e60f31400c7af0c3624f426c/timefhuman-0.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9a3de9d9eb252a80dd47d87d829a068958221ca26cd210df6f989c4eecfcac8e",
                "md5": "ee30fff265b2e7a95ff2402e9d556411",
                "sha256": "df007defbd7b5bda96e77708e94a0f557230b80e674fa3be7a81a3da4ad08eee"
            },
            "downloads": -1,
            "filename": "timefhuman-0.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "ee30fff265b2e7a95ff2402e9d556411",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 21137,
            "upload_time": "2025-02-09T23:39:30",
            "upload_time_iso_8601": "2025-02-09T23:39:30.535909Z",
            "url": "https://files.pythonhosted.org/packages/9a/3d/e9d9eb252a80dd47d87d829a068958221ca26cd210df6f989c4eecfcac8e/timefhuman-0.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-09 23:39:30",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "alvinwan",
    "github_project": "timefhuman",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": false,
    "lcname": "timefhuman"
}
        
Elapsed time: 0.70220s