Releases: ariebovenberg/whenever
0.9.3
0.8.10
Backport of timezone fixes from 0.9.x to 0.8.x that affected some timezones far into the future or past
0.9.2
0.9.1
Added ZonedDateTime.now_in_system_tz() and ZonedDateTime.from_system_tz() as convenience methods to ease migration away from SystemDateTime.
0.9.0
Breaking Changes
-
SystemDateTimehas been removed and merged intoZonedDateTimeTo create a more consistent and intuitive API, the SystemDateTime class
has been removed. Its functionality is now fully integrated into an
enhanced ZonedDateTime, which now serves as the single, canonical class
for all timezone-aware datetimes, including those based on the system's
local timezone.Rationale:
The
SystemDateTimeclass, while useful, created several challenges that
compromised the library's consistency and predictability:- Inconsistent Behavior: Methods like
replace()andadd()on a
SystemDateTimeinstance would use the current system timezone definition,
not necessarily the one that was active when the instance was created.
This could lead to subtle and unpredictable bugs if the system timezone
changed during the program's execution. - API Division: Despite having nearly identical interfaces, SystemDateTime
andZonedDateTimewere not interchangeable. A function expecting a
ZonedDateTimecould not accept aSystemDateTime, forcing users to write
more complex code withUniontype hints. - Maintenance Overhead: Maintaining two parallel APIs for timezone-aware
datetimes led to significant code duplication and a higher maintenance
burden.
This change unifies the API by integrating system timezone support
directly intoZonedDateTime, providing a single, consistent way to handle
all timezone-aware datetimes. The original use cases forSystemDateTime
are fully supported by the improvedZonedDateTime.This new, unified approach also provides two major benefits:
- Performance: Operations on a
ZonedDateTimerepresenting a system time are
now orders of magnitude faster than they were on the oldSystemDateTime. - Cross-Platform Consistency: The new
whenever.reset_system_tz()function
provides a reliable, cross-platform way to update the library's view of
the system timezone, replacing the previous reliance on the Unix-only
time.tzset().
Migration:
- Replace all
SystemDateTimewithZonedDateTimein all type hints. - Replace
SystemDateTime.now()withZonedDateTime.now_in_system_tz()(whenever >=0.9.1)
orInstant.now().to_system_tz()(whenever <0.9.1) - Replace
SystemDateTime(...)constructor calls withZonedDateTime.from_system_tz(...)
(whenever >=0.9.1) orPlainDateTime(...).assume_system_tz()(whenever <0.9.1) - Check calls to
.to_system_tz()and.assume_system_tz(): these
methods now return aZonedDateTimeinstance. In most cases,
no code change is needed. - Instead of
time.tzset(), usewhenever.reset_system_tz()to
update the system timezone (forwheneveronly).
- Inconsistent Behavior: Methods like
-
ZonedDateTimeinstances with a system timezone may in rare cases
not have a known IANA timezone ID (thetzproperty will beNone).
This is an unfortunate limitation of some platforms.
SuchZonedDateTimeinstances can still be used for all operations,
and will account for DST correctly. However, these instances cannot be pickled,
and their ISO format will not be able to include the timezone ID.Rationale: This is an necessary compromise for broad system timezone support.
Other libraries (and Python's ownzoneinfo) have similar limitations. -
The
repr()of all classes now includes quotes: e.g.Date("2023-10-05").
Since all constructors now also accept ISO 8601 strings, therepr()output
can be directly used as input and thuseval(repr(obj)) == obj.Rationale: This makes the types easier to use in interactive sessions
and tests. A round-trippablerepr()is also a common expectation for primitive types. -
Renamed
[format|parse]_common_isomethods to[format|parse]_iso.
The old methods are still available (but deprecated) to ease the transition.Rationale: The "common" qualifier is no longer necessary because
these methods have been expanded to handle a wider range of ISO 8601 formats. -
Removed the deprecated
local()methods (useto_plain()instead). -
Removed the deprecated
instant()method (useto_instant()instead).
Improved
-
All classes can now be directly instantiated from an ISO 8601 formatted string
passed as a sole argument. For example,Date("2023-10-05")is equivalent to
Date(2023, 10, 5)(which is still supported, of course). -
Customizable ISO 8601 Formatting: The
format_iso()methods now accept
parameters to customize the output. You can control the separator
(e.g.,'T'or' '), the smallest unit (fromhourtonanosecond),
and toggle the "basic" (compact) or "extended" format.Also, the formatting is now significantly faster. Up to 5x faster for
ZonedDateTime, which is now 10x faster than the standard library'sdatetime.isoformat().
Fixed
- Resolved a memory leak in the Rust extension where timezone objects that
were no longer in use were not properly evicted from the cache. - Fixed a rare bug in determining the UTC offset for times far in the future
- Fixed
PlainDateTimeconstructor raisingTypeErrorinstead of
ValueErrorwhen passed invalid parameters. - TZ IDs starting with a
./are now properly rejected. Other path traversal
attempts were already handled correctly. - More robust timezone refcounting in the Rust extension, preventing crashes
in rare cases (#270) - Panics in Rust extension no longer crash the interpreter, raise
RuntimeErrorinstead
0.9.0rc1
A small addition to 0.9.0rc0 that fixes some bugs, and makes the transition from format/parse_common_iso to format/parse_iso easier by deprecating (not removing) the old names. Full list of changes since 0.8.9 below:
Breaking Changes
-
SystemDateTimehas been removed and its functionality is now integrated intoZonedDateTime.
Migration:SystemDateTime.now()can be replaced withInstant.now().to_system_tz().to_system_tz()andassume_system_tz()now return aZonedDateTimeinstead of aSystemDateTime.
Rationale: The
SystemDateTimeclass was an awkward corner of the API,
creating inconsistencies and overlapping withZonedDateTime.
This change unifies the API, providing a single, consistent way to handle
all timezone-aware datetimes. The original use cases are fully supported
by the improvedZonedDateTime. -
ZonedDateTimeinstances with a system timezone may in rare cases
not have a known IANA timezone ID (thetzproperty will beNone).
This is an unfortunate limitation of some platforms.
SuchZonedDateTimeinstances can still be used for all operations,
and will account for DST correctly. However, these instances cannot be pickled,
and their ISO format will not be able to include the timezone ID.Rationale: This is an necessary compromise for broad system timezone support.
Other libraries (and Python's ownzoneinfo) have similar limitations. -
All classes can now be directly instantiated from an ISO 8601 formatted string
passed as a sole argument. For example,Date("2023-10-05")is equivalent to
Date(2023, 10, 5)(which is still supported, of course).
Therepr()of all classes now includes quotes, so that the output
can be directly used as input and thuseval(repr(obj)) == obj.Rationale: This makes the types a lot easier to use in interactive sessions
and tests. It also makesrepr()round-trippable, which is a common
expectation for primitive types. -
Renamed
[format|parse]_common_isomethods to[format|parse]_iso.
The old methods are still available (but deprecated) to ease the transition.Rationale: The "common" qualifier is no longer necessary because
these methods have been expanded to handle a wider range of ISO 8601 formats. -
Removed the deprecated
local()methods (useto_plain()instead). -
Removed the deprecated
instant()method (useto_instant()instead).
Improved
-
Customizable ISO 8601 Formatting: The
format_iso()methods now accept
parameters to customize the output. You can control theseparator
(e.g.,'T'or' '), the smallestunit(fromhourtonanosecond),
and toggle thebasic(compact) orextendedformat.Also, the formatting is now significantly faster. Up to 5x faster for
ZonedDateTime, which is now 10x faster than the standard library'sdatetime.isoformat().
Fixed
- Resolved a memory leak in the Rust extension where timezone objects that
were no longer in use were not properly evicted from the cache. - Fixed a rare bug in determining the UTC offset for times far in the future
- Fixed
PlainDateTimeconstructor raisingTypeErrorinstead of
ValueErrorwhen passed invalid parameters. - TZ IDs starting with a
./are now properly rejected. Other path traversal
attempts were already handled correctly. - More robust timezone refcounting in the Rust extension, preventing crashes
in rare cases (#270) - Panics in Rust extension no longer crash the interpreter, raise
RuntimeErrorinstead
0.9.0rc0
First release candidate for the next big release: 0.9.0.
Breaking Changes
-
SystemDateTimehas been removed and its functionality is now integrated intoZonedDateTime.
Migration:SystemDateTime.now()can be replaced withInstant.now().to_system_tz().to_system_tz()andassume_system_tz()now return aZonedDateTimeinstead of aSystemDateTime.
Rationale: The
SystemDateTimeclass was an awkward corner of the API,
creating inconsistencies and overlapping withZonedDateTime.
This change unifies the API, providing a single, consistent way to handle
all timezone-aware datetimes. The original use cases are fully supported
by the improvedZonedDateTime. -
All classes can now be directly instantiated from an ISO 8601 formatted string
passed as a sole argument. For example,Date("2023-10-05")is equivalent to
Date(2023, 10, 5)(which is still supported, of course).
Therepr()of all classes now includes quotes, so that the output
can be directly used as input and thuseval(repr(obj)) == obj.Rationale: This makes the types a lot easier to use in interactive sessions
and tests. It also makesrepr()round-trippable, which is a common
expectation for primitive types. -
Renamed
[format|parse]_common_isomethods to[format|parse]_iso.Rationale: The "common" qualifier is no longer necessary because
these methods have been expanded to handle a wider range of ISO 8601 formats. -
Remove the deprecated
local()methods (useto_plain()instead). -
Remove the deprecated
instant()method (useto_instant()instead).
Improved
-
Customizable ISO 8601 Formatting: The
format_iso()methods now accept
parameters to customize the output. You can control theseparator
(e.g.,'T'or' '), the smallestunit(fromhourtonanosecond),
and toggle thebasic(compact) orextendedformat.Also, the formatting is now significantly faster. Up to 5x faster for
ZonedDateTime, which is now 10x faster than the standard library'sdatetime.isoformat().
Fixed
- Resolved a memory leak in the Rust extension where timezone objects that
were no longer in use were not properly evicted from the cache. - Fixed a rare bug in determining the UTC offset for times far in the future
- Fixed
PlainDateTimeconstructor raisingTypeErrorinstead of
ValueErrorwhen passed invalid parameters. - TZ IDs starting with a
./are now properly rejected. Other path traversal
attempts were already handled correctly. - More robust timezone refcounting in the Rust extension, preventing crashes
in rare cases (#270)