OffsetDateTime

final class whenever.OffsetDateTime(iso_string: str, /)[source]
final class whenever.OffsetDateTime(py_dt: datetime, /)
final class whenever.OffsetDateTime(
year: int,
month: int,
day: int,
hour: int = 0,
minute: int = 0,
second: int = 0,
*,
nanosecond: int = 0,
offset: int | TimeDelta,
)

A datetime with a fixed UTC offset.

Useful for representing a moment in time together with the local date and time as observed at that offset. The offset is fixed and does not account for DST transitions.

>>> # Midnight in Salt Lake City
>>> OffsetDateTime(2023, 4, 21, offset=-6)
OffsetDateTime("2023-04-21 00:00:00-06:00")

Can also be constructed from an ISO 8601 string or a standard library datetime:

>>> OffsetDateTime("2023-04-21T00:00:00-06:00")
OffsetDateTime("2023-04-21 00:00:00-06:00")

Convert to ZonedDateTime for DST-aware operations:

>>> dt = OffsetDateTime(2023, 4, 21, offset=-6)
>>> dt.assume_tz("US/Mountain")
ZonedDateTime("2023-04-21 00:00:00-06:00[US/Mountain]")

Important

Operations that shift, round, or replace fields of this type keep the original offset, which may become stale if DST rules have changed. Use assume_tz() to convert to a ZonedDateTime first if you need DST-aware arithmetic.

classmethod from_py_datetime(d: datetime, /) _T

Create an instance from a datetime object.

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. ValueError is raised if the datetime doesn’t have the correct tzinfo matching the class. For example, ZonedDateTime requires a ZoneInfo tzinfo.

Warning

No exceptions are raised if the datetime is ambiguous. Its fold attribute is used to disambiguate.

classmethod from_timestamp(
i: int | float,
/,
*,
offset: int | TimeDelta,
ignore_dst: bool = ...,
) OffsetDateTime[source]

Create an instance from a UNIX timestamp (in seconds).

The inverse of the timestamp() method.

Warning

Converting a UNIX timestamp to OffsetDateTime with a fixed UTC offset may produce an incorrect result: you can’t know from the offset alone whether DST applies to this timestamp. Use ZonedDateTime.from_timestamp(ts, tz='<tz>') if you know the timezone, or Instant.from_timestamp() for timezone-agnostic exact time. Suppress with ignore_potentially_stale_offset_warning().

classmethod from_timestamp_millis(
i: int,
/,
*,
offset: int | TimeDelta,
ignore_dst: bool = ...,
) OffsetDateTime[source]

Create an instance from a UNIX timestamp (in milliseconds).

The inverse of the timestamp_millis() method.

See from_timestamp() for more information.

classmethod from_timestamp_nanos(
i: int,
/,
*,
offset: int | TimeDelta,
ignore_dst: bool = ...,
) OffsetDateTime[source]

Create an instance from a UNIX timestamp (in nanoseconds).

The inverse of the timestamp_nanos() method.

See from_timestamp() for more information.

classmethod now(offset: int | TimeDelta, /, *, ignore_dst: bool = ...) OffsetDateTime[source]

Create an instance from the current time.

Warning

Getting the current time as an OffsetDateTime with a fixed UTC offset may be incorrect: the offset doesn’t update when DST or other timezone rules change. Use ZonedDateTime.now('<tz>') if you know the timezone, or Instant.now() for timezone-agnostic exact time. Suppress with ignore_potentially_stale_offset_warning().

classmethod parse(s: str, /, *, format: str) OffsetDateTime[source]

Parse an offset datetime from a custom pattern string.

The pattern must include an offset field (x/X). See Pattern format for details.

Tip

If your input string doesn’t include an offset, parse it with PlainDateTime.parse() first, then convert using assume_fixed_offset() or assume_tz().

>>> OffsetDateTime.parse("2024-03-15 14:30+02:00", format="YYYY-MM-DD hh:mmxxx")
OffsetDateTime("2024-03-15 14:30:00+02:00")
classmethod parse_iso(s: str, /) OffsetDateTime[source]

Parse the popular ISO format YYYY-MM-DDTHH:MM:SS±HH:MM

The inverse of the format_iso() method.

>>> OffsetDateTime.parse_iso("2020-08-15T23:12:00+02:00")
OffsetDateTime("2020-08-15 23:12:00+02:00")
classmethod parse_rfc2822(s: str, /) OffsetDateTime[source]

Parse an offset datetime in RFC 2822 format.

The inverse of the format_rfc2822() method.

>>> OffsetDateTime.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 +0200")
OffsetDateTime("2020-08-15 23:12:00+02:00")
>>> # also valid:
>>> OffsetDateTime.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 UT")
>>> OffsetDateTime.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 GMT")
>>> OffsetDateTime.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 MST")

