From e7a7bf0d4f24183a47591af72a248be9a24d8d93 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Thu, 1 May 2025 15:50:17 -0400 Subject: [PATCH] Add static .nanoseconds(_: Double) to Duration (#81210) SE-0329 defines the following static factory methods: ``` public static func seconds(_ seconds: T) -> Duration public static func seconds(_ seconds: Double) -> Duration public static func milliseconds(_ milliseconds: T) -> Duration public static func milliseconds(_ milliseconds: Double) -> Duration public static func microseconds(_ microseconds: T) -> Duration public static func microseconds(_ microseconds: Double) -> Duration public static func nanoseconds(_ value: T) -> Duration ``` For no good reason, the obvious additional method: ``` public static func nanoseconds(_ nanoseconds: Double) -> Duration ``` was omitted. After talking this through with the LSG, we have decided that this is simply a bug, and we will add this method without formal evolution review. --- stdlib/public/core/Duration.swift | 11 +++++++++++ test/abi/macOS/arm64/stdlib.swift | 5 ++++- test/abi/macOS/x86_64/stdlib.swift | 2 ++ test/stdlib/Duration.swift | 15 +++++++++++++-- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/stdlib/public/core/Duration.swift b/stdlib/public/core/Duration.swift index 5b3b9da5bae0e..6b4ac94d17e46 100644 --- a/stdlib/public/core/Duration.swift +++ b/stdlib/public/core/Duration.swift @@ -250,6 +250,17 @@ extension Duration { let highScaled = high * 1_000_000_000 return Duration(_high: highScaled + Int64(lowScaled.high), low: lowScaled.low) } + + /// Construct a `Duration` given a number of seconds nanoseconds as a + /// `Double` by converting the value into the closest attosecond scale value. + /// + /// let d: Duration = .nanoseconds(382.9) + /// + /// - Returns: A `Duration` representing a given number of nanoseconds. + @available(SwiftStdlib 6.2, *) + public static func nanoseconds(_ nanoseconds: Double) -> Duration { + Duration(nanoseconds, scale: 1_000_000_000) + } } @available(SwiftStdlib 5.7, *) diff --git a/test/abi/macOS/arm64/stdlib.swift b/test/abi/macOS/arm64/stdlib.swift index c5bde9b46c1bb..e1a10fb3ceab6 100644 --- a/test/abi/macOS/arm64/stdlib.swift +++ b/test/abi/macOS/arm64/stdlib.swift @@ -1127,4 +1127,7 @@ Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7Ra Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7RawSpanV9byteCountSivpMV$ Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7RawSpanVMa$ Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7RawSpanVMn$ -Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7RawSpanVN$ \ No newline at end of file +Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7RawSpanVN$ + +// Duration.nanoseconds(_:) +Added: _$ss8DurationV11nanosecondsyABSdFZ diff --git a/test/abi/macOS/x86_64/stdlib.swift b/test/abi/macOS/x86_64/stdlib.swift index 9aee5506d525c..a49496cd3bb14 100644 --- a/test/abi/macOS/x86_64/stdlib.swift +++ b/test/abi/macOS/x86_64/stdlib.swift @@ -1130,3 +1130,5 @@ Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7Ra Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7RawSpanVMn$ Added: $ld$previous$@rpath/libswiftCompatibilitySpan.dylib$$1$10.14$15.0$_$ss7RawSpanVN$ +// Duration.nanoseconds(_:) +Added: _$ss8DurationV11nanosecondsyABSdFZ diff --git a/test/stdlib/Duration.swift b/test/stdlib/Duration.swift index 9e94003a63285..d6cdc5844acf1 100644 --- a/test/stdlib/Duration.swift +++ b/test/stdlib/Duration.swift @@ -28,11 +28,11 @@ if #available(SwiftStdlib 5.7, *) { // Divide by 1000 to get back to a duration with representable components: let smallerDuration = duration / 1000 expectEqual(smallerDuration.components, (170_000_000_000_000_000, 0)) - #if !os(WASI) +#if !os(WASI) // Now check that the components of the original value trap: expectCrashLater() let _ = duration.components - #endif +#endif } suite.test("milliseconds from Double") { @@ -266,3 +266,14 @@ if #available(SwiftStdlib 6.0, *) { expectEqual(min.attoseconds, .min) } } + +if #available(SwiftStdlib 6.2, *) { + suite.test("nanoseconds from Double") { + for _ in 0 ..< 100 { + let integerValue = Double(Int64.random(in: 0 ... 0x7fff_ffff_ffff_fc00)) + let (sec, attosec) = Duration.nanoseconds(integerValue).components + expectEqual(sec, Int64(integerValue) / 1_000_000_000) + expectEqual(attosec, Int64(integerValue) % 1_000_000_000 * 1_000_000_000) + } + } +}