Instant

class whenever.Instant(iso_string: str, /)[source]
class whenever.Instant(py_datetime: datetime, /)

A moment in time, independent of any time zone or calendar.

This is the right type when you only care about when something happened, not the local date or time. It maps 1:1 to a UNIX timestamp.

>>> from whenever import Instant
>>> py311_release = Instant.from_utc(2022, 10, 24, hour=17)
Instant("2022-10-24 17:00:00Z")
>>> py311_release.add(hours=3).timestamp()
1666641600

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

>>> Instant("2022-10-24T17:00:00Z")
Instant("2022-10-24 17:00:00Z")

Convert to other types for local date/time information:

>>> py311_release.to_tz("US/Pacific")
ZonedDateTime("2022-10-24 10:00:00-07:00[US/Pacific]")

Note

Although the debug representation uses UTC, Instant does not have .year, .hour, or other calendar attributes—it is not a UTC datetime. See the FAQ.

classmethod from_timestamp(value: int | float, /, *, unit: TimestampUnitStr = 'second') → Instant[source]

Create an Instant from a UNIX timestamp in the requested unit.

The inverse of the timestamp() method.

Seconds accept integers and floats, which are floored to whole nanoseconds; milliseconds, microseconds, and nanoseconds require integers. A value outside Instant.MIN..MAX raises ValueError.

classmethod from_timestamp_millis(value: int, /) → Instant[source]

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

Deprecated since version 0.11: Use from_timestamp(..., unit="millisecond") instead.

The inverse of the timestamp_millis() method.

classmethod from_timestamp_nanos(value: int, /) → Instant[source]

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

Deprecated since version 0.11: Use from_timestamp(..., unit="nanosecond") instead.

The inverse of the timestamp_nanos() method.

classmethod from_utc(
year: int,
month: int,
day: int,
hour: int = 0,
minute: int = 0,
second: int = 0,
*,
nanosecond: int = 0,
) → Instant[source]

Create an Instant from a date and time-of-day in UTC. This is the field constructor of Instant; see the FAQ for why Instant(...) takes no fields.

>>> Instant.from_utc(2022, 10, 24, hour=17)
Instant("2022-10-24 17:00:00Z")
classmethod now() → Instant[source]

Create an Instant from the current time.

>>> Instant.now()
Instant("2024-06-15 12:34:56.789123456Z")
classmethod parse(s: str, /, *, pattern: str = ...) → Instant[source]

Parse an instant from a custom pattern string.

The pattern must include an offset specifier (x/X) to unambiguously identify the instant. 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_utc() or assume_tz().

>>> Instant.parse("2024-03-15 14:30Z", pattern="YYYY-MM-DD HH:mmXXX")
Instant("2024-03-15 14:30:00Z")
>>> Instant.parse("2024-03-15 14:30+05:30", pattern="YYYY-MM-DD HH:mmxxx")
Instant("2024-03-15 09:00:00Z")
classmethod parse_iso(s: str, /) → Instant[source]

Parse an ISO 8601 string, such as 2020-08-15T23:12:00Z.

The basic and extended formats are accepted, but not week dates or ordinal dates. Z or an offset is required, and a non-zero offset is converted to UTC. A bracketed time zone ID is accepted and ignored. See ISO 8601 for details.

Inverse of format_iso().

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

Parse an RFC 2822 string; the offset is applied and the result is UTC.

>>> Instant.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 GMT")
Instant("2020-08-15 23:12:00Z")
>>> # also valid:
>>> Instant.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 +0000")
>>> Instant.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 +0800")
>>> Instant.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 -0000")
>>> Instant.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 UT")
>>> Instant.parse_rfc2822("Sat, 15 Aug 2020 23:12:00 MST")

Note

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

__add__(delta: TimeDelta, /) → Instant[source]

Add a time amount to this datetime.

See the docs on arithmetic for more information.

__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

