NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1367 most downloaded on PyPI
Modern datetime library for Python
Last release 1 months ago
07 Aug 2026
Release timing varies
gaps range from 8 days to 2 months
Nearly every release is documented
notes for 59 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
3 years old
84 releases · first in 2023
Nothing published for this version
Improve robustness and speed of keyword argument parsing in Rust extension
Add third-party licenses to distributions
Add third-party licenses to distributions
One column per month.
Small updates to project metadata
Small updates to project metadata
:tada: A big release touting a Rust extension module and an API more consistent with other modern libraries.
:tada: A big release touting a Rust extension module and an API more consistent with other modern libraries.
Added or improved
replace_date and replace_time methods to datetimes.Date.MIN and Date.MAX constants.from_py_* methods are more robust.Breaking changes
(see the changelog for the full rationale behind each change)
UTCDateTime is now Instant. Removed methods that were specific to UTC.NaiveDateTime is now LocalDateTimenanosecond is a keyword-only argument for all constructors, to prevent mistakes porting code from datetime (which uses microseconds).[from_]canonical_format methods with [from_]common_iso8601 methods into [format|parse]_common_iso methods.[from_][rfc3339|rfc2822] methods to [format|parse]_[rfc3339|rfc2822].ignore_dst=True flag to DST-unsafe operations such as shifting an offset datetime.as_utc, as_offset, as_zoned, as_local to to_utc, to_fixed_offset, to_tz, to_system_tz, and the NaiveDateTime.assume_* methods accordinglydisambiguate= is non-optional for all relevant methods. The only exception is the constructor, which defaults to "raise".Date[Time]Delta can now only be retrieved together. For example, there is no delta.months or delta.days anymore,delta.in_months_days() should be used in this case.AmbiguousTime to RepeatedTime.A big release touting a Rust extension module and an API more consistent with other modern libraries.
Added or improved
replace_date and replace_time methods to datetimes.Date.MIN and Date.MAX constants.from_py_* methods are more robust.Breaking changes
UTCDateTime is now Instant. Removed methods that were specific to
UTC.
Rationale: Instant is simpler and more conceptually clear. It
also avoids the mistake of performing calendar arithmetic in UTC.
NaiveDateTime is now LocalDateTime
Rationale: "Local" is more descriptive for describing the concept of "wall clock" time observed locally by humans. It's also consistent with other libraries and standards.
Nanosecond precision is now the default for all datetimes and deltas.
nanosecond is a keyword-only argument for all constructors, to
prevent mistakes porting code from datetime (which uses
microseconds).
Rationale: Nanosecond precision is the standard for modern datetime libraries.
Unified [from_]canonical_format methods with [from_]common_iso8601
methods into [format|parse]_common_iso methods.
Rationale: This cuts down on the number of methods; the performance benefits of separate methods aren't worth the clutter.
Timestamp methods now use integers instead of floats. There are now separate methods for seconds, milliseconds, and nanoseconds.
Rationale: This prevents loss of precision when converting to floats, and is more in line with other modern libraries.
Renamed [from_][rfc3339|rfc2822] methods to
[format|parse]_[rfc3339|rfc2822].
Rationale: Consistency with other methods.
Added explicit ignore_dst=True flag to DST-unsafe operations such as
shifting an offset datetime.
Rationale: Previously, DST-unsafe operations were completely disallowed, but to a frustrating degree. This flag is a better alternative than having users resort to workarounds.
Renamed as_utc, as_offset, as_zoned, as_local to to_utc,
to_fixed_offset, to_tz, to_system_tz, and the
NaiveDateTime.assume_* methods accordingly
Rationale: "to" better clarifies a conversion is being made (not a replacement), and "fixed offset" and "tz" are more descriptive than "offset" and "zoned".
disambiguate= is non-optional for all relevant methods. The only
exception is the constructor, which defaults to "raise".
Rationale: This makes it explicit how ambiguous and non-existent times are handled.
Removed weakref support.
Rationale: The overhead of weakrefs was too high for such primitive objects, and the use case was not clear.
Weekdays are now an enum instead of an integer.
Rationale: Enums are more descriptive and less error-prone, especially since ISO weekdays start at 1 and Python weekdays at 0.
Calendar units in Date[Time]Delta can now only be retrieved
together. For example, there is no delta.months or delta.days
anymore, delta.in_months_days() should be used in this case.
Rationale: This safeguards against mistakes like
(date1 - date2).days which would only return the days component of
the delta, excluding months. Having to call in_months_days() is more
explicit that both parts are needed.
Units in delta cannot be different signs anymore (after normalization).
Rationale: The use case for mixed sign deltas (e.g. 2 months and -15 days) is unclear, and having a consistent sign makes it easier to reason about. It also aligns with the most well-known version of the ISO format.
Calendar units are normalized, but only in so far as they can be converted strictly. For example, 1 year is always equal to 12 months, but 1 month isn't equal to a fixed number of days. Refer to the delta docs for more information.
Rationale: This is more in line with TimeDelta which also
normalizes.
Renamed AmbiguousTime to RepeatedTime.
Rationale: The new name is more descriptive for repeated times occurring twice due to DST. It also clarifies the difference between "repeated" times and "ambiguous" times (which can also refer to non-existent times).
Dropped Python 3.8 support
Rationale: Rust extension relies on C API features added in Python 3.9. Python 3.8 will be EOL later this year.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fix LocalSystemDateTime.now() not setting the correct offset
Fix LocalSystemDateTime.now() not setting the correct offset (#104)
Fix handling of -0000 offset in RFC2822 format, which was not according to the standard. NaiveDateTime can now no longer be created from this format.
Breaking changes
-0000 offset in RFC2822 format, which was not according to the standard. NaiveDateTime can now no longer be created from this format.DateDelta canonical format now uses P prefix.Improved
Date.from_canonical_format method.NaiveDateTime.assume_offset now also accepts integers as hour offsets.A big release with the main feature being the addition of date/time deltas. I've also tried to bundle as many small breaking changes as possible into…
A big release with the main feature being the addition of date/time deltas. I've also tried to bundle as many small breaking changes as possible into this release, to avoid having to do them in the future.
For the rationale behind each breaking change, see the full changelog
Breaking changes
LocalDateTime renamed to LocalSystemDateTime.LocalSystemDateTime no longer adjusts automatically to changes in the system timezone. Now, LocalSystemDateTime reflects the system timezone at the moment of instantiation. It can be updated explicitly.disambiguate= argument now also determines how non-existent times are handled.from_naive() removed in favor of methods on NaiveDateTime. For example, UTCDateTime.from_naive(n) becomes n.assume_utc().ZonedDateTime.disambiguated() to .is_ambiguous()..py property with .py_datetime() method.datetime object: tzinfo, weekday, and fold. date and time now return whenever.Date and whenever.Time objects..canonical_str() to .canonical_format().DoesntExistInZone to SkippedTime, Ambiguous to AmbiguousTime.min and max to MIN and MAX.Improved
disambiguation="compatible" option that matches the behavior of other languages and the RFC5545 standard.repr() of all types, use space separator instead of T.sep="T" or " " option to canonical_format()OffsetDateTime constructor and methods creating offset datetimes now accept integers as hour offsets.Date and Time classes for working with dates and times separately.A big release with the main feature being the addition of date/time deltas. I've also tried to bundle as many small breaking changes as possible into this release, to avoid having to do them in the future.
Breaking changes
LocalDateTime renamed to LocalSystemDateTime.
Rationale: The LocalDateTime name is used in other libraries for
naive datetimes, and the new name is more explicit.
LocalSystemDateTime no longer adjusts automatically to changes in
the system timezone. Now, LocalSystemDateTime reflects the system
timezone at the moment of instantiation. It can be updated explicitly.
Rationale: The old behavior was dependent on too many assumptions, and behaved unintuitively in some cases. It also made the class dependent on shared mutable state, which made it hard to reason about.
The disambiguate= argument now also determines how non-existent
times are handled.
Rationale: This makes it possible to handle both ambiguous and non-existent times gracefully and in a consistent way. This behavior is also more in line with the RFC5545 standard, and Temporal.
from_naive() removed in favor of methods on NaiveDateTime. For
example, UTCDateTime.from_naive(n) becomes n.assume_utc().
Rationale: It's shorter, and more explicit about assumptions.
Renamed ZonedDateTime.disambiguated() to .is_ambiguous().
Rationale: The new name distinguishes it from the disambiguate=
argument, which also affects non-existent times.
Replaced .py property with .py_datetime() method.
Rationale: Although it currently works fine as a property, this
may be changed in the future if the library no longer contains a
datetime internally.
Removed properties that simply delegated to the underlying datetime
object: tzinfo, weekday, and fold. date and time now return
whenever.Date and whenever.Time objects.
Rationale: Removing these properties makes it possible to create
improved versions. If needed, these properties can be accessed from
the underlying datetime object with .py_datetime().
Renamed .canonical_str() to .canonical_format().
Rationale: A more descriptive name.
Renamed DoesntExistInZone to SkippedTime, Ambiguous to
AmbiguousTime.
Rationale: The new names are shorter and more consistent.
Renamed min and max to MIN and MAX.
Rationale: Consistency with other uppercase class constants
Improved
disambiguation="compatible" option that matches the behavior
of other languages and the RFC5545 standard.repr() of all types, use space separator instead of
T.sep="T" or " " option to canonical_format()OffsetDateTime constructor and methods creating offset datetimes now
accept integers as hour offsets.Date and Time classes for working with dates and times
separately.Improved exception messages for ambiguous or non-existent times
Improved exception messages for ambiguous or non-existent times (#26)
💾 Add CPython-maintained tzdata package as Windows dependency
💾 Add CPython-maintained tzdata package as Windows dependency (#32)
🔓 Relax overly strict Python version constraint in package metadata
🔓 Relax overly strict Python version constraint in package metadata (#33)
📦 Fix packaging metadata issue involving README and CHANGELOG being installed in the wrong place
📦 Fix packaging metadata issue involving README and CHANGELOG being installed in the wrong place (#23)
Nothing published for this version
🥒 Change pickle format so that backwards-compatible unpickling is possible in the future.
Breaking changes
Added
strptime() to UTCDateTime, OffsetDateTime and NaiveDateTime.rfc2822()/from_rfc2822() to UTCDateTime, OffsetDateTime and NaiveDateTime.rfc3339()/from_rfc3339() to UTCDateTime and OffsetDateTimeImprovements to README, other docs
days() timedelta alias📐Disambiguation of local datetimes is now consistent with zoned datetimes, and is also run on replace().
Breaking changes
📐Disambiguation of local datetimes is now consistent with zoned datetimes, and is also run on replace().
👌Renamed:
from_str → from_canonical_strto_utc/offset/zoned/local → as_utc/offset/zoned/local.ZonedDateTime.zone → ZonedDateTime.tzAdded
Docs
The first feature-complete release 🚀
The first feature-complete release 🚀
OffsetDateTime, ZonedDateTime and LocalDateTimeOffsetDateTime, ZonedDateTime and LocalDateTimeRevert to pure Python implementation, as Rust extension disadvantages outweigh its advantages
NaiveDateTime🌐 Implement basic UTC-only DateTime
🌐 Implement basic UTC-only DateTime
Empty release with Rust extension
Empty release with Rust extension
- Dummy release
Dummy release
On this page
Changelog
Unreleased
0.10.5 (2026-08-07)
0.10.4 (2026-08-02)
0.10.3 (2026-07-17)
0.10.2 (2026-07-06)
0.10.1 (2026-07-03)
0.10.0 (2026-04-05)
0.9.5 (2026-01-11)
0.9.4 (2025-12-14)
0.9.3 (2025-10-16)
0.9.2 (2025-09-29)
0.9.1 (2025-09-28)
0.9.0 (2025-09-25)
0.8.9 (2025-09-21)
0.8.8 (2025-07-24)
0.8.7 (2025-07-18)
0.8.6 (2025-06-23)
0.8.5 (2025-06-09)
0.8.4 (2025-05-28)
0.8.3 (2025-05-22)
0.8.2 (2025-05-21)
0.8.1 (2025-05-21)
0.8.0 (2025-05-01)
0.7.3 (2025-03-19)
0.7.2 (2025-02-25)
0.7.1 (2025-02-24)
0.7.0 (2025-02-20)
0.6.17 (2025-01-30)
0.6.16 (2024-12-22)
0.6.15 (2024-12-11)
0.6.14 (2024-11-27)
0.6.13 (2024-11-17)
0.6.12 (2024-11-08)
0.6.11 (2024-11-04)
0.6.10 (2024-10-30)
0.6.9 (2024-09-12)
0.6.8 (2024-09-05)
0.6.7 (2024-08-06)
0.6.6 (2024-07-27)
0.6.5 (2024-07-27)
0.6.4 (2024-07-26)
0.6.3 (2024-07-13)
0.6.2 (2024-07-04)
0.6.1 (2024-07-04)
0.6.0 (2024-07-04)
0.5.1 (2024-04-02)
0.5.0 (2024-03-21)
0.4.0 (2024-03-13)
0.3.4 (2024-02-07)
0.3.3 (2024-02-04)
0.3.2 (2024-02-03)
0.3.1 (2024-02-01)
0.3.0 (2024-01-23)
0.2.1 (2024-01-20)
0.2.0 (2024-01-10)
0.1.0 (2023-12-20)
0.0.4 (2023-11-30)
0.0.3 (2023-11-16)
0.0.2 (2023-11-10)
0.0.1
Your coding agent can read these notes before it upgrades. Set up the MCP server →