Note

  • Strictly speaking, an offset of -0000 means that the offset is “unknown”. Here, we treat it the same as +0000.

  • Although technically part of the RFC 2822 standard, comments within folding whitespace are not supported.

classmethod parse_strptime(s: str, /, *, format: str) OffsetDateTime[source]

Parse a datetime with offset using the standard library strptime() method.

Deprecated since version 0.10.0: Use parse() with a pattern string instead, or use OffsetDateTime(datetime.strptime(...)).

__add__(delta: TimeDelta) OffsetDateTime[source]

Add a time delta to this datetime.

Warning

Shifting an OffsetDateTime keeps the fixed UTC offset, which may not match the actual offset after a DST or other timezone transition. For example, adding 1 day to 2024-03-09 12:00-07:00 gives 2024-03-10 12:00-07:00, but if this offset represents Denver, Colorado (America/Denver), the actual offset changed to -06:00 that day. Convert to a ZonedDateTime first for timezone-aware arithmetic using assume_tz(). Suppress with the ignore_potentially_stale_offset_warning() context manager; Python’s standard warning filters also apply.

__eq__(other: object) bool

Check if two datetimes represent at the same moment in time

a == b is equivalent to a.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 >= b is equivalent to a.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 > b is equivalent to a.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 <= b is equivalent to a.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 < b is equivalent to a.to_instant() < b.to_instant()

>>> OffsetDateTime(2020, 8, 15, hour=23, offset=8) < (
...     ZoneDateTime(2020, 8, 15, hour=20, tz="Europe/Amsterdam")
... )
True
__str__() str

Return str(self).

__sub__(
other: Instant | OffsetDateTime | ZonedDateTime,
) TimeDelta[source]
__sub__(other: TimeDelta) OffsetDateTime

Subtract a time delta or calculate the duration to another exact time.

add(
delta: DateTimeDelta | TimeDelta | DateDelta | ItemizedDelta | ItemizedDateDelta,
/,
) OffsetDateTime[source]
add(
*,
years: int = 0,
months: int = 0,
weeks: int = 0,
days: int = 0,
hours: float = 0,
minutes: float = 0,
seconds: float = 0,
milliseconds: float = 0,
microseconds: float = 0,
nanoseconds: int = 0,
ignore_dst: bool = ...,
) OffsetDateTime

Add a time amount to this datetime.

Warning

Shifting an OffsetDateTime keeps the fixed UTC offset, which may not match the actual offset after a DST or other timezone transition. Convert to a ZonedDateTime first for timezone-aware arithmetic using assume_tz(). Suppress with the ignore_potentially_stale_offset_warning() context manager; Python’s standard warning filters also apply.

assume_tz(tz: str, *, offset_mismatch: OffsetMismatchStr = 'raise') ZonedDateTime[source]

Associate this offset datetime with a timezone, returning a ZonedDateTime.

This is the inverse of ZonedDateTime.to_fixed_offset().

By default, if the offset of this datetime doesn’t match the actual offset of the timezone at this datetime, an error is raised. Using the offset_mismatch parameter, you can choose to ignore the mismatch, keeping either the instant or the local time the same.

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 like assume_utc() or assume_tz():

>>> date.at(time).assume_tz("Europe/London")
ZonedDateTime("2021-01-02T03:04:05+00:00[Europe/London]")
difference(
other: Instant | OffsetDateTime | ZonedDateTime,
/,
) TimeDelta

Calculate the difference between two instants in time.

Deprecated since version 0.10.0: Use the subtraction operator instead

exact_eq(other: _T, /) bool

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, then a == b is 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.

>>> OffsetDateTime(2024, 3, 15, 14, 30, offset=hours(2)).format(
...     "YYYY-MM-DD hh:mmxxx"
... )
'2024-03-15 14:30+02:00'
format_iso(
*,
unit: Literal['hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond', 'auto'] = 'auto',
basic: bool = False,
sep: Literal['T', ' '] = 'T',
) str[source]

Convert to the popular ISO format YYYY-MM-DDTHH:MM:SS±HH:MM

The inverse of the parse_iso() method.

format_rfc2822() str[source]

Format as an RFC 2822 string.

The inverse of the parse_rfc2822() method.

>>> OffsetDateTime(2020, 8, 15, 23, 12, offset=hours(2)).format_rfc2822()
"Sat, 15 Aug 2020 23:12:00 +0200"
py_datetime() datetime

Convert to a standard library datetime

Deprecated since version 0.10.0: Use to_stdlib() instead.

