ZonedDateTime¶
- final class whenever.ZonedDateTime(iso_string: str, /)[source]¶
- final class whenever.ZonedDateTime(py_dt: datetime, /)
- final class whenever.ZonedDateTime(
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- *,
- nanosecond: int = 0,
- tz: str,
- disambiguate: DisambiguateStr = 'compatible',
A datetime associated with a timezone from the IANA database.
This is the right type when you need both the exact moment and the local date/time at a specific location. Arithmetic is fully DST-aware: the offset is always kept in sync with the timezone rules.
>>> ZonedDateTime("2024-12-08T11[Europe/Paris]") ZonedDateTime("2024-12-08 11:00:00+01:00[Europe/Paris]") >>> # Explicitly resolve ambiguities during DST transitions >>> ZonedDateTime(2023, 10, 29, 1, 15, tz="Europe/London", disambiguate="earlier") ZonedDateTime("2023-10-29 01:15:00+01:00[Europe/London]") >>> # From a standard library datetime (must have a ZoneInfo tzinfo) >>> ZonedDateTime(datetime(2020, 8, 15, 23, 12, tzinfo=ZoneInfo("Europe/London"))) ZonedDateTime("2020-08-15 23:12:00+01:00[Europe/London]")
Convert to other types to discard timezone information:
>>> d = ZonedDateTime(2024, 7, 1, 12, tz="Europe/Amsterdam") >>> d.to_instant() Instant("2024-07-01 10:00:00Z") >>> d.to_plain() PlainDateTime("2024-07-01 12:00:00")
Important
To use this type properly, read more about ambiguity in timezones.
- classmethod from_py_datetime(d: datetime, /) _T¶
Create an instance from a
datetimeobject.Deprecated since version 0.10.0: Use the constructor instead (e.g.
Instant(d),ZonedDateTime(d), etc.)Note
The datetime is checked for validity, raising similar exceptions to the constructor.
ValueErroris raised if the datetime doesn’t have the correct tzinfo matching the class. For example,ZonedDateTimerequires aZoneInfotzinfo.Warning
No exceptions are raised if the datetime is ambiguous. Its
foldattribute is used to disambiguate.
- classmethod from_system_tz(
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- *,
- nanosecond: int = 0,
- disambiguate: DisambiguateStr = 'compatible',
Create an instance in the system timezone.
Equivalent to
ZonedDateTime(..., tz=<the system timezone>), except it also works for system timezones whose corresponding IANA timezone ID is unknown.>>> ZonedDateTime.from_system_tz(2020, 8, 15, hour=23, minute=12) ZonedDateTime("2020-08-15 23:12:00+02:00[Europe/Berlin]")
- classmethod from_timestamp(i: int | float, /, *, tz: str) ZonedDateTime[source]¶
Create an instance from a UNIX timestamp (in seconds).
The inverse of the
timestamp()method.
- classmethod from_timestamp_millis(i: int, /, *, tz: str) ZonedDateTime[source]¶
Create an instance from a UNIX timestamp (in milliseconds).
The inverse of the
timestamp_millis()method.
- classmethod from_timestamp_nanos(i: int, /, *, tz: str) ZonedDateTime[source]¶
Create an instance from a UNIX timestamp (in nanoseconds).
The inverse of the
timestamp_nanos()method.
- classmethod now(tz: str, /) ZonedDateTime[source]¶
Create an instance from the current time in the given timezone.
- classmethod now_in_system_tz() ZonedDateTime[source]¶
Create an instance from the current time in the system timezone.
Equivalent to
Instant.now().to_system_tz().
- classmethod parse(s: str, /, *, format: str, disambiguate: DisambiguateStr = 'compatible') ZonedDateTime[source]¶
Parse a zoned datetime from a custom pattern string.
The pattern must include a timezone ID field (
VV). An offset field (x/X) is optional but recommended for disambiguation during DST transitions. See Pattern format for details.Tip
If your input string doesn’t include a timezone ID, parse it with
PlainDateTime.parse()first, then convert usingassume_tz().>>> ZonedDateTime.parse( ... "2024-03-15 14:30+01:00[Europe/Paris]", ... format="YYYY-MM-DD hh:mmxxx'['VV']'", ... ) ZonedDateTime("2024-03-15 14:30:00+01:00[Europe/Paris]")
- classmethod parse_iso(s: str, /) ZonedDateTime[source]¶
Parse from the popular ISO format
YYYY-MM-DDTHH:MM:SS±HH:MM[TZ_ID]The inverse of the
format_iso()method.>>> ZonedDateTime.parse_iso("2020-08-15T23:12:00+01:00[Europe/London]") ZonedDateTime("2020-08-15 23:12:00+01:00[Europe/London]")
Important
The timezone ID is a recent extension to the ISO 8601 format (RFC 9557). Although it is gaining popularity, it is not yet widely supported.
- __add__(
- delta: TimeDelta | DateDelta | DateTimeDelta,
Add an amount of time, accounting for timezone changes (e.g. DST).
See the docs for more information.
- __eq__(other: object) bool¶
Check if two datetimes represent at the same moment in time
a == bis equivalent toa.to_instant() == b.to_instant()Note
If you want to exactly compare the values on their values instead, use
exact_eq().>>> Instant.from_utc(2020, 8, 15, hour=23) == Instant.from_utc(2020, 8, 15, hour=23) True >>> OffsetDateTime(2020, 8, 15, hour=23, offset=1) == ( ... ZonedDateTime(2020, 8, 15, hour=18, tz="America/New_York") ... ) True
- __format__(spec: str, /) str[source]¶
Default object formatter.
Return str(self) if format_spec is empty. Raise TypeError otherwise.
- __ge__(other: Instant | OffsetDateTime | ZonedDateTime) bool¶
Compare two datetimes by when they occur in time
a >= bis equivalent toa.to_instant() >= b.to_instant()>>> OffsetDateTime(2020, 8, 15, hour=19, offset=-8) >= ( ... ZoneDateTime(2020, 8, 15, hour=20, tz="Europe/Amsterdam") ... ) True
- __gt__(other: Instant | OffsetDateTime | ZonedDateTime) bool¶
Compare two datetimes by when they occur in time
a > bis equivalent toa.to_instant() > b.to_instant()>>> OffsetDateTime(2020, 8, 15, hour=19, offset=-8) > ( ... ZoneDateTime(2020, 8, 15, hour=20, tz="Europe/Amsterdam") ... ) True
- __le__(other: Instant | OffsetDateTime | ZonedDateTime) bool¶
Compare two datetimes by when they occur in time
a <= bis equivalent toa.to_instant() <= b.to_instant()>>> OffsetDateTime(2020, 8, 15, hour=23, offset=8) <= ( ... ZoneDateTime(2020, 8, 15, hour=20, tz="Europe/Amsterdam") ... ) True
- __lt__(other: Instant | OffsetDateTime | ZonedDateTime) bool¶
Compare two datetimes by when they occur in time
a < bis equivalent toa.to_instant() < b.to_instant()>>> OffsetDateTime(2020, 8, 15, hour=23, offset=8) < ( ... ZoneDateTime(2020, 8, 15, hour=20, tz="Europe/Amsterdam") ... ) True
- __sub__(
- other: Instant | OffsetDateTime | ZonedDateTime,
- __sub__(other: TimeDelta) ZonedDateTime
Subtract another datetime or duration.
See the docs for more information.
- add(
- d: DateTimeDelta | TimeDelta | DateDelta | ItemizedDelta | ItemizedDateDelta,
- /,
- *,
- disambiguate: DisambiguateStr = ...,
- add(
- *,
- years: int = ...,
- months: int = ...,
- weeks: int = ...,
- days: int = ...,
- hours: float = ...,
- minutes: float = ...,
- seconds: float = ...,
- milliseconds: float = ...,
- microseconds: float = ...,
- nanoseconds: int = ...,
- disambiguate: DisambiguateStr = ...,
Return a new
ZonedDateTimeshifted by the given time amountsImportant
Shifting by calendar units (e.g. months, weeks) may result in an ambiguous time (e.g. during a DST transition). Therefore, when adding calendar units, it’s recommended to specify how to handle such a situation using the
disambiguateargument.See the documentation for more information.
- date() Date¶
The date part of the datetime
>>> d = PlaineDateTime("2020-01-02 03:04:05") >>> d.date() Date("2021-01-02")
To perform the inverse, use
Date.at()and a method likeassume_utc()orassume_tz():>>> date.at(time).assume_tz("Europe/London") ZonedDateTime("2021-01-02T03:04:05+00:00[Europe/London]")
- day_length() TimeDelta[source]¶
The duration between the start of the current day and the next. This is usually 24 hours, but may be different due to timezone transitions.
>>> ZonedDateTime(2020, 8, 15, tz="Europe/London").day_length() TimeDelta(24:00:00) >>> ZonedDateTime(2023, 10, 29, tz="Europe/Amsterdam").day_length() TimeDelta(25:00:00)
- difference(
- other: Instant | OffsetDateTime | ZonedDateTime,
- /,
Calculate the difference between two instants in time.
Deprecated since version 0.10.0: Use the subtraction operator instead
- dst_offset() TimeDelta[source]¶
The DST offset (adjustment) as a
TimeDelta.>>> ZonedDateTime(2020, 8, 15, tz="Europe/London").dst_offset() TimeDelta("PT1h") >>> ZonedDateTime(2020, 1, 15, tz="Europe/London").dst_offset() TimeDelta("PT0s")
This value is
TimeDelta.ZEROwhen DST is not active:>>> if zoned_dt.dst_offset(): ... print("DST is active")
Note
Some timezones have unusual DST rules. For example, Europe/Dublin defines its standard time as IST (UTC+1) and uses “negative DST” in winter. In such cases, this method returns a negative value during winter.
- exact_eq(other: ZonedDateTime, /) bool[source]¶
Compare objects by their values (instead of whether they represent the same instant). Different types are never equal.
>>> a = OffsetDateTime(2020, 8, 15, hour=12, offset=1) >>> b = OffsetDateTime(2020, 8, 15, hour=13, offset=2) >>> a == b True # equivalent instants >>> a.exact_eq(b) False # different values (hour and offset) >>> a.exact_eq(Instant.now()) TypeError # different types
Note
If
a.exact_eq(b)is true, thena == bis also true, but the converse is not necessarily true.
- format(pattern: str, /) str[source]¶
Format as a custom pattern string.
See Pattern format for details.
>>> ZonedDateTime(2024, 3, 15, 14, 30, tz="Europe/Paris").format( ... "YYYY-MM-DD hh:mmxxx'['VV']'" ... ) '2024-03-15 14:30+01:00[Europe/Paris]'
- format_iso(
- *,
- unit: Literal['hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond', 'auto'] = 'auto',
- basic: bool = False,
- sep: Literal['T', ' '] = 'T',
- tz: Literal['always', 'never', 'auto'] = 'always',
Convert to the popular ISO format
YYYY-MM-DDTHH:MM:SS±HH:MM[TZ_ID].The inverse of the
parse_iso()method.>>> zdt = ZonedDateTime(2020, 8, 15, hour=23, minute=12, tz="Europe/London") >>> zdt.format_iso(unit="minute", basic=True) "20200815T2312+0100[Europe/London]"
- Parameters:
unit – The smallest unit to include in the output.
"auto"is the same as"nanosecond", except that trailing zeroes are omitted from the time part.basic – Whether to use the basic ISO format (without separators) instead of the extended one.
sep – The separator between the date and time parts.
tz – Whether to include the timezone ID in the output.
"always"(default) raises an error if the timezone ID is not available (in practice, this should only happen for some system timezones without a corresponding IANA timezone ID)."auto"includes the ID if available, and omits it otherwise."never"always omits the ID.
Important
The timezone ID is a recent extension to the ISO 8601 format (RFC 9557). Although it is gaining popularity, it is not yet widely supported by ISO 8601 parsers.
- is_ambiguous() bool[source]¶
Whether the date and time-of-day are ambiguous, e.g. due to a DST transition.
>>> ZonedDateTime(2020, 8, 15, 23, tz="Europe/London").is_ambiguous() False >>> ZonedDateTime(2023, 10, 29, 2, 15, tz="Europe/Amsterdam").is_ambiguous() True
- py_datetime() datetime¶
Convert to a standard library
datetimeDeprecated since version 0.10.0: Use
to_stdlib()instead.
- replace(
- year: int = ...,
- month: int = ...,
- day: int = ...,
- hour: int = ...,
- minute: int = ...,
- second: int = ...,
- *,
- nanosecond: int = ...,
- tz: str = ...,
- disambiguate: DisambiguateStr = ...,
Construct a new instance with the given fields replaced.
Important
Replacing fields of a ZonedDateTime may result in an ambiguous time (e.g. during a DST transition). Therefore, it’s recommended to specify how to handle such a situation using the
disambiguateargument.By default, if the tz remains the same, the offset is used to disambiguate if possible, falling back to the “compatible” strategy if needed.
See the documentation for more information.
- replace_date(date: Date, /, disambiguate: DisambiguateStr = ...) ZonedDateTime[source]¶
Construct a new instance with the date replaced.
See the
replace()method for more information.
- replace_time(time: Time, /, disambiguate: DisambiguateStr = ...) ZonedDateTime[source]¶
Construct a new instance with the time replaced.
See the
replace()method for more information.
- round(
- unit: Literal['day', 'hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond'] | TimeDelta = 'second',
- /,
- *,
- increment: int = 1,
- mode: RoundModeStr = 'half_even',
Round the datetime to the specified unit and increment, or to a multiple of a
TimeDelta. Different rounding modes are available.>>> d = ZonedDateTime("2020-08-15 23:24:18+02:00[Europe/Paris]") >>> d.round("day") ZonedDateTime("2020-08-16 00:00:00+02:00[Europe/Paris]") >>> d.round("minute", increment=15, mode="floor") ZonedDateTime("2020-08-15 23:15:00+02:00[Europe/Paris]")
Notes
In the rare case that rounding results in a repeated time, the offset is preserved if possible. Otherwise, ambiguity is resolved according to the “compatible” strategy.
Rounding in “day” mode may be affected by DST transitions. i.e. on 23-hour days, 11:31 AM is rounded up.
This method has similar behavior to the
round()method of Temporal objects in JavaScript.
- since(b: ZonedDateTime, /, *, total: DeltaUnitStr) float[source]¶
- since(
- b: ZonedDateTime,
- /,
- *,
- in_units: Sequence[TypeAliasForwardRef('DeltaUnitStr')],
- round_mode: RoundModeStr = ...,
- round_increment: int = ...,
Calculate the duration since another ZonedDateTime, in terms of the specified units.
>>> d1 = ZonedDateTime("2020-08-15T23:12:00+01:00[Europe/London]") >>> d2 = ZonedDateTime("2020-08-14T22:00:00+09:00[Asia/Tokyo]") >>> d1.since(d2, in_units=["hours", "minutes"], ... round_increment=15, ... round_mode="ceil") ItemizedDelta("PT33h15m")
When calculating calendar units (years, months, weeks, days), both datetimes must have the same timezone.
- start_of_day() ZonedDateTime[source]¶
The start of the current calendar day.
This is almost always at midnight the same day, but may be different for timezones which transition at—and thus skip over—midnight.
- subtract(
- d: DateTimeDelta | TimeDelta | DateDelta | ItemizedDelta | ItemizedDateDelta,
- /,
- *,
- disambiguate: DisambiguateStr = ...,
- subtract(
- *,
- years: int = ...,
- months: int = ...,
- weeks: int = ...,
- days: int = ...,
- hours: float = ...,
- minutes: float = ...,
- seconds: float = ...,
- milliseconds: float = ...,
- microseconds: float = ...,
- nanoseconds: int = ...,
- disambiguate: DisambiguateStr = ...,
The inverse of the
add()method. Seeadd()for more information.
- time() Time¶
The time-of-day part of the datetime
>>> d = ZonedDateTime("2021-01-02T03:04:05+01:00[Europe/Paris])" >>> d.time() Time(03:04:05)
To perform the inverse, use
Time.on()and a method likeassume_utc()orassume_tz():>>> time.on(date).assume_tz("Europe/Paris") ZonedDateTime("2021-01-02T03:04:05+01:00[Europe/Paris]")
- timestamp() int¶
The UNIX timestamp for this datetime. Inverse of
from_timestamp().>>> Instant.from_utc(1970, 1, 1).timestamp() 0 >>> ts = 1_123_000_000 >>> Instant.from_timestamp(ts).timestamp() == ts True
Note
In contrast to the standard library, this method always returns an integer, not a float. This is because floating point timestamps are not precise enough to represent all instants to nanosecond precision. This decision is consistent with other modern date-time libraries.
- timestamp_millis() int¶
Like
timestamp(), but with millisecond precision.
- timestamp_nanos() int¶
Like
timestamp(), but with nanosecond precision.
- to_fixed_offset(offset: int | TimeDelta = ..., /) OffsetDateTime¶
Convert to an OffsetDateTime that represents the same moment in time.
If not offset is given, the offset is taken from the original datetime.
- to_instant() Instant¶
Get the underlying instant in time
>>> d = ZonedDateTime(2020, 8, 15, hour=23, tz="Europe/Amsterdam") >>> d.to_instant() Instant("2020-08-15 21:00:00Z")
- to_plain() PlainDateTime¶
Get the underlying date and time without offset or timezone
As an inverse,
PlainDateTimehas methodsassume_utc(),assume_fixed_offset(),assume_tz(), andassume_system_tz().
- to_stdlib() datetime[source]¶
Convert to a standard library
datetimeNote
Nanoseconds are truncated to microseconds. If you wish to customize the rounding behavior, use the
round()method first.For
ZonedDateTimelinked to a system timezone without a IANA timezone ID, the returned Python datetime will have a fixed offset (timezonetzinfo)
- to_system_tz() ZonedDateTime¶
Convert to a ZonedDateTime of the system’s timezone.
- to_tz(tz: str, /) ZonedDateTime[source]¶
Convert to a ZonedDateTime that represents the same moment in time.
- Raises:
TimeZoneNotFoundError – If the timezone ID is not found in the timezone database.
- tz_abbrev() str[source]¶
The timezone abbreviation (e.g.
"EST","CEST").>>> ZonedDateTime(2020, 8, 15, tz="Europe/London").tz_abbrev() 'BST' >>> ZonedDateTime(2020, 1, 15, tz="Europe/London").tz_abbrev() 'GMT'
Warning
The abbreviation is often ambiguous and may not be unique, but it is commonly used in human-readable formats. Use the timezone ID (e.g.
"Europe/London") for unambiguous identification of timezones.
- until(b: ZonedDateTime, /, *, total: DeltaUnitStr) float[source]¶
- until(
- b: ZonedDateTime,
- /,
- *,
- in_units: Sequence[TypeAliasForwardRef('DeltaUnitStr')],
- round_mode: RoundModeStr = ...,
- round_increment: int = ...,
Inverse of the
since()method. Seesince()for more information.