Skip to main content

Typesafe datetimes powered by Rust's chrono library

Project description

https://img.shields.io/pypi/v/whenever.svg?style=flat-square&color=blue https://img.shields.io/pypi/pyversions/whenever.svg?style=flat-square https://img.shields.io/pypi/l/whenever.svg?style=flat-square&color=blue https://img.shields.io/badge/mypy-strict-forestgreen?style=flat-square https://img.shields.io/github/actions/workflow/status/ariebovenberg/whenever/CI.yml?branch=main&style=flat-square https://img.shields.io/readthedocs/whenever.svg?style=flat-square

Typesafe datetimes powered by Rust’s chrono library.

Currently a work in progress. Leave a ⭐️ if you’re interested how this develops.

Why?

Most Python datetime libraries use a single class for naive, timezoned, and offset datetimes, making it all too easy to mistakenly (and silently!) mix them. Your type checker and IDE are powerless to help you, leaving you to discover these errors at runtime.

Whenever takes a different approach, and provides dedicated datetime types that reveal mistakes before you run your code.

Types of datetime (and why they’re important)

🚧 NOT YET FULLY IMPLEMENTED 🚧

Whenever distinguishes these types:

  1. Naive datetime: A simple type that isn’t aware of any timezone or UTC offset.

  2. UTC-only datetime: A fast and efficient type for when you only want to deal with UTC.

  3. Offset datetime: A datetime with a fixed offset from UTC.

  4. Zoned datetime: A datetime within a timezone, often with a variable UTC offset. Zoned datetimes may be ambiguous or non-existent.

Below is a table of supported operations for each type:

Operation

Naive

UTC

Offset

Zoned

comparison

difference

add/subtract duration

to timestamp

⚠️

from timestamp

now()

to naive

n/a

to UTC

n/a

⚠️

to offset

n/a

⚠️

to zoned

n/a

⚠️ = returns 0, 1, or 2 results, which must explicitly be handled.

❌ = Too ambiguous to provide a sensible result.

Quickstart

Most of the functionality it not yet implemented. Some basic UTC functionality is already available though:

from whenever.utc import DateTime
from whenever import Some, Nothing

# Explicit types for functional/Rust-style error handling
d = DateTime.new(2020, 1, 1, 12, 0, 0).unwrap()

match DateTime.parse("2020-08-15T12:08:30Z"):
    case Some(d2) if d2 > d:
        print('parsed a datetime after 2020-01-01T12:00:00Z')
    case Nothing():
        print('failed to parse')

d.timestamp()  # UNIX timestamp
d.to_py()  # convert to Python's datetime.datetime

Versioning and compatibility policy

Whenever follows semantic versioning. Until the 1.0 version, the API may change with minor releases. Breaking changes will be announced in the changelog. Since the API is fully typed, your typechecker and/or IDE will help you adjust to any API changes.

Acknowledgements

This project is inspired by the following projects. Check them out!

Development

An example of setting up things and running the tests:

pip install maturin
maturin develop --extras test
pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

whenever-0.0.3.tar.gz (16.9 kB view hashes)

Uploaded Source

Built Distributions

whenever-0.0.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

whenever-0.0.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

whenever-0.0.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

whenever-0.0.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

whenever-0.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

whenever-0.0.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

whenever-0.0.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

whenever-0.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

whenever-0.0.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

whenever-0.0.3-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

whenever-0.0.3-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

whenever-0.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl (1.2 MB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

whenever-0.0.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded CPython 3.13 manylinux: glibc 2.17+ s390x

whenever-0.0.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded CPython 3.13 manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded CPython 3.13 manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded CPython 3.13 manylinux: glibc 2.17+ ARM64

whenever-0.0.3-cp312-none-win_amd64.whl (167.9 kB view hashes)

Uploaded CPython 3.12 Windows x86-64

whenever-0.0.3-cp312-none-win32.whl (163.6 kB view hashes)

Uploaded CPython 3.12 Windows x86

whenever-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

whenever-0.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x

whenever-0.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

whenever-0.0.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl (1.2 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.5+ i686

whenever-0.0.3-cp312-cp312-macosx_11_0_arm64.whl (305.3 kB view hashes)

Uploaded CPython 3.12 macOS 11.0+ ARM64

whenever-0.0.3-cp311-none-win_amd64.whl (167.2 kB view hashes)

Uploaded CPython 3.11 Windows x86-64

whenever-0.0.3-cp311-none-win32.whl (163.5 kB view hashes)

Uploaded CPython 3.11 Windows x86

whenever-0.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

whenever-0.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x

whenever-0.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

whenever-0.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl (1.2 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.5+ i686

whenever-0.0.3-cp311-cp311-macosx_11_0_arm64.whl (305.2 kB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

whenever-0.0.3-cp311-cp311-macosx_10_7_x86_64.whl (310.6 kB view hashes)

Uploaded CPython 3.11 macOS 10.7+ x86-64

whenever-0.0.3-cp310-none-win_amd64.whl (167.4 kB view hashes)

Uploaded CPython 3.10 Windows x86-64

whenever-0.0.3-cp310-none-win32.whl (163.6 kB view hashes)

Uploaded CPython 3.10 Windows x86

whenever-0.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

whenever-0.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x

whenever-0.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

whenever-0.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl (1.2 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.5+ i686

whenever-0.0.3-cp310-cp310-macosx_11_0_arm64.whl (305.6 kB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

whenever-0.0.3-cp310-cp310-macosx_10_7_x86_64.whl (310.6 kB view hashes)

Uploaded CPython 3.10 macOS 10.7+ x86-64

whenever-0.0.3-cp39-none-win_amd64.whl (167.6 kB view hashes)

Uploaded CPython 3.9 Windows x86-64

whenever-0.0.3-cp39-none-win32.whl (165.2 kB view hashes)

Uploaded CPython 3.9 Windows x86

whenever-0.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

whenever-0.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x

whenever-0.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

whenever-0.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl (1.2 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.5+ i686

whenever-0.0.3-cp38-none-win_amd64.whl (167.1 kB view hashes)

Uploaded CPython 3.8 Windows x86-64

whenever-0.0.3-cp38-none-win32.whl (163.5 kB view hashes)

Uploaded CPython 3.8 Windows x86

whenever-0.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

whenever-0.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.4 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x

whenever-0.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.3 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le

whenever-0.0.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.2 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARMv7l

whenever-0.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

whenever-0.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl (1.2 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.5+ i686

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page