|
| 1 | +# Clock Epochs |
| 2 | + |
| 3 | +* Proposal: [SE-0473](0473-clock-epochs.md) |
| 4 | +* Authors: [Philippe Hausler](https://github.com/phausler) |
| 5 | +* Review Manager: [John McCall](https://github.com/rjmccall) |
| 6 | +* Status: **Active Review (March 28th...April 9th, 2025)** |
| 7 | +* Implementation: |
| 8 | +* Review: ([pitch](https://forums.swift.org/t/pitch-suspendingclock-and-continuousclock-epochs/78017)) |
| 9 | + |
| 10 | +## Introduction |
| 11 | + |
| 12 | +[SE-0329: Clock, Instant, and Duration](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0329-clock-instant-duration.md) introduced three concrete clock types: `SuspendingClock`, `ContinuousClock`, and `UTCClock`. While not all clocks have a meaningful concept of a reference or zero instant, `SuspendingClock` and `ContinuousClock` do, and having access to it can be useful. |
| 13 | + |
| 14 | +## Motivation |
| 15 | + |
| 16 | +The `Instant` type of a `Clock` represents a moment in time as measured by that clock. `Clock` intentionally imposes very few requirements on `Instant` because different kinds of clocks can have very different characteristics. Just because something does not belong on the generic `Clock` protocol, however, does not mean it shouldn't be exposed in the interface of a concrete clock type. |
| 17 | + |
| 18 | +Many clocks have a concept of a reference instant, also called an "epoch", that has special meaning for the clock. For example, the Unix `gettimeofday` function measures the nominal elapsed time since 00:00 UTC on January 1st, 1970, an instant often called the "Unix epoch". Swift's `SuspendingClock` and `ContinuousClock` are defined using system facilities that similarly measure time relative to an epoch, and while the exact definition of the epoch is system-specific, it is at least consistent for any given system. This means that durations since the epoch can be meaningfully compared within the system, even across multiple processes or with code written in other languages (as long as they use the same system facilities). |
| 19 | + |
| 20 | +## Proposed solution |
| 21 | + |
| 22 | +Two new properties will be added, one to `SuspendingClock` and another to `ContinuousClock`. These properties define the system epoch that all `Instant` types for the clock are derived from; practically speaking, this is the "zero" point for these clocks. Since the values may be relative to the particular system they are being used on, their names reflect that they are a system-specific definition and should not be expected to be consistent (or meaningfully serializable) across systems. |
| 23 | + |
| 24 | +## Detailed design |
| 25 | + |
| 26 | +```swift |
| 27 | +extension ContinuousClock { |
| 28 | + public var systemEpoch: Instant { get } |
| 29 | +} |
| 30 | + |
| 31 | +extension SuspendingClock { |
| 32 | + public var systemEpoch: Instant { get } |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +On most platforms, including Apple platforms, Linux, and Windows, the system epoch of these clocks is set at boot time, and so measurements relative to the epoch can used to gather information such as the uptime or active time of a system: |
| 37 | + |
| 38 | +```swift |
| 39 | +let clock = ContinousClock() |
| 40 | +let uptime = clock.now - clock.systemEpoch |
| 41 | +``` |
| 42 | + |
| 43 | +Likewise: |
| 44 | + |
| 45 | +```swift |
| 46 | +let clock = SuspendingClock() |
| 47 | +let activeTime = clock.now - clock.systemEpoch |
| 48 | +``` |
| 49 | + |
| 50 | +However, this cannot be guaranteed for all possible platforms. A platform may choose to use a different instant for its system epoch, perhaps because the concept of uptime doesn't apply cleanly on the platform or because it is intentionally not exposed to the programming environment for privacy reasons. |
| 51 | + |
| 52 | +## ABI compatibility |
| 53 | + |
| 54 | +This is a purely additive change and provides no direct impact to existing ABI. It only carries the ABI impact of new properties being added to an existing type. |
| 55 | + |
| 56 | +## Alternatives considered |
| 57 | + |
| 58 | +We considered adding a constructor or static member to `SuspendingClock.Instant` and `ContinousClock.Instant` instead of on the clock. However, placing it on the clock itself provides a more discoverable and nameable location. |
| 59 | + |
| 60 | +As proposed, `systemEpoch` is an informal protocol that works across multiple clock implementations. We consider formalizing it as a new protocol, but ultimately we decided not to because no generic function made much sense that would not be better served with generic specialization or explicit clock parameter types. |
0 commit comments