回合时间到最近的30秒

Wil*_*ill 1 swift

我有一个应用程序,提供每30秒到期的数据(确切地说,在h/m/s 11:30:00,11:30:30,11:31:00等).

我可以得到当前时间,但我不确定如何计算从现在到最近的30秒之间的时间.

我发现的任何东西都在Objective-C中,我一直无法转换它.

这是我试过的:

func nearestThirtySeconds() -> Date? {
        var components = NSCalendar.current.dateComponents([.second], from: self)
        let second = components.second ?? 30
        components.second = second >= 30 ? 60 - second : -second
        return Calendar.current.date(byAdding: components, to: self)
    }
Run Code Online (Sandbox Code Playgroud)

但这会返回最近的分钟(我想,它总是会返回一分钟)

有任何想法吗?

Mar*_*n R 9

您可以将秒数舍入到最接近的30的倍数,然后将舍入值和原始值之间的差值添加到日期:

extension Date {
    func nearestThirtySeconds() -> Date {
        let cal = Calendar.current
        let seconds = cal.component(.second, from: self)
        // Compute nearest multiple of 30:
        let roundedSeconds = lrint(Double(seconds) / 30) * 30
        return cal.date(byAdding: .second, value: roundedSeconds - seconds, to: self)!
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该足以显示四舍五入的时间,但不准确:A Date还包括小数秒,因此例如"11:30:10.123"将变为"11:30:00.123"而不是"11:30:00.000" ".这是解决该问题的另一种方法:

extension Date {
    func nearestThirtySeconds() -> Date {
        let cal = Calendar.current
        let startOfMinute = cal.dateInterval(of: .minute, for: self)!.start
        var seconds = self.timeIntervalSince(startOfMinute)
        seconds = (seconds / 30).rounded() * 30
        return startOfMinute.addingTimeInterval(seconds)
    }
}
Run Code Online (Sandbox Code Playgroud)

现在seconds是自当前分钟开始以来的时间间隔(包括小数秒).该间隔四舍五入到最接近的30的倍数并添加到分钟的开头.


Cas*_*gen 5

我使用了Martin R的答案来编写一个更通用的版本来循环任何时间段.

答案已过时,仅适用于时间,请查看要点以获取最新版本.

https://gist.github.com/casperzandbergenyaacomm/83c6a585073fd7da2e1fbb97c9bcd38a

extension Date {

    func rounded(on amount: Int, _ component: Calendar.Component) -> Date {
        let cal = Calendar.current
        let value = cal.component(component, from: self)

        // Compute nearest multiple of amount:
        let roundedValue = lrint(Double(value) / Double(amount)) * amount
        let newDate = cal.date(byAdding: component, value: roundedValue - value, to: self)!

        return newDate.floorAllComponents(before: component)
    }

    func floorAllComponents(before component: Calendar.Component) -> Date {
        // All components to round ordered by length
        let components = [Calendar.Component.year, .month, .day, .hour, .minute, .second, .nanosecond]

        guard let index = components.index(of: component) else {
            fatalError("Wrong component")
        }

        let cal = Calendar.current
        var date = self

        components.suffix(from: index + 1).forEach { roundComponent in
            let value = cal.component(roundComponent, from: date) * -1
            date = cal.date(byAdding: roundComponent, value: value, to: date)!
        }

        return date
    }
}
Run Code Online (Sandbox Code Playgroud)

要舍入到x分钟,您还需要对秒数进行处理,因此这也包含我写的底层方法.

如何使用:

let date: Date = Date() // 10:16:34
let roundedDate0 = date.rounded(on: 30, .second) // 10:16:30
let roundedDate1 = date.rounded(on: 15, .minute) // 10:15:00 
let roundedDate2 = date.rounded(on: 1, .hour)    // 10:00:00 
Run Code Online (Sandbox Code Playgroud)