From f2461e53439f52701f68baba7ffc4522bb1d90d9 Mon Sep 17 00:00:00 2001 From: Stevenson Michel <130018170+thoven87@users.noreply.github.com> Date: Mon, 16 Sep 2024 20:35:47 -0400 Subject: [PATCH 1/2] feat(every): adding every N minutes or hours --- Sources/Jobs/Scheduler/Schedule.swift | 33 +++++++++++++++++++++++++ Tests/JobsTests/JobSchedulerTests.swift | 9 +++++++ 2 files changed, 42 insertions(+) diff --git a/Sources/Jobs/Scheduler/Schedule.swift b/Sources/Jobs/Scheduler/Schedule.swift index 5ffcfd8..a611982 100644 --- a/Sources/Jobs/Scheduler/Schedule.swift +++ b/Sources/Jobs/Scheduler/Schedule.swift @@ -117,6 +117,39 @@ public struct Schedule: Sendable { .init(second: .specific(second)) } + /// Return schedule that generates a Date for minutes, hours or seconds + /// - Parameter minute: minute value e.g 5 + /// - Parameter hour: hour value e.g 3 + /// - Parameter timeZone defaults to GMT + public static func every(minute: Int = 5, hour: Int = 0, timeZone: TimeZone = .gmt) -> Self { + let maxNumber = if minute > 0, hour == 0 { + 60 / minute + } else { + 24 / hour + } + + var multiples: [Int] = [] + var index = 0 + let number = hour > 0 ? hour : minute + repeat { + let multiple = number * index + + if hour > 0, multiple > 24 { + let remainder = multiple % 24 + multiples.append(remainder - hour) + } else { + multiples.append(multiple) + } + + index = index + 1 + } while index < maxNumber + + if hour == 0 { + return .onMinutes(multiples) + } + return .onHours(multiples, timeZone: timeZone) + } + /// Return Schedule that generates a Date for a selection of minutes /// - Parameters /// - minutes: Array of minutes if should return Dates for diff --git a/Tests/JobsTests/JobSchedulerTests.swift b/Tests/JobsTests/JobSchedulerTests.swift index 330ff6e..e697b7d 100644 --- a/Tests/JobsTests/JobSchedulerTests.swift +++ b/Tests/JobsTests/JobSchedulerTests.swift @@ -62,6 +62,15 @@ final class JobSchedulerTests: XCTestCase { try self.testSchedule(start: "1999-12-31T23:59:25Z", expectedEnd: "2000-01-01T00:00:15Z", schedule: .everyMinute(second: 15)) } + func testEverySchedule() throws { + try self.testSchedule(start: "2021-06-21T21:00:00Z", expectedEnd: "2021-06-21T22:00:00Z", schedule: .every(minute: 5)) + try self.testSchedule(start: "2021-06-21T21:10:15Z", expectedEnd: "2021-06-21T22:00:00Z", schedule: .every(minute: 5)) + try self.testSchedule(start: "2024-02-22T20:00:00Z", expectedEnd: "2024-02-23T00:00:00Z", schedule: .every(hour: 3)) + try self.testSchedule(start: "2024-02-22T20:00:00Z", expectedEnd: "2024-02-23T00:00:00Z", schedule: .every(hour: 12)) + try self.testSchedule(start: "2024-02-22T00:00:00Z", expectedEnd: "2024-02-23T00:00:00Z", schedule: .every(hour: 12)) + try self.testSchedule(start: "2024-02-22T01:00:00Z", expectedEnd: "2024-02-23T00:00:00Z", schedule: .every(hour: 24)) + } + func testHourlySchedule() throws { try self.testSchedule(start: "2021-06-21T21:10:15Z", expectedEnd: "2021-06-21T21:58:00Z", schedule: .hourly(minute: 58)) try self.testSchedule(start: "1999-12-31T23:59:25Z", expectedEnd: "2000-01-01T00:01:00Z", schedule: .hourly(minute: 1)) From c2337dc39cdc5b52881470bc6abe8348c7e93635 Mon Sep 17 00:00:00 2001 From: Stevenson Michel <130018170+thoven87@users.noreply.github.com> Date: Mon, 16 Sep 2024 20:44:45 -0400 Subject: [PATCH 2/2] timezone GMT is not available in swift 5.10 or below --- Sources/Jobs/Scheduler/Schedule.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Jobs/Scheduler/Schedule.swift b/Sources/Jobs/Scheduler/Schedule.swift index a611982..8f713de 100644 --- a/Sources/Jobs/Scheduler/Schedule.swift +++ b/Sources/Jobs/Scheduler/Schedule.swift @@ -120,8 +120,8 @@ public struct Schedule: Sendable { /// Return schedule that generates a Date for minutes, hours or seconds /// - Parameter minute: minute value e.g 5 /// - Parameter hour: hour value e.g 3 - /// - Parameter timeZone defaults to GMT - public static func every(minute: Int = 5, hour: Int = 0, timeZone: TimeZone = .gmt) -> Self { + /// - Parameter timeZone defaults to current timezone + public static func every(minute: Int = 5, hour: Int = 0, timeZone: TimeZone = .current) -> Self { let maxNumber = if minute > 0, hour == 0 { 60 / minute } else {