我有一个应用程序,显示每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)
}
但这会返回最近的分钟(我想,它总是会返回一分钟)
有什么想法吗?
答案 0 :(得分:7)
您可以将秒数舍入到最接近的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)!
}
}
这应该足以显示圆形时间,但它
不准确: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)
}
}
现在seconds
是自当前分钟开始以来的时间间隔
(包括小数秒)。该间隔四舍五入到最近
30的倍数,并添加到分钟的开头。
答案 1 :(得分: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
}
}
要舍入到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
答案 2 :(得分:0)
let now = Date()
var timeInterval = now.timeIntervalSinceReferenceDate
timeInterval += 30 - timeInterval.truncatingRemainder(dividingBy: 30)
let rounded = Date(timeIntervalSinceReferenceDate: timeInterval)
print("\(now) rounded to nearest 30 seconds is \(rounded)")
答案 3 :(得分:-1)
有一个名为'SwiftDate'的Cocoapod,非常适合可以应用于Date()实例的日期格式和操作。
如何使用日期舍入方法的示例:
let date = Date() // 2018-10-01 23:05:29
date.dateRoundedAt(at: .toFloor5Mins) // 2018-10-01 23:05:00
date.dateRoundedAt(at: .toCeil5Mins) // 2018-10-01 23:10:00
date.dateRoundedAt(at: .toFloorMins(1)) // 2018-10-01 23:05:00
date.dateRoundedAt(at: .toCeilMins(1)) // 2018-10-01 23:06:00
(作为参考,请查看https://cocoapods.org/pods/SwiftDate上的文档)