16

我试图从中获取NSDateUIDatePicker但它不断返回我一个日期时间,后缀为 20 秒。如何手动将NSDate's second 设置为零?

4

7 回答 7

16

NSDate 是不可变的,所以你不能修改它的时间。但是您可以创建一个捕捉到最近分钟的新日期对象:

NSTimeInterval time = floor([date timeIntervalSinceReferenceDate] / 60.0) * 60.0;
NSDate *minute = [NSDate dateWithTimeIntervalSinceReferenceDate:time];

编辑以回答 Uli 的评论

参考日期为NSDate2001 年 1 月 1 日 0:00 GMT。从那时起已经添加了两个闰秒:2005 年和 2010 年,因此返回的值[NSDate timeIntervalSinceReferenceDate]应该关闭两秒。

情况并非如此:timeIntervalSinceReferenceDate与挂墙时间完全同步。

在回答这个问题时,我不确定这是否属实。我只是假设 Mac OS 的行为与 UNIX 时间(1970 纪元)一样:POSIX 保证每天以 86,400 秒的倍数开始。

查看从NSDate这个假设返回的值似乎是正确的,但找到一个明确的(记录的)声明肯定会很好。

于 2009-10-06T14:24:12.190 回答
11

您不能直接操作 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: 处理的任何特殊事情也被考虑在内。

于 2012-01-27T17:46:33.547 回答
5

这是任何有兴趣的人的 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比在日期中添加时间间隔要强大得多。

于 2018-01-25T22:58:42.747 回答
3

虽然这是一个老问题,并且 Uli 给出了“正确”的答案,但最简单的解决方案恕我直言,只是从日历中减去从日期中获得的秒数。请注意,这可能仍会保留毫秒。

NSDate *date = [NSDate date];
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitSecond
                                                         fromDate:date];
date = [date dateByAddingTimeInterval:-comp.second];
于 2014-08-06T03:30:16.107 回答
1

NSDate记录一个时刻。如果您想做的是存储特定日期,请不要使用NSDate. 您会遇到很多与时区、夏令时等相关的意外头痛。

一种替代解决方案是将日期存储为准 ISO 标准格式的整数,例如 2011 年 9 月 15 日的 20110915。这保证以与排序相同的方式进行NSDate排序。

于 2012-01-27T11:30:56.820 回答
1

这是在 Swift 中执行此操作的扩展:

extension NSDate {
    func truncateSeconds() -> NSDate {
        let roundedTime = floor(self.timeIntervalSinceReferenceDate / 60) * 60
        return NSDate(timeIntervalSinceReferenceDate: roundedTime)
    }
}
于 2016-07-20T22:24:09.617 回答
0

还有斯威夫特...

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)!
  }

}
于 2020-05-25T23:30:25.937 回答