# python-snaptime
![PyPI - Version](https://img.shields.io/pypi/v/python-snaptime?style=flat-square)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/python-snaptime)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/dtomlinson91/python-snaptime/codacy.yml?style=flat-square)
![Codacy coverage](https://img.shields.io/codacy/coverage/d252742da60f4d90b72aa7d7de1a7a2f?style=flat-square)
![Codacy grade](https://img.shields.io/codacy/grade/d252742da60f4d90b72aa7d7de1a7a2f?style=flat-square)
Inspired by Splunk's [relative time modifiers](http://docs.splunk.com/Documentation/Splunk/latest/SearchReference/SearchTimeModifiers#How_to_specify_relative_time_modifiers), `python-snaptime` will transform `datetime` objects using relative time modifiers.
For example, `@d-2h` will give you two hours ago from the start of the day.
- Use snaptime strings to get relative dates/times for a given datetime.
- Timezone aware.
- Effortlessly handles daylight savings using [pendulum](https://github.com/python-pendulum/pendulum).
- Can snap backwards in time to the nearest second, minute, hour, day, week, month, quarter or year.
- Can add/subtract microseconds, milliseconds, seconds, minutes, hours, days, weeks, months, quarters or years.
- Chain snaps together as needed e.g `@d-12h+10m@h`.
- Use either a snaptime string, or use Python to define snaptimes ([see advanced example](#advanced)).
- Fully type annotated for IDE completion.
> [!NOTE]
> This package was created as a more up to date replacement for [zartstrom/snaptime](https://github.com/zartstrom/snaptime), which is long since abandoned.
## Snaptime strings
| Unit | Strings | Supports Snapping? | Supports Delta? |
| :------------ | :---------------------------------------- | :----------------: | :-------------: |
| `MICROSECOND` | `us`, `microsecond`, `microseconds` | ❌ | ✅ |
| `MILLISECOND` | `ms`, `millisecond`, `milliseconds` | ❌ | ✅ |
| `SECOND` | `s`, `sec`, `secs`, `second`, `seconds` | ✅ | ✅ |
| `MINUTE` | `m`, `min`, `mins`, `minute`, `minutes` | ✅ | ✅ |
| `HOUR` | `h`, `hr`, `hrs`, `hour`, `hours` | ✅ | ✅ |
| `DAY` | `d`, `day`, `days` | ✅ | ✅ |
| `WEEK` | `w`, `week`, `weeks` | ✅ | ✅ |
| `MONTH` | `mon`, `month`, `months` | ✅ | ✅ |
| `QUARTER` | `q`, `qtr`, `qtrs`, `quarter`, `quarters` | ✅ | ✅ |
| `YEAR` | `y`, `yr`, `yrs`, `year`, `years` | ✅ | ✅ |
## Examples
### Timezones
Using `pendulum` timezones are handled easily.
```python
>>> import pendulum
>>> from python_snaptime import snap
>>> dtm = pendulum.datetime(2024, 12, 30, 18, 0, 0)
>>> snap(dtm, "@d-12h")
DateTime(2024, 12, 29, 12, 0, 0, tzinfo=Timezone('UTC'))
```
```python
>>> import pendulum
>>> from python_snaptime import snap
>>> dtm = pendulum.datetime(2024, 12, 30, 18, 0, 0, tz=pendulum.timezone("Europe/London"))
>>> snap(dtm, "@d-12h")
DateTime(2024, 12, 29, 12, 0, 0, tzinfo=Timezone('Europe/London'))
```
### DST
`pendulum` makes working around DST easy
```python
>>> import pendulum
>>> from python_snaptime import snap
>>> dtm = pendulum.datetime(2024, 10, 27, 1, 59, 59, tz="Europe/London", fold=0)
>>> snap(dtm, "+1s")
DateTime(2024, 10, 27, 1, 0, 0, tzinfo=Timezone('Europe/London')) # pre-transition
```
```python
>>> import pendulum
>>> from python_snaptime import snap
>>> dtm = pendulum.datetime(2024, 10, 27, 1, 59, 59, tz="Europe/London", fold=1)
>>> snap(dtm, "+1s")
DateTime(2024, 10, 27, 2, 0, 0, tzinfo=Timezone('Europe/London')) # post-transition (default)
```
### datetime
Don't care about timezones/want to use builtin `datetime.datetime`?
```python
>>> from datetime import datetime
>>> from python_snaptime import snap
>>> dtm = datetime(2024, 12, 30, 18, 0, 0)
>>> snap(dtm, "@d-12h")
datetime.datetime(2024, 12, 29, 12, 0)
```
Can also work with builtin timezone aware datetimes
```python
>>> from datetime import datetime
>>> from zoneinfo import ZoneInfo
>>> from python_snaptime import snap
>>> dtm = datetime(2024, 12, 30, 18, 0, 0, tzinfo=ZoneInfo("Europe/London"))
>>> snap(dtm, "@d-12h")
datetime.datetime(2024, 12, 29, 12, 0, tzinfo=Timezone('Europe/London'))
```
## Installation
### pypi
```sh
# using poetry
poetry add python-snaptime
# using pip
pip install python-snaptime
```
## Usage
```python
import pendulum
from python_snaptime import snap
snapped_datetime = snap(pendulum.now(), "@d-2h+10m")
```
### Advanced
You can programmatically calculate snaptimes without a snaptime string, e.g the equivalent of `@d-2h+10m` is:
```python
import pendulum
from python_snaptime.handlers import handle_timesnapping
from python_snaptime.models import Action, Snaptime, Unit
def main():
datetime = pendulum.now()
time_snapping_operations = [
Snaptime(action=Action.SNAP, unit=Unit.DAY),
Snaptime(action=Action.SUB, unit=Unit.HOUR, time_int=2),
Snaptime(action=Action.ADD, unit=Unit.MINUTE, time_int=10),
]
for operation in time_snapping_operations:
datetime = handle_timesnapping(operation, datetime)
print(datetime) # `@d-2h+10m`
if __name__ == "__main__":
main()
```
Raw data
{
"_id": null,
"home_page": "https://github.com/dtomlinson91/python-snaptime",
"name": "python-snaptime",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": "datetime, time, datetime, timesnap, timesnapper, snaptime",
"author": "Daniel Tomlinson",
"author_email": "dtomlinson@panaetius.co.uk",
"download_url": "https://files.pythonhosted.org/packages/d7/90/056e4784d661d35f5e5e104c01afc6c3330bb5dfdf14fcb902a6c79658c4/python_snaptime-0.1.2.tar.gz",
"platform": null,
"description": "# python-snaptime\n\n![PyPI - Version](https://img.shields.io/pypi/v/python-snaptime?style=flat-square)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/python-snaptime)\n![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/dtomlinson91/python-snaptime/codacy.yml?style=flat-square)\n![Codacy coverage](https://img.shields.io/codacy/coverage/d252742da60f4d90b72aa7d7de1a7a2f?style=flat-square)\n![Codacy grade](https://img.shields.io/codacy/grade/d252742da60f4d90b72aa7d7de1a7a2f?style=flat-square)\n\n\nInspired by Splunk's [relative time modifiers](http://docs.splunk.com/Documentation/Splunk/latest/SearchReference/SearchTimeModifiers#How_to_specify_relative_time_modifiers), `python-snaptime` will transform `datetime` objects using relative time modifiers.\n\nFor example, `@d-2h` will give you two hours ago from the start of the day.\n\n- Use snaptime strings to get relative dates/times for a given datetime.\n- Timezone aware.\n- Effortlessly handles daylight savings using [pendulum](https://github.com/python-pendulum/pendulum).\n- Can snap backwards in time to the nearest second, minute, hour, day, week, month, quarter or year.\n- Can add/subtract microseconds, milliseconds, seconds, minutes, hours, days, weeks, months, quarters or years.\n- Chain snaps together as needed e.g `@d-12h+10m@h`.\n- Use either a snaptime string, or use Python to define snaptimes ([see advanced example](#advanced)).\n- Fully type annotated for IDE completion.\n\n> [!NOTE]\n> This package was created as a more up to date replacement for [zartstrom/snaptime](https://github.com/zartstrom/snaptime), which is long since abandoned.\n\n## Snaptime strings\n\n| Unit | Strings | Supports Snapping? | Supports Delta? |\n| :------------ | :---------------------------------------- | :----------------: | :-------------: |\n| `MICROSECOND` | `us`, `microsecond`, `microseconds` | \u274c | \u2705 |\n| `MILLISECOND` | `ms`, `millisecond`, `milliseconds` | \u274c | \u2705 |\n| `SECOND` | `s`, `sec`, `secs`, `second`, `seconds` | \u2705 | \u2705 |\n| `MINUTE` | `m`, `min`, `mins`, `minute`, `minutes` | \u2705 | \u2705 |\n| `HOUR` | `h`, `hr`, `hrs`, `hour`, `hours` | \u2705 | \u2705 |\n| `DAY` | `d`, `day`, `days` | \u2705 | \u2705 |\n| `WEEK` | `w`, `week`, `weeks` | \u2705 | \u2705 |\n| `MONTH` | `mon`, `month`, `months` | \u2705 | \u2705 |\n| `QUARTER` | `q`, `qtr`, `qtrs`, `quarter`, `quarters` | \u2705 | \u2705 |\n| `YEAR` | `y`, `yr`, `yrs`, `year`, `years` | \u2705 | \u2705 |\n\n## Examples\n\n### Timezones\n\nUsing `pendulum` timezones are handled easily.\n\n```python\n>>> import pendulum\n>>> from python_snaptime import snap\n\n>>> dtm = pendulum.datetime(2024, 12, 30, 18, 0, 0)\n>>> snap(dtm, \"@d-12h\")\nDateTime(2024, 12, 29, 12, 0, 0, tzinfo=Timezone('UTC'))\n```\n\n```python\n>>> import pendulum\n>>> from python_snaptime import snap\n\n>>> dtm = pendulum.datetime(2024, 12, 30, 18, 0, 0, tz=pendulum.timezone(\"Europe/London\"))\n>>> snap(dtm, \"@d-12h\")\nDateTime(2024, 12, 29, 12, 0, 0, tzinfo=Timezone('Europe/London'))\n```\n\n### DST\n\n`pendulum` makes working around DST easy\n\n```python\n>>> import pendulum\n>>> from python_snaptime import snap\n\n>>> dtm = pendulum.datetime(2024, 10, 27, 1, 59, 59, tz=\"Europe/London\", fold=0)\n>>> snap(dtm, \"+1s\")\nDateTime(2024, 10, 27, 1, 0, 0, tzinfo=Timezone('Europe/London')) # pre-transition\n```\n\n```python\n>>> import pendulum\n>>> from python_snaptime import snap\n\n>>> dtm = pendulum.datetime(2024, 10, 27, 1, 59, 59, tz=\"Europe/London\", fold=1)\n>>> snap(dtm, \"+1s\")\nDateTime(2024, 10, 27, 2, 0, 0, tzinfo=Timezone('Europe/London')) # post-transition (default)\n```\n\n### datetime\n\nDon't care about timezones/want to use builtin `datetime.datetime`?\n\n```python\n>>> from datetime import datetime\n>>> from python_snaptime import snap\n\n>>> dtm = datetime(2024, 12, 30, 18, 0, 0)\n>>> snap(dtm, \"@d-12h\")\ndatetime.datetime(2024, 12, 29, 12, 0)\n```\n\nCan also work with builtin timezone aware datetimes\n\n```python\n>>> from datetime import datetime\n>>> from zoneinfo import ZoneInfo\n>>> from python_snaptime import snap\n\n>>> dtm = datetime(2024, 12, 30, 18, 0, 0, tzinfo=ZoneInfo(\"Europe/London\"))\n>>> snap(dtm, \"@d-12h\")\ndatetime.datetime(2024, 12, 29, 12, 0, tzinfo=Timezone('Europe/London'))\n```\n\n## Installation\n\n### pypi\n\n```sh\n# using poetry\npoetry add python-snaptime\n\n# using pip\npip install python-snaptime\n```\n\n## Usage\n\n```python\nimport pendulum\nfrom python_snaptime import snap\n\nsnapped_datetime = snap(pendulum.now(), \"@d-2h+10m\")\n```\n\n### Advanced\n\nYou can programmatically calculate snaptimes without a snaptime string, e.g the equivalent of `@d-2h+10m` is:\n\n```python\nimport pendulum\n\nfrom python_snaptime.handlers import handle_timesnapping\nfrom python_snaptime.models import Action, Snaptime, Unit\n\n\ndef main():\n datetime = pendulum.now()\n time_snapping_operations = [\n Snaptime(action=Action.SNAP, unit=Unit.DAY),\n Snaptime(action=Action.SUB, unit=Unit.HOUR, time_int=2),\n Snaptime(action=Action.ADD, unit=Unit.MINUTE, time_int=10),\n ]\n for operation in time_snapping_operations:\n datetime = handle_timesnapping(operation, datetime)\n print(datetime) # `@d-2h+10m`\n\n\nif __name__ == \"__main__\":\n main()\n\n```\n",
"bugtrack_url": null,
"license": "ISC",
"summary": "Easily manipulate datetime objects with relative time modifiers. Snap, shift, and chain operations on timezone-aware datetimes. E.g `@d-2h`",
"version": "0.1.2",
"project_urls": {
"Documentation": "https://github.com/dtomlinson91/python-snaptime",
"Homepage": "https://github.com/dtomlinson91/python-snaptime",
"Repository": "https://github.com/dtomlinson91/python-snaptime"
},
"split_keywords": [
"datetime",
" time",
" datetime",
" timesnap",
" timesnapper",
" snaptime"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "6aef002e43645a9b46692e66fb64d7762a0bc105690ad0f5e20dcd0512d79bca",
"md5": "5640f21adf9e5c3bacbb3258885b7a8a",
"sha256": "00c2dd993dee05d2c4bf716c4cd7bafe8615de00a9be7ba9eb9f61b096cb18ad"
},
"downloads": -1,
"filename": "python_snaptime-0.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5640f21adf9e5c3bacbb3258885b7a8a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 7772,
"upload_time": "2025-01-03T23:52:05",
"upload_time_iso_8601": "2025-01-03T23:52:05.119655Z",
"url": "https://files.pythonhosted.org/packages/6a/ef/002e43645a9b46692e66fb64d7762a0bc105690ad0f5e20dcd0512d79bca/python_snaptime-0.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d790056e4784d661d35f5e5e104c01afc6c3330bb5dfdf14fcb902a6c79658c4",
"md5": "0a23267ed6c2f1f9c453333a817b2e8f",
"sha256": "baf0414da2cc8a57640c8d14236d14b14f971649d1245fca8d6a7ffe23b47675"
},
"downloads": -1,
"filename": "python_snaptime-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "0a23267ed6c2f1f9c453333a817b2e8f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 8015,
"upload_time": "2025-01-03T23:52:07",
"upload_time_iso_8601": "2025-01-03T23:52:07.245824Z",
"url": "https://files.pythonhosted.org/packages/d7/90/056e4784d661d35f5e5e104c01afc6c3330bb5dfdf14fcb902a6c79658c4/python_snaptime-0.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-03 23:52:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "dtomlinson91",
"github_project": "python-snaptime",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "python-snaptime"
}