A big release with several breaking changes and improvements. Highlights are the new delta API, customizable string formatting and parsing, and since()/until() methods for calculating differences between datetimes. See the full list below.
Breaking changes
-
DateTimeDeltaandDateDeltahave been replaced byItemizedDeltaandItemizedDateDelta, respectively. The helper functions for creating calendar deltas (years(),months(),weeks(),days()) have also been deprecated.The new deltas are fully un-normalized, meaning "90 minutes" and "1 hour and 30 minutes" are distinct values. They implement the
Mappinginterface and support a rich set of operations includingadd(),subtract(),total(),in_units(),replace(), andsign().Rationale: the "partially" normalized approach was confusing to users. A fully un-normalized approach also better fits the new API for calculating deltas between datetimes. This approach is also more consistent with other libraries, and allows for more control over formatting and parsing of deltas.
Migration:
- Replace
DateDelta(...)withItemizedDateDelta(...). - Replace
DateTimeDelta(...)withItemizedDelta(...). - Replace
years(),months(),weeks(),days()helper functions withItemizedDateDelta(years=...), etc. Or, if passing to a datetime method, use keyword arguments directly (e.g.dt.add(years=1, months=2)). - Replace
.in_months_days()and.in_months_days_secs_nanos()with.in_units(['months', 'days'])and.in_units(['months', 'days', 'seconds', 'nanoseconds']), respectively. - The
Date+/-operators withDateDeltaare deprecated; useadd()/subtract()instead. - The
Date-operator between two dates is deprecated; usesince()orsubtract()instead.
- Replace
-
The
ignore_dstparameter (which was used to enable DST-unsafe operations) has been replaced by a warnings mechanism that allows users to suppress or escalate DST-related warnings using per-method keyword arguments or Python's standard warning filters.Rationale: The
ignore_dstparameter was a source of confusion, and made theOffsetDateTimeAPIs less compatible.Migration:
- Replace
ignore_dst=Truewith the appropriate keyword argument:OffsetDateTimemethods:stale_offset_ok=TruePlainDateTimemethods:naive_arithmetic_ok=TrueTimeDeltamethods:days_assumed_24h_ok=True
- Alternatively, use Python's
warnings.filterwarnings()to suppressStaleOffsetWarning,NaiveArithmeticWarning, orDaysAssumed24HoursWarning. ignore_dstis still accepted (with a deprecation warning) and will be removed in a future release.
- Replace
-
Behavior of an edge case is changed: disambiguation of non-existent times as a result of calendar arithmetic (or
replace()) no longer tries to reuse the previous offset. This change also fixes a rare bug in case a timezone transition skips an entire day (like the Samoa timezone did in 2011) (#252).Rationale: Unlike the case of repeated times, reusing the previous offset for non-existent times doesn't have the advantage of preventing unexpected jumps in time. The new behavior is consistent with other libraries.
-
Dropped Python 3.9 support
Rationale: Python 3.9 is EOL since October 2025. Python 3.9 only accounts for less than 0.1% of downloads.
-
Removed
format_common_iso()andparse_common_iso()methods. Useformat_iso()andparse_iso()instead. These have been deprecated since 0.9.0. -
The
round()methods are stricter about keyword-only and positional-only arguments.
Deprecated
TimeDelta.in_hours(),.in_minutes(),.in_seconds(),.in_milliseconds(),.in_microseconds(),.in_nanoseconds(),.in_days_of_24h(), and.in_hrs_mins_secs_nanos(). Usetotal()orin_units()instead.Date.days_since()andDate.days_until(). Usesince()anduntil()withtotal='days'instead.py_date(),py_time(),py_datetime(), andpy_timedelta(). Use the newto_stdlib()method instead, which provides a consistent name across all types.from_py_date(),from_py_time(),from_py_datetime(), andfrom_py_timedelta(). Use the constructor directly instead (e.g.Date(datetime.date(...))).parse_strptime()methods onOffsetDateTimeandPlainDateTime. Use the newparse()method instead.ZonedDateTime.start_of_day(). Usestart_of("day")instead.
Added or improved
- Parsing methods now accept leap seconds (second value of
60), normalizing them to59. This applies to ISO 8601, RFC 2822, and custom format strings. - New
ZonedDateTime.next_transition()andZonedDateTime.prev_transition()methods for finding the next or previous UTC offset transition (e.g. DST change) relative to the current datetime. ReturnsNonefor timezones without transitions (e.g. UTC or fixed-offset). - New
since()anduntil()methods onDate,ZonedDateTime,OffsetDateTime, andPlainDateTimefor calculating the difference between two values in terms of specific calendar/time units. - New
format()andparse()methods onDate,Time,PlainDateTime,OffsetDateTime,ZonedDateTime, andInstantfor custom format/parse patterns. Example:Date(2024, 3, 15).format("YYYY/MM/DD")→"2024/03/15". These types also support__format__, enabling f-string usage:f"{date:YYYY/MM/DD}". See the pattern format documentation for details. - New
TimeDelta.total()andTimeDelta.in_units()methods for converting a time delta into specific units. - New
TimeDelta.add()andTimeDelta.subtract()methods. The operators+and-were supported already, but these methods make it easier for simple operations, as well as making the API more consistent with other classes. - New
OffsetDateTime.assume_tz()method for associating an offset datetime with a timezone. round()methods now support four new rounding modes:trunc,expand,half_trunc, andhalf_expand. They also now support larger and irregular values forincrement.TimeDelta.round()now supports days and weeks as rounding units (with a warning about 24-hour days).- All types that have a Python standard library equivalent now also accept these objects in the constructor. For example:
Date(datetime.date(2024, 1, 1)). - New
ZonedDateTime.dst_offset()andZonedDateTime.tz_abbrev()methods for querying timezone metadata (DST offset adjustment and timezone abbreviation). - Warning classes (
StaleOffsetWarning,NaiveArithmeticWarning,DaysAssumed24HoursWarning) and corresponding per-method keyword arguments (stale_offset_ok,naive_arithmetic_ok,days_assumed_24h_ok) for fine-grained control over DST-related warnings. - New
IsoWeekDatetype for representing ISO calendar week dates. Construct withIsoWeekDate(year, week, weekday)or parse withIsoWeekDate("2024-W01-1"). Convert fromDatewithDate.iso_week_date(). - New calendar methods on
Date:day_of_year(),days_in_month(),days_in_year(),in_leap_year(),next_day(),prev_day(),nth_weekday_of_month(),nth_weekday(),start_of(),end_of(). - New calendar methods on
PlainDateTime,ZonedDateTime,OffsetDateTime:day_of_year(),days_in_month(),days_in_year(),in_leap_year(),start_of(),end_of(). - New calendar methods on
YearMonth:days_in_month(),days_in_year(),in_leap_year(). - A huge revamp and expansion of the documentation. The structure and navigability of API reference and overview pages has been improved. Several new pages have been added, including:
- An explanation of the fundamental concepts of time
- An overview of Python's datetime pitfalls
- Explanation of the rounding API
YearMonth,MonthDay,Weekday, andIsoWeekDateare now implemented in pure Python always, reducing the compiled extension size.Instant.add/subtractnow support passingTimeDeltainstances. Instead of rejectingdaysandweeks, these methods now emit a warning about DST issues, consistent with the behavior ofTimeDelta.- SQLAlchemy support, see https://pypi.org/project/whenever-sqlalchemy/
Fixed
- (Pure-Python version) Fixed incorrect behavior of
<operator betweenTimeinstances if nanoseconds are involved.