如何为NSDate设置秒为零

时间:2009-10-06 14:09:44

标签: ios iphone objective-c cocoa-touch nsdate

我正试图从NSDate获取UIDatePicker,但它会不断地返回一个约会时间为20秒的日期时间。如何手动将NSDate的秒设置为零?

7 个答案:

答案 0 :(得分:13)

NSDate是不可变的,因此您无法修改其时间。但是您可以创建一个新的日期对象,该对象可以捕捉到最近的分钟:

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

编辑以回答Uli的评论

NSDate的参考日期是2001年1月1日格林尼治标准时间0:00。从那时起,已经有两个闰秒:2005年和2010年,因此[NSDate timeIntervalSinceReferenceDate]返回的值应该关闭两秒钟。

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

在回答这个问题时,我并没有确定这是真的。我只是假设Mac OS会behave as UNIX time(1970年代)这样做:POSIX保证每天从86,400秒的倍数开始。

查看从NSDate返回的值,这个假设似乎是正确的,但确定找到明确的(有文件证明的)陈述是很好的。

答案 1 :(得分: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:处理的任何特殊事情都会被考虑在内。

答案 2 :(得分:2)

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

NSDate *date = [NSDate date];
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitSecond
                                                         fromDate:date];
date = [date dateByAddingTimeInterval:-comp.second];

答案 3 :(得分:2)

以下是感兴趣的任何人的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比向日期添加时间间隔要强大得多。

答案 4 :(得分:1)

NSDate记录一个时刻。如果您要执行的操作是存储特定日期,请不要使用NSDate。你会得到许多与时区相关的意想不到的头痛,夏令时e.tc.

另一种解决方案是将日期作为准ISO标准格式的整数存储,例如2011年9月15日的20110915.这保证按照与NSDate排序相同的方式进行排序。 / p>

答案 5 :(得分:1)

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

extension NSDate {
    func truncateSeconds() -> NSDate {
        let roundedTime = floor(self.timeIntervalSinceReferenceDate / 60) * 60
        return NSDate(timeIntervalSinceReferenceDate: roundedTime)
    }
}

答案 6 :(得分: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)!
  }

}