Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# DevFoundation Changelog


## 1.4.0: October 8, 2025

- We’ve added `Duration`-based alternatives to all APIs that take a `TimeInterval`. Specifically,

- We’ve added an overload of `DateProvider.offset(by:)` that takes a `Duration`.
- We’ve added an overload of `ExpiringValue.init(_:lifetimeDuration:)` that takes a
`Duration`.


## 1.3.0: October 8, 2025

- We’ve added a computed property spelled `timeInterval` to `Duration`, which returns the
Expand Down
20 changes: 14 additions & 6 deletions Sources/DevFoundation/Date Providers/OffsetDateProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,46 @@ struct OffsetDateProvider<Base>: DateProvider where Base: DateProvider {
private let base: Base

/// The time interval that this provider adds to the base provider’s dates.
private let offset: TimeInterval
private let offset: Duration


/// Creates a new `OffsetDateProvider` with the specified base and offset.
///
/// - Parameters:
/// - base: The base date provider whose dates this provider’s dates are relative to.
/// - offset: The time interval that the new date provider adds to its base provider’s dates.
init(base: Base, offset: TimeInterval) {
/// - offset: The duration that the new date provider adds to its base provider’s dates.
init(base: Base, offset: Duration) {
self.base = base
self.offset = offset
}


var now: Date {
return base.now + offset
return base.now + offset.timeInterval
}
}


extension OffsetDateProvider: CustomStringConvertible {
public var description: String {
return "\(base).offset(by: \(offset))"
return "\(base).offset(by: \(offset.timeInterval))"
}
}


extension DateProvider {
/// Returns a relative date provider whose current date is offset from this one’s by a constant duration.
///
/// - Parameter offset: The duration to add to this date provider’s dates.
public func offset(by offset: Duration) -> some DateProvider {
return OffsetDateProvider(base: self, offset: offset)
}


/// Returns a relative date provider whose current date is offset from this one’s by a constant time interval.
///
/// - Parameter offset: The time interval to add to this date provider’s dates.
public func offset(by offset: TimeInterval) -> some DateProvider {
return OffsetDateProvider(base: self, offset: offset)
return self.offset(by: .seconds(offset))
}
}
16 changes: 13 additions & 3 deletions Sources/DevFoundation/Utility Types/ExpiringValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ public struct ExpiringValue<Value> {
}


/// Creates a new expiring value with the specified value and lifetime duration.
///
/// - Parameters:
/// - value: The value.
/// - lifetimeDuration: The length of the value’s lifetime.
public init(_ value: Value, lifetimeDuration: Duration) {
let now = DateProviders.current.now
self.value = value
self.lifetimeRange = now ... (now + lifetimeDuration.timeInterval)
}


/// Creates a new expiring value with the specified value and lifetime duration.
///
/// The value’s lifetime starts now and ends `lifetimeDuration` seconds in the future.
Expand All @@ -42,9 +54,7 @@ public struct ExpiringValue<Value> {
/// - value: The value.
/// - lifetimeDuration: The length of the value’s lifetime.
public init(_ value: Value, lifetimeDuration: TimeInterval) {
let now = DateProviders.current.now
self.value = value
self.lifetimeRange = now ... (now + lifetimeDuration)
self.init(value, lifetimeDuration: .seconds(lifetimeDuration))
}


Expand Down