NSDate
から取得しようとしてUIDatePicker
いますが、末尾が 20 秒の日付時刻が常に返されます。NSDate
の秒を手動でゼロに設定するにはどうすればよいですか?
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 年の 2 つの閏秒が追加されているため、 によって返される値は[NSDate timeIntervalSinceReferenceDate]
2 秒ずれているはずです。
これは当てはまりません: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: が処理する特別なことも考慮されることが保証されます。
これは古い質問であり、Uli は「正しい」答えを出していますが、最も簡単な解決策は、カレンダーから取得した日付から秒を差し引くことです。これにより、ミリ秒がそのまま残る場合があることに注意してください。
NSDate *date = [NSDate date];
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitSecond
fromDate:date];
date = [date dateByAddingTimeInterval:-comp.second];
Swift でこれを行うための拡張機能を次に示します。
extension NSDate {
func truncateSeconds() -> NSDate {
let roundedTime = floor(self.timeIntervalSinceReferenceDate / 60) * 60
return NSDate(timeIntervalSinceReferenceDate: roundedTime)
}
}
NSDate
一瞬一瞬を記録します。特定の日付を保存したい場合は、使用しないでくださいNSDate
。タイムゾーン、夏時間などに関連する多くの予期しない頭痛が発生します。
別の解決策の 1 つは、2011 年 9 月 15 日を表す 20110915 のように、日を準 ISO 標準形式の整数として格納することです。これは、並べ替えと同じ方法で並べ替えることが保証されていNSDate
ます。
スイフトも…
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)!
}
}