2009-10-06 6 views

Antwort

12

NSDate ist unveränderbar, daher kann die Zeit nicht geändert werden. Sie können jedoch ein neues Date-Objekt erstellen, die auf die nächste Minute schnappt:

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

bearbeiten zu Ulis Kommentar

Das Referenzdatum verantworten NSDate ist 1. Januar 2001, 0:00 Uhr GMT. Seither wurden zwei Schaltsekunden hinzugefügt: 2005 und 2010, daher sollte der von [NSDate timeIntervalSinceReferenceDate] zurückgegebene Wert um zwei Sekunden abweichen. Dies ist nicht der Fall: timeIntervalSinceReferenceDate ist genau synchron zur Wandzeit

Bei der Beantwortung der Frage habe ich nicht sichergestellt, dass dies tatsächlich wahr ist. Ich habe einfach angenommen, dass Mac OS behave as UNIX time (1970 Epoche) tut: POSIX garantiert, dass jeder Tag mit einem Vielfachen von 86.400 Sekunden beginnt.

Mit Blick auf die Werte von NSDate scheint diese Annahme korrekt zu sein, aber es wäre sicher schön, eine definitive (dokumentierte) Aussage darüber zu finden.

+4

Dies wird nicht funktionieren. Das Zeitintervall seit dem Referenzdatum ist nicht garantiert, ein gerades Vielfaches von 60 für eine Zeit zu sein, die 00 Sekunden hat. Es ist die Anzahl der Sekunden seit dem Referenzdatum, und daher werden Schaltsekunden, die gelegentlich eingefügt werden, Sie davon abhalten. Ich denke, Sie müssen NSCalendar verwenden, um herauszufinden, welche Sekunden Ihr Datum hat, dann subtrahieren Sie * das * vom Zeitintervall. – uliwitness

+1

Die Zeit, die Sie erhalten, kann eine Minute in der Zukunft sein, wenn die aktuelle Minute die 30-Sekunden-Marke überschreitet. Dies geschieht, weil Runde runden könnte. Versuchen Sie es mit 'floor ([Datum timeIntervalSinceReferenceDate]/60.0) * 60.0;' –

+1

@flovonderuni Guter Fang. Die Ergebnisse von 'floor' schalten gleichzeitig Wanduhren. Bearbeitete Antwort, danke! –

1

NSDate zeichnet einen einzigen Zeitpunkt auf. Wenn Sie einen bestimmten Tag speichern möchten, verwenden Sie nicht NSDate. Sie werden viele unerwartete Kopfschmerzen in Bezug auf Zeitzonen, Sommerzeit e.tc.

Eine alternative Lösung besteht darin, den Tag als Integer im Quasi-ISO-Standardformat zu speichern, wie 20110915 für den 15. September 2011. Dies wird garantiert auf die gleiche Weise sortiert wie NSDate sortieren würde.

10

Sie können NSTimeInterval nicht direkt manipulieren, da dies die Entfernung in Sekunden seit dem Referenzdatum ist, die nicht garantiert ist, eine 00-Sekunden-Zeit zu sein, wenn sie durch 60 geteilt wird eingefügt, um die Unterschiede zwischen Sonnenzeit und UTC anzupassen. Jeder Schaltsekunde würde werfen Sie weg von 1. Was ich tun, um die Sekunden meines Zeitpunkt 0 zu beheben ist:

NSDate    * startDateTime = [NSDate date]; 
NSDateComponents * startSeconds = [[NSCalendar currentCalendar] components: NSSecondCalendarUnit fromDate: startDateTime]; 

startDateTime = [NSDate dateWithTimeIntervalSinceReferenceDate: [startDateTime timeIntervalSinceReferenceDate] -[startSeconds second]]; 

Diese kümmert sich um Schaltsekunden. Ich denke, eine noch sauberere Weg wäre -dateByAddingComponents zu verwenden:

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]; 

diese Weise werden Sie garantiert sind, dass das, was das Besondere -dateByAddingComponents: kümmert sich um für als auch berücksichtigt wird.

+1

Ich glaube, Ihre Behauptung über Schaltsekunden, die das 'timeIntervalSinceReferenceDate 'beeinflussen, ist nicht wahr. Während Apples Date and Time Programming Guide das Verhalten nicht explizit definiert, macht POSIX dies für die UNIX-Zeit: Leap-Sekunden werden ignoriert (siehe http://en.wikipedia.org/wiki/Unix_time). Es scheint, dass dies auch für Cocoa gilt. –

+1

Ein weiterer Gedanke: Beide von Ihnen vorgeschlagenen Lösungen berücksichtigen keine Bruchteile von Sekunden. Sie berechnen die (ganzzahlige) Anzahl von Sekunden und subtrahieren sie vom ursprünglichen Datum. Das Ergebnis bezieht sich auf eine Zeit mit null Sekunden, aber nicht null Millisekunden, was ein bisschen seltsam ist. –

2

Obwohl dies eine alte Frage ist und Uli die "richtige" Antwort gegeben hat, ist die einfachste Lösung IMHO, einfach die Sekunden vom Datum zu subtrahieren, wie es aus dem Kalender kommt. Beachten Sie, dass dies immer noch Millisekunden an Ort und Stelle bleiben kann.

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

Hier ist eine Erweiterung dieses in Swift zu tun:

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

ist hier ein Swift-Erweiterung für alle Interessierten:

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

Beispiel Nutzung:

let date = Date() 
date.floorSeconds() 

Verwenden DateComponents ist viel robuster als das Hinzufügen eines Zeitintervalls zu einem Datum.

Verwandte Themen