2009-10-06 3 views

答えて

12

NSDateは不変なので、時刻を変更することはできません。

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

編集ウリさんのコメントに

に答えるためにNSDateのための基準日は2001年1月1日、午後12時00分GMTです:しかし、あなたは最も近い分にスナップ新しい日付オブジェクトを作成することができます。それ以来2つの閏秒が追加されています:2005年と2010年のため、[NSDate timeIntervalSinceReferenceDate]によって返される値は2秒ずれているはずです。

これはそうではありません。timeIntervalSinceReferenceDateは、壁の時刻に正確に同期しています。

質問に答えるとき、私はこれが実際に本当であることを確認しませんでした。私はちょうどMac OSがbehave as UNIX time(1970エポック)であると仮定しました。POSIXは毎日が86,400秒の倍数で始まることを保証します。

NSDateから返された値を見ると、この仮定は正しいと思われますが、それについての明確な(文書化された)ステートメントを見つけることは間違いありません。

+4

これは機能しません。基準日からの時間間隔は、00秒の時間に対して60の偶数倍であることが保証されていません。これは基準日からの秒数であり、時折挿入されるうるう秒はあなたを捨てます。あなたはNSCalendarを使ってあなたの日付が何秒あるかを調べ、時間間隔から*を差し引かなければならないと思います。 – uliwitness

+1

現在の分が30秒のマークを超えていると、将来の時間は1分になることがあります。これはラウンドが丸くなる可能性があるために発生します。 'floor([date timeIntervalSinceReferenceDate]/60.0)* 60.0;で試してください。' –

+1

@flovonderuni良いキャッチです。ウォールクロックと同時に「フロア」スイッチの結果が表示されます。編集された答え、ありがとう! –

1

NSDateは、1つの瞬間を記録します。特定の日を保存する場合は、NSDateを使用しないでください。あなたは、タイムゾーン、夏時間e.tc.に関連する予期しない頭痛をたくさん受けるでしょう。

2011年9月15日の20110915のように、曜日をISO準標準形式で整数として格納する方法もあります。これは、NSDateと同じ方法で並べ替えることが保証されています。

10

NSTimeIntervalは、基準日からの秒単位の距離であるため、直接操作することはできません.60秒で00秒になることは保証されません。結局、うるう秒はソーラータイムとUTCの差を調整するために挿入されます。各うるう秒は、私が0に私の日付の秒を修正するために何1.によってあなたを投げるだろうです:

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がいることを保証しているその方法:だけでなく計上されたの世話をします。

+1

'timeIntervalSinceReferenceDate'に影響を与えるうるう秒についてのあなたの主張は真実ではないと思います。 Appleの「日付と時刻のプログラミングガイド」では明示的に動作を定義していませんが、POSIXはUNIXの場合にそうしています。うるう秒は無視されます(http://en.wikipedia.org/wiki/Unix_time参照)。これはココアにも当てはまると思われます。 –

+1

もう1つの考え方:提案されている解決方法はどちらも秒数を考慮していません。 (整数)秒数を計算し、元の日付から減算します。結果は、0秒の時間ですが、ゼロ以外のミリ秒です。少し奇数です。 –

2

これは古い質問ですが、Uliは「正しい」答えを示していますが、最も単純な解決策は、カレンダーから取得した日付から秒を差し引くことです。これはまだミリ秒の場所が残っているかもしれないことを覚えておいてください。ここで

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

はスウィフトでこれを行うに拡張したものである:ここでは

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

は興味を持っている人のためスウィフト拡張したものです:

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は、日付に時間間隔を追加するよりはるかに堅牢です。

関連する問題