Hello, I recently asked about random durations on this forum. However I was hitting some limitations and was encouraged to pitch. Looking forward to your feedback
Introduction
This proposal introduces public APIs to enable seamless integration of Int128
into the Duration
type. Specifically, it provides support for directly accessing a Duration
's attosecond representation via the newly available Int128
type and simplifies the creation of Duration
values from attoseconds.
Motivation
The Duration
type currently offers two ways to construct and decompose itself:
Low and high bits
public struct Duration: Sendable {
public var _low: UInt64
public var _high: Int64
public init(_high: Int64, low: UInt64) { ... }
}
Components
extension Duration {
public var components: (seconds: Int64, attoseconds: Int64) { ... }
public init(secondsComponent: Int64, attosecondsComponent: Int64) { ... }
}
However, both approaches have limitations when it comes to exposing Duration
's total attosecond representation:
- The
_low
and_high
properties are underscored, indicating that their direct use is discouraged. - The
components
property decomposes the value into seconds and attoseconds, requiring additional arithmetic operations for many use cases.
This gap becomes particularly evident in scenarios like generating a random Duration
, which currently requires verbose and potentially inefficient code:
func randomDuration(upTo maxDuration: Duration) -> Duration {
let attosecondsPerSecond: Int128 = 1_000_000_000_000_000_000
let upperRange = Int128(maxDuration.components.seconds) * attosecondsPerSecond + Int128(maxDuration.components.attoseconds)
let (seconds, attoseconds) = Int128.random(in: 0..<upperRange).quotientAndRemainder(dividingBy: attosecondsPerSecond)
return .init(secondsComponent: Int64(seconds), attosecondsComponent: Int64(attoseconds))
}
By introducing direct Int128
support to Duration
, this complexity is eliminated. Developers can write concise and efficient code instead:
func randomDuration(upTo maxDuration: Duration) -> Duration {
return Duration(attoseconds: Int128.random(in: 0..<maxDuration.attoseconds))
}
This addition reduces boilerplate, minimizes potential errors, and improves performance for use cases requiring high-precision time calculations.
Proposed solution
This proposal complements the existing construction and decomposition options by introducing a third approach, leveraging the new Int128
type:
- A new computed property
attoseconds
, which exposes the total attoseconds of aDuration
as anInt128
. - A new initializer
init(attoseconds: Int128)
, which allows creating aDuration
directly from a single 128-bit value.
These additions provide a direct and efficient mechanism for working with Duration
values while maintaining full compatibility with existing APIs.
Detailed design
Internally, the Duration
type represents its value using the underscored _high
and _low
properties, which encode attoseconds as a 128-bit integer split into two 64-bit values. The proposed APIs unify these components into a single Int128
representation:
@available(SwiftStdlib 6.0, *)
extension Duration {
/// The duration represented in attoseconds.
public var attoseconds: Int128 {
Int128(_low: _low, _high: _high)
}
/// Initializes a `Duration` from the given number of attoseconds.
public init(attoseconds: Int128) {
self.init(_high: attoseconds._high, low: attoseconds._low)
}
}