To also compare what == ignores, use strict_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=hours(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=-hours(8)) >= (
...     ZonedDateTime(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=-hours(8)) > (
...     ZonedDateTime(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=hours(8)) <= (
...     ZonedDateTime(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=hours(8)) < (
...     ZonedDateTime(2020, 8, 15, hour=20, tz="Europe/Amsterdam")
... )
True
__str__() → str

Return str(self).

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

Subtract another exact time or TimeDelta

See the docs on arithmetic for more information.

>>> d = Instant.from_utc(2020, 8, 15, hour=23, minute=12)
>>> d - hours(24) - seconds(5)
Instant("2020-08-14 23:11:55Z")
>>> d - Instant.from_utc(2020, 8, 14)
TimeDelta("PT47h12m")
add(d: TimeDelta, /) → Instant[source]
add(
*,
weeks: float = 0,
days: float = 0,
hours: float = 0,
minutes: float = 0,
seconds: float = 0,
milliseconds: float = 0,
microseconds: float = 0,
nanoseconds: int = 0,
days_assumed_24h_ok: bool = UNSET,
) → Instant

Add a time amount to this instant.

See the docs on arithmetic for more information.

Warning

days and weeks are exact 24-hour and 168-hour units here, which emits DaysAssumed24HoursWarning. Pass days_assumed_24h_ok=True when that is intentional.

difference(
other: Instant | OffsetDateTime | ZonedDateTime,
/,
) → TimeDelta

Calculate the exact time difference between two datetimes.

This method returns the exact elapsed TimeDelta between two instants in time. Equivalent to the subtraction operator (-).

Use since() or until() on the local datetimes for calendar units, unit decomposition, and rounding.

exact_eq(other: Any, /) → bool

Deprecated alias for strict_eq().

Deprecated since version 0.11: Use strict_eq() instead.

format(pattern: str, /) → str[source]

Format as a custom pattern string.

Instant formats as UTC; See Pattern format for details.

>>> Instant.from_utc(2024, 3, 15, 14, 30).format("YYYY-MM-DD HH:mm:ssXXX")
'2024-03-15 14:30:00Z'
format_iso(
*,
unit: Literal['hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond', 'auto'] = 'auto',
basic: bool = False,
sep: Literal['T', ' '] = 'T',
) → str[source]

Format as an ISO 8601 string, such as 2020-08-15T23:12:00Z.

Inverse of parse_iso().

>>> Instant.from_utc(2020, 8, 15, hour=23, minute=12).format_iso()
'2020-08-15T23:12:00Z'

unit, basic, and sep are as on ZonedDateTime.format_iso().

format_rfc2822() → str[source]

Format as an RFC 2822 string in the fixed UTC/GMT subset.

RFC 2822 has whole-second precision, so nanoseconds are discarded.

>>> Instant.from_utc(2020, 8, 8, hour=23, minute=12).format_rfc2822()
"Sat, 08 Aug 2020 23:12:00 GMT"

Note

This is also the IMF-fixdate representation used to generate HTTP dates under the stricter RFC 9110 standard.

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

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

>>> Instant.from_utc(2020, 1, 1, 12, 39, 59).round("minute", increment=15)
Instant("2020-01-01 12:45:00Z")
>>> Instant.from_utc(2020, 1, 1, 8, 9, 13).round("second", increment=5, mode="floor")
Instant("2020-01-01 08:09:10Z")
>>> Instant.from_utc(2020, 1, 1, 12, 39, 59).round(TimeDelta(minutes=15))
Instant("2020-01-01 12:45:00Z")

"day" is rejected: an instant has no calendar, so a day has no midnight to start at. round("hour", increment=24) gives periods of exactly 24 hours, counted from midnight UTC like every increment on an Instant. "half_even" also breaks a tie toward the even multiple counted from that midnight, not from the epoch.

strict_eq(other: Any, /) → bool

Compare two values, including what == ignores.

Instant.__eq__ ignores nothing but the argument’s type, while OffsetDateTime.__eq__ also ignores the local datetime and the offset. An argument of a different type raises TypeError. The example uses OffsetDateTime, where == ignores the offset.

>>> a = OffsetDateTime(2020, 8, 15, hour=12, offset=hours(1))
>>> b = OffsetDateTime(2020, 8, 15, hour=13, offset=hours(2))
>>> a == b
True  # equivalent instants
>>> a.strict_eq(b)
False  # different local datetime and offset
>>> a.strict_eq(Instant.now())
TypeError  # different types

See Strict equality for the rules on every type.

subtract(d: TimeDelta, /) → Instant[source]
subtract(
*,
weeks: float = 0,
days: float = 0,
hours: float = 0,
minutes: float = 0,
seconds: float = 0,
milliseconds: float = 0,
microseconds: float = 0,
nanoseconds: int = 0,
days_assumed_24h_ok: bool = UNSET,
) → Instant

Subtract a time amount from this instant.

See the docs on arithmetic for more information.

Warning

days and weeks are exact 24-hour and 168-hour units here, which emits DaysAssumed24HoursWarning. Pass days_assumed_24h_ok=True when that is intentional.

timestamp(*, unit: TimestampUnitStr = 'second') → int

The UNIX timestamp in the requested unit. 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.

Values before the epoch are floored at the requested unit. For example, 1969-12-31T23:59:59.999999999Z has timestamp -1 in seconds, milliseconds, microseconds, and nanoseconds. This differs from applying int() to a negative float, which truncates toward zero.

timestamp_millis() → int

Like timestamp(), but with millisecond precision.

Deprecated since version 0.11: Use timestamp(unit="millisecond") instead.

timestamp_nanos() → int

Like timestamp(), but with nanosecond precision.

Deprecated since version 0.11: Use timestamp(unit="nanosecond") instead.

to_fixed_offset(offset: TimeDelta = ..., /) → OffsetDateTime

Convert to an OffsetDateTime that represents the same moment in time.

With no offset, the value’s own offset is kept; an Instant gives +00:00.

to_stdlib() → datetime

Convert to a standard library datetime

Note

Nanoseconds are floored to microseconds. If you need more control over rounding, use round() first.

to_system_tz() → ZonedDateTime

Convert to a ZonedDateTime of the system time zone.

Deprecated since version 0.11: Use to_tz(SYSTEM_TZ) instead.

to_tz(tz: str | SYSTEM_TZ, /) → ZonedDateTime

Convert to a ZonedDateTime that represents the same moment in time. Pass SYSTEM_TZ for the system time zone.

Raises:

TimeZoneNotFoundError – If the time zone ID is not found in the time zone database.

MAX: ClassVar[Instant] = Instant("9999-12-31 23:59:59.999999999Z")

The maximum possible value of this type.

MIN: ClassVar[Instant] = Instant("0001-01-01 00:00:00Z")

The minimum possible value of this type.