replace(
year: int = ...,
month: int = ...,
day: int = ...,
hour: int = ...,
minute: int = ...,
second: int = ...,
*,
nanosecond: int = ...,
offset: int | TimeDelta = ...,
ignore_dst: bool = ...,
) OffsetDateTime[source]

Construct a new instance with the given fields replaced.

Warning

Replacing fields of an OffsetDateTime keeps the fixed UTC offset, which may no longer be correct after the change (e.g. replacing the month on a European-timezone datetime may move it into a different DST period). Convert to ZonedDateTime first for timezone-aware field replacement using assume_tz(). Suppress with ignore_potentially_stale_offset_warning().

replace_date(date: Date, /, *, ignore_dst: bool = ...) OffsetDateTime[source]

Construct a new instance with the date replaced.

See replace() for more information.

replace_time(time: Time, /, *, ignore_dst: bool = ...) OffsetDateTime[source]

Construct a new instance with the time replaced.

See replace() for more information.

round(
unit: Literal['day', 'hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond'] | TimeDelta = 'second',
/,
*,
increment: int = 1,
mode: RoundModeStr = 'half_even',
ignore_dst: bool = ...,
) OffsetDateTime[source]

Round the datetime to the specified unit and increment, or to a multiple of a TimeDelta. Different rounding modes are available.

>>> d = OffsetDateTime(2020, 8, 15, 23, 24, 18, offset=+4)
>>> d.round("day")
OffsetDateTime("2020-08-16 00:00:00[+04:00]")
>>> d.round("minute", increment=15, mode="floor")
OffsetDateTime("2020-08-15 23:15:00[+04:00]")

Note

  • This method has similar behavior to the round() method of Temporal objects in JavaScript.

Warning

Rounding an OffsetDateTime keeps the fixed UTC offset, which may not be accurate if the rounded datetime crosses into a different DST period. Convert to a ZonedDateTime first for timezone-aware rounding using assume_tz(). Suppress with ignore_potentially_stale_offset_warning().

since(b: OffsetDateTime, /, *, total: DeltaUnitStr) float[source]
since(
b: OffsetDateTime,
/,
*,
in_units: Sequence[TypeAliasForwardRef('DeltaUnitStr')],
round_mode: RoundModeStr = ...,
round_increment: int = ...,
) ItemizedDelta

Calculate the duration since another OffsetDateTime, in terms of the specified units.

>>> d1 = OffsetDateTime(2020, 8, 15, 23, 12, offset=2)
>>> d2 = OffsetDateTime(2020, 8, 14, 22, offset=2)
>>> d1.since(d2, in_units=["hours", "minutes"],
...          round_increment=15,
...          round_mode="ceil")
ItemizedDelta("PT25h15m")

When calculating calendar units (years, months, weeks, days), both datetimes must have the same offset.

subtract(
delta: DateTimeDelta | TimeDelta | DateDelta | ItemizedDelta | ItemizedDateDelta,
/,
) OffsetDateTime[source]
subtract(
*,
years: int = 0,
months: int = 0,
weeks: int = 0,
days: int = 0,
hours: float = 0,
minutes: float = 0,
seconds: float = 0,
milliseconds: float = 0,
microseconds: float = 0,
nanoseconds: int = 0,
ignore_dst: bool = ...,
) OffsetDateTime

Subtract a time amount from this datetime.

See add() 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 like assume_utc() or assume_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, PlainDateTime has methods assume_utc(), assume_fixed_offset() , assume_tz(), and assume_system_tz().

to_stdlib() datetime

Convert to a standard library datetime

Note

  • Nanoseconds are truncated to microseconds. If you wish to customize the rounding behavior, use the round() method first.

  • For ZonedDateTime linked to a system timezone without a IANA timezone ID, the returned Python datetime will have a fixed offset (timezone tzinfo)

to_system_tz() ZonedDateTime

Convert to a ZonedDateTime of the system’s timezone.

to_tz(tz: str, /) ZonedDateTime

Convert to a ZonedDateTime that represents the same moment in time.

Raises:

TimeZoneNotFoundError – If the timezone ID is not found in the timezone database.

until(b: OffsetDateTime, /, *, total: DeltaUnitStr) float[source]
until(
b: OffsetDateTime,
/,
*,
in_units: Sequence[TypeAliasForwardRef('DeltaUnitStr')],
round_mode: RoundModeStr = ...,
round_increment: int = ...,
) ItemizedDelta

Inverse of the since() method. See since() for more information.

property day: int

The day component of the datetime

property hour: int

The hour component of the datetime

property minute: int

The minute component of the datetime

property month: int

The month component of the datetime

property nanosecond: int

The nanosecond component of the datetime

property offset: TimeDelta

The UTC offset of the datetime

property second: int

The second component of the datetime

property year: int

The year component of the datetime