{"id":46670694,"url":"https://github.com/dtomlinson91/python-snaptime","last_synced_at":"2026-03-08T21:52:11.366Z","repository":{"id":270393031,"uuid":"910225744","full_name":"dtomlinson91/python-snaptime","owner":"dtomlinson91","description":"Easily manipulate datetime objects with relative time modifiers. Snap, shift, and chain operations on timezone-aware datetimes. E.g `@d-2h`","archived":false,"fork":false,"pushed_at":"2025-01-14T18:05:18.000Z","size":106,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-19T11:40:31.889Z","etag":null,"topics":["datetime","python","snaptime","time","timesnap","timesnapper"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dtomlinson91.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-30T18:18:34.000Z","updated_at":"2025-12-17T11:44:04.000Z","dependencies_parsed_at":"2024-12-30T20:30:35.801Z","dependency_job_id":"64277331-78ae-4fc6-a377-e107362bfb93","html_url":"https://github.com/dtomlinson91/python-snaptime","commit_stats":null,"previous_names":["dtomlinson91/python-snaptime"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/dtomlinson91/python-snaptime","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtomlinson91%2Fpython-snaptime","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtomlinson91%2Fpython-snaptime/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtomlinson91%2Fpython-snaptime/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtomlinson91%2Fpython-snaptime/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dtomlinson91","download_url":"https://codeload.github.com/dtomlinson91/python-snaptime/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtomlinson91%2Fpython-snaptime/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30274852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T20:45:49.896Z","status":"ssl_error","status_checked_at":"2026-03-08T20:45:49.525Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["datetime","python","snaptime","time","timesnap","timesnapper"],"created_at":"2026-03-08T21:52:10.773Z","updated_at":"2026-03-08T21:52:11.356Z","avatar_url":"https://github.com/dtomlinson91.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 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- Use [pendulum](https://github.com/python-pendulum/pendulum) or builtin [datetime](https://docs.python.org/3/library/datetime.html#datetime-objects).\n- Timezone aware.\n- Handles daylight savings with `fold`.\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\u003e [!NOTE]\n\u003e 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`       |         ❌         |       ✅        |\n| `MILLISECOND` | `ms`, `millisecond`, `milliseconds`       |         ❌         |       ✅        |\n| `SECOND`      | `s`, `sec`, `secs`, `second`, `seconds`   |         ✅         |       ✅        |\n| `MINUTE`      | `m`, `min`, `mins`, `minute`, `minutes`   |         ✅         |       ✅        |\n| `HOUR`        | `h`, `hr`, `hrs`, `hour`, `hours`         |         ✅         |       ✅        |\n| `DAY`         | `d`, `day`, `days`                        |         ✅         |       ✅        |\n| `WEEK`        | `w`, `week`, `weeks`                      |         ✅         |       ✅        |\n| `MONTH`       | `mon`, `month`, `months`                  |         ✅         |       ✅        |\n| `QUARTER`     | `q`, `qtr`, `qtrs`, `quarter`, `quarters` |         ✅         |       ✅        |\n| `YEAR`        | `y`, `yr`, `yrs`, `year`, `years`         |         ✅         |       ✅        |\n\n## Examples\n\n### Timezones\n\nUsing `pendulum` timezones are handled easily.\n\n```python\n\u003e\u003e\u003e import pendulum\n\u003e\u003e\u003e from python_snaptime import snap\n\n\u003e\u003e\u003e dtm = pendulum.datetime(2024, 12, 30, 18, 0, 0)\n\u003e\u003e\u003e snap(dtm, \"@d-12h\")\nDateTime(2024, 12, 29, 12, 0, 0, tzinfo=Timezone('UTC'))\n```\n\n```python\n\u003e\u003e\u003e import pendulum\n\u003e\u003e\u003e from python_snaptime import snap\n\n\u003e\u003e\u003e dtm = pendulum.datetime(2024, 12, 30, 18, 0, 0, tz=pendulum.timezone(\"Europe/London\"))\n\u003e\u003e\u003e snap(dtm, \"@d-12h\")\nDateTime(2024, 12, 29, 12, 0, 0, tzinfo=Timezone('Europe/London'))\n```\n\n### datetime\n\nDon't care about timezones/want to use builtin `datetime.datetime`?\n\n```python\n\u003e\u003e\u003e from datetime import datetime\n\u003e\u003e\u003e from python_snaptime import snap\n\n\u003e\u003e\u003e dtm = datetime(2024, 12, 30, 18, 0, 0)\n\u003e\u003e\u003e 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\u003e\u003e\u003e from datetime import datetime\n\u003e\u003e\u003e from zoneinfo import ZoneInfo\n\u003e\u003e\u003e from python_snaptime import snap\n\n\u003e\u003e\u003e dtm = datetime(2024, 12, 30, 18, 0, 0, tzinfo=ZoneInfo(\"Europe/London\"))\n\u003e\u003e\u003e snap(dtm, \"@d-12h\")\ndatetime.datetime(2024, 12, 29, 12, 0, tzinfo=Timezone('Europe/London'))\n```\n\n### DST\n\nUse `fold` to work with DST.\n\n```python\n\u003e\u003e\u003e import pendulum\n\u003e\u003e\u003e from python_snaptime import snap\n\n\u003e\u003e\u003e dtm = pendulum.datetime(2024, 10, 27, 1, 59, 59, tz=\"Europe/London\", fold=0)\n\u003e\u003e\u003e snap(dtm, \"+1s\")\nDateTime(2024, 10, 27, 1, 0, 0, tzinfo=Timezone('Europe/London'))  # pre-transition\n```\n\n```python\n\u003e\u003e\u003e import pendulum\n\u003e\u003e\u003e from python_snaptime import snap\n\n\u003e\u003e\u003e dtm = pendulum.datetime(2024, 10, 27, 1, 59, 59, tz=\"Europe/London\", fold=1)\n\u003e\u003e\u003e snap(dtm, \"+1s\")\nDateTime(2024, 10, 27, 2, 0, 0, tzinfo=Timezone('Europe/London'))  # post-transition (default)\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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtomlinson91%2Fpython-snaptime","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdtomlinson91%2Fpython-snaptime","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtomlinson91%2Fpython-snaptime/lists"}