Durations, parsed once at the boundary.
Public APIs accept a Duration (seconds as a float, or a timedelta)
and parse it with to_seconds into Seconds. Everything past the
boundary (clocks, schedulers, schedule decisions) takes Seconds, so a
raw float cannot reach a timer without being parsed.
Parsing follows Effect's Duration.make: NaN and -0 become 0.
Infinities are kept (an infinite sleep never wakes); negative values are
kept (a negative sleep wakes at once).
| Attribute | Type | Description |
|---|---|---|
ZERO | Seconds = Seconds(0.0) |
Classes#
Functions#
to_seconds#
to_seconds(duration) -> Seconds| Parameter | Type | Description |
|---|---|---|
duration | Duration |
Returns Seconds
def to_seconds(duration: Duration) -> Seconds:
return Seconds(duration.total_seconds() if isinstance(duration, timedelta) else duration)to_nanos#
to_nanos(seconds) -> intWhole nanoseconds (floored) in a finite number of seconds.
The float is read as the shortest decimal that prints it, so
1_000_000_000.001 is exactly 1_000_000_000_001_000_000;
multiplying by 1e9 in floating point would be off by tens of
nanoseconds at epoch-sized values.
| Parameter | Type | Description |
|---|---|---|
seconds | float |
Returns int
def to_nanos(seconds: float) -> int:
"""Whole nanoseconds (floored) in a finite number of seconds.
The float is read as the shortest decimal that prints it, so
``1_000_000_000.001`` is exactly ``1_000_000_000_001_000_000``;
multiplying by ``1e9`` in floating point would be off by tens of
nanoseconds at epoch-sized values."""
return math.floor(_exact_nanos(seconds))to_millis#
to_millis(duration) -> floatMilliseconds in duration, read as the shortest decimal that
prints it (as to_nanos does), so a duration measured in whole
nanoseconds gives nanos / 1e6 as Effect's Duration.toMillis
does, not a float product one ulp off.
| Parameter | Type | Description |
|---|---|---|
duration | Duration |
Returns float
def to_millis(duration: Duration) -> float:
"""Milliseconds in ``duration``, read as the shortest decimal that
prints it (as ``to_nanos`` does), so a duration measured in whole
nanoseconds gives ``nanos / 1e6`` as Effect's ``Duration.toMillis``
does, not a float product one ulp off."""
if isinstance(duration, timedelta):
return duration / timedelta(milliseconds=1)
seconds = to_seconds(duration)
if math.isinf(seconds):
return float(seconds)
return float(Decimal(repr(float(seconds))) * 1000)format_duration#
format_duration(seconds) -> strHuman-readable, as Effect's Duration.format: "1s 500ms".
| Parameter | Type | Description |
|---|---|---|
seconds | Seconds |
Returns str
def format_duration(seconds: Seconds) -> str:
"""Human-readable, as Effect's ``Duration.format``: ``"1s 500ms"``."""
if math.isinf(seconds):
return "Infinity" if seconds > 0 else "-Infinity"
nanos = round(_exact_nanos(abs(seconds))) # Effect keeps whole nanoseconds
if nanos == 0:
return "0"
pieces: list[str] = []
for suffix, size in _UNITS:
count, nanos = divmod(nanos, size)
if count:
pieces.append(f"{count}{suffix}")
if nanos:
pieces.append(f"{nanos}ns")
return ("-" if seconds < 0 else "") + " ".join(pieces)