diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fd75256f..2c083b1e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,5 +15,5 @@ - [ ] Version updated in changelog - [ ] Branch merged - [ ] Tag created and pushed -- [ ] Published +- [ ] Confirm published job runs successfully - [ ] Github release created diff --git a/CHANGELOG.rst b/CHANGELOG.rst index afea5ff8..56619941 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,10 +1,11 @@ šŸš€ Changelog ============ -0.6.3 (2024-07-??) +0.6.3 (2024-07-13) ------------------ - Improve robustness and speed of keyword argument parsing in Rust extension (#149) +- Add more answers to common questions in the docs and FAQ (#148, #150) 0.6.2 (2024-07-04) ------------------ diff --git a/Cargo.lock b/Cargo.lock index 05407df8..fbafad8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,7 +165,7 @@ checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" [[package]] name = "whenever" -version = "0.6.0-beta.1" +version = "0.6.3" dependencies = [ "pyo3", "pyo3-build-config", diff --git a/Cargo.toml b/Cargo.toml index 356c191d..07ca0663 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "whenever" -version = "0.6.0-beta.1" +version = "0.6.3" authors = [] description = "Rust extension module for whenever" edition = "2021" diff --git a/README.md b/README.md index 086e8886..6dbc1ab6 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![](https://img.shields.io/github/actions/workflow/status/ariebovenberg/whenever/checks.yml?branch=main&style=flat-square)](https://github.com/ariebovenberg/whenever) [![](https://img.shields.io/readthedocs/whenever.svg?style=flat-square)](http://whenever.readthedocs.io/) -**Typed and DST-safe datetimes for Python, written in Rust** +**Typed and DST-safe datetimes for Python, written in Rust\*** Do you cross your fingers every time you work with Python's datetimeā€”hoping that you didn't mix naive and aware? or that you avoided its [other pitfalls](https://dev.arie.bovenberg.net/blog/python-datetime-pitfalls/)? @@ -33,6 +33,7 @@ It's also **way faster** than other third-party librariesā€”and usually the stan RFC3339-parse, normalize, compare to now, shift, and change timezone (1M times)

+
[šŸ“–Ā Docs](https://whenever.readthedocs.io)Ā | @@ -49,6 +50,8 @@ It's also **way faster** than other third-party librariesā€”and usually the stan > as we gather feedback and improve the library. > Leave a ā­ļø on github if you'd like to see how this project develops! +\**Skeptical of Rust? Don't worry, it's available in pure Python too!* + ## Why not the standard library? Over 20+ years, Python's `datetime` has grown diff --git a/docs/faq.rst b/docs/faq.rst index 7ce3f24c..c15304fc 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -139,6 +139,12 @@ You can check if the Rust extension is being used by running: you should consult its documentation on opting out of binary wheels. +What's the performance of the pure-Python version? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In casual benchmarks, the pure-Python version is about 10x slower than the Rust version, +making it 5x slower than the standard library but still (in general) faster than Pendulum and Arrow. + What about ``dateutil``? ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -150,3 +156,21 @@ That said, here are my thoughts on dateutil: while it certainly provides useful helpers (especially for parsing and arithmetic), it doesn't solve the (IMHO) most glaring issues with the standard library: DST-safety and typing for naive/aware. These are issues that only a full replacement can solve. + +Why use ``pyo3_ffi`` instead of ``PyO3``? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are two main reasons: + +1. The higher-level binding library PyO3 has a small additional overhead for function calls, + which can be significant for small functions. Whenever has a lot of small functions. + Only with ``pyo3_ffi`` can these functions be on par (or faster) than the standard library. + The overhead has decreased in recent versions of PyO3, but it's still there. +2. I was eager to learn to use the bare C API of Python, in order to better + understand how Python extension modules and PyO3 work under the hood. + +Additional advantages of ``pyo3_ffi`` are: + +- Its API is more stable than PyO3's, which is still evolving. +- It allows support for per-interpreter GIL, and free-threaded Python, + which are not yet supported by PyO3. diff --git a/docs/overview.rst b/docs/overview.rst index dd79a802..a55dd840 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -375,6 +375,20 @@ and :class:`~whenever.SystemDateTime` types: Common approaches are to extrapolate the time forward or backwards to 1:30am or 3:30am. + .. important:: + + You may wonder why skipped time is "extrapolated" like this, + and not truncated. Why turn 2:30am into 3:30am and not cut + it off at 1:59am when the gap occurs? + + The reason for the "extrapolation" approach is: + + * It fits the most likely reason the time is skipped: we forgot to adjust the clock, or adjusted it too early + * This is how other datetime libraries do it (e.g. Javascript (Temporal), C# (Nodatime), Java, Python itself) + * It corresponds with the iCalendar (RFC5545) standard of handling gaps + + The figure in the Python docs `here `_ also shows how this "extrapolation" makes sense graphically. + **Whenever** `refuses to guess `_ and requires that you explicitly handle these situations with the ``disambiguate=`` argument: diff --git a/pyproject.toml b/pyproject.toml index 6edc7b8d..4bfbbe2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ authors = [ {name = "Arie Bovenberg", email = "a.c.bovenberg@gmail.com"}, ] readme = "README.md" -version = "0.6.1" +version = "0.6.3" description = "Modern datetime library for Python, written in Rust" requires-python = ">=3.9" classifiers = [ diff --git a/pysrc/whenever/_pywhenever.py b/pysrc/whenever/_pywhenever.py index 48c47404..5cf4ff3a 100644 --- a/pysrc/whenever/_pywhenever.py +++ b/pysrc/whenever/_pywhenever.py @@ -32,7 +32,7 @@ # - It saves some overhead from __future__ import annotations -__version__ = "0.6.2" +__version__ = "0.6.3" import enum import re