我试图从中获取NSDate
,UIDatePicker
但它不断返回我一个日期时间,后缀为 20 秒。如何手动将NSDate
's second 设置为零?
7 回答
NSDate 是不可变的,所以你不能修改它的时间。但是您可以创建一个捕捉到最近分钟的新日期对象:
NSTimeInterval time = floor([date timeIntervalSinceReferenceDate] / 60.0) * 60.0;
NSDate *minute = [NSDate dateWithTimeIntervalSinceReferenceDate:time];
编辑以回答 Uli 的评论
参考日期为NSDate
2001 年 1 月 1 日 0:00 GMT。从那时起已经添加了两个闰秒:2005 年和 2010 年,因此返回的值[NSDate timeIntervalSinceReferenceDate]
应该关闭两秒。
情况并非如此:timeIntervalSinceReferenceDate
与挂墙时间完全同步。
在回答这个问题时,我不确定这是否属实。我只是假设 Mac OS 的行为与 UNIX 时间(1970 纪元)一样:POSIX 保证每天以 86,400 秒的倍数开始。
查看从NSDate
这个假设返回的值似乎是正确的,但找到一个明确的(记录的)声明肯定会很好。
您不能直接操作 NSTimeInterval,因为这是自参考日期以来的秒数距离,不能保证除以 60 时为 00 秒时间。毕竟,可能已插入闰秒以调整太阳时和UTC之间的差异。每个闰秒都会让你失望 1。我将日期的秒数固定为 0 的方法是:
NSDate * startDateTime = [NSDate date];
NSDateComponents * startSeconds = [[NSCalendar currentCalendar] components: NSSecondCalendarUnit fromDate: startDateTime];
startDateTime = [NSDate dateWithTimeIntervalSinceReferenceDate: [startDateTime timeIntervalSinceReferenceDate] -[startSeconds second]];
这需要处理闰秒。我想一个更干净的方法是使用-dateByAddingComponents:
NSDate * startDateTime = [NSDate date];
NSDateComponents * startSeconds = [[NSCalendar currentCalendar] components: NSSecondCalendarUnit fromDate: startDateTime];
[startSeconds setSecond: -[startSeconds second]];
startDateTime = [[NSCalendar currentCalendar] dateByAddingComponents: startSeconds toDate: startDateTime options: 0];
这样,您就可以保证 -dateByAddingComponents: 处理的任何特殊事情也被考虑在内。
这是任何有兴趣的人的 Swift 扩展:
extension Date {
public mutating func floorSeconds() {
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: self)
self = calendar.date(from: components) ?? self // you can handle nil however you choose, probably safe to force unwrap in most cases anyway
}
}
示例用法:
let date = Date()
date.floorSeconds()
使用DateComponents
比在日期中添加时间间隔要强大得多。
虽然这是一个老问题,并且 Uli 给出了“正确”的答案,但最简单的解决方案恕我直言,只是从日历中减去从日期中获得的秒数。请注意,这可能仍会保留毫秒。
NSDate *date = [NSDate date];
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitSecond
fromDate:date];
date = [date dateByAddingTimeInterval:-comp.second];
NSDate
记录一个时刻。如果您想做的是存储特定日期,请不要使用NSDate
. 您会遇到很多与时区、夏令时等相关的意外头痛。
一种替代解决方案是将日期存储为准 ISO 标准格式的整数,例如 2011 年 9 月 15 日的 20110915。这保证以与排序相同的方式进行NSDate
排序。
这是在 Swift 中执行此操作的扩展:
extension NSDate {
func truncateSeconds() -> NSDate {
let roundedTime = floor(self.timeIntervalSinceReferenceDate / 60) * 60
return NSDate(timeIntervalSinceReferenceDate: roundedTime)
}
}
还有斯威夫特...
extension Date {
func floored() -> Date {
let flooredSeconds = DateComponents(second: 0, nanosecond: 0)
return Calendar.current.nextDate(after: self,
matching: flooredSeconds,
matchingPolicy: .strict,
direction: Calendar.SearchDirection.backward)!
}
}