NSDate erhalten Jahr / Monat / Tag

291

Wie kann ich das Jahr / den Monat / den Tag eines NSDateObjekts ohne weitere Informationen abrufen? Mir ist klar, dass ich das wahrscheinlich mit etwas Ähnlichem machen könnte:

NSCalendar *cal = [[NSCalendar alloc] init];
NSDateComponents *components = [cal components:0 fromDate:date];
int year = [components year];
int month = [components month];
int day = [components day];

Aber das scheint eine Menge Ärger für etwas so Einfaches wie das Erhalten eines NSDateJahres / Monats / Tages zu sein. Gibt es eine andere Lösung?

Richard J. Ross III
quelle
4
Ich hatte einige Probleme mit diesem Code, bis ich die erste Zeile in "NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];" änderte. Die API muss geändert worden sein, seit diese Frage gestellt wurde.
Russell Thackston
@ futureelite7 wurde auf Revision 1 zurückgesetzt. Der Code dort dient historischen Zwecken und war eine einfache Erklärung für meine ursprüngliche Idee.
Richard J. Ross III
Der Code funktioniert nicht mehr. Können Sie den richtigen Code notieren?
futureelite7
@ futureelite7 no. Dieser Code war eine Demonstration meines ersten Versuchs, er sollte nie funktionieren. Wenn Sie der Meinung sind, dass dies nicht eindeutig ist, können Sie den Kontext um diesen Codeblock bearbeiten, aber den Code selbst nicht bearbeiten. Wenn Sie extrem stark daran interessiert sind, den Code selbst zu bearbeiten, nehmen Sie diese Abdeckung bitte zu Meta und wir werden sehen, was andere Mods zu sagen haben.
Richard J. Ross III
8
@mike deshalb liest du die Antworten, nicht die Frage.
Richard J. Ross III

Antworten:

615

Da dies anscheinend meine beliebteste Antwort ist, werde ich versuchen, sie zu bearbeiten, um ein bisschen mehr Informationen zu enthalten.

Trotz seines Namens NSDatemarkiert es an und für sich nur einen Zeitpunkt in der Maschine, kein Datum. Es gibt keine Korrelation zwischen dem durch a NSDateund einem Jahr, Monat oder Tag angegebenen Zeitpunkt . Dafür müssen Sie sich auf einen Kalender beziehen. Jeder gegebene Zeitpunkt gibt unterschiedliche Datumsinformationen zurück, je nachdem, welchen Kalender Sie betrachten (Datumsangaben sind beispielsweise im gregorianischen und im jüdischen Kalender nicht gleich), und während der gregorianische Kalender der am häufigsten verwendete Kalender im Kalender ist Welt - ich nehme an - wir sind ein wenig voreingenommen, das NSDatesollte es immer benutzen. NSDateZum Glück ist es viel parteiübergreifender.


NSCalendarWie Sie bereits erwähnt haben, müssen Datum und Uhrzeit ermittelt werden , aber es gibt einen einfacheren Weg, dies zu tun:

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];

Dadurch wird NSDateComponentsaus dem aktuellen Systemkalender für den aktuellen Tag ein Objekt generiert , das Tag, Monat und Jahr enthält. ( Hinweis: Dies ist nicht unbedingt der aktuelle benutzerdefinierte Kalender, sondern nur der Standardsystemkalender.)

Wenn Sie einen anderen Kalender oder ein anderes Datum verwenden, können Sie dies natürlich leicht ändern. Eine Liste der verfügbaren Kalender und Kalendereinheiten finden Sie in der NSCalendarKlassenreferenz . Weitere Informationen NSDateComponentszu finden Sie in der NSDateComponentsKlassenreferenz .


Als Referenz ist der Zugriff auf einzelne Komponenten von der NSDateComponentsziemlich einfach:

NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];

Sie müssen nur aufpassen: Sie NSDateComponentsenthalten keine gültigen Informationen für Felder, nach denen Sie fragen, es sei denn, Sie haben sie mit diesen gültigen Informationen generiert (dh Sie müssen diese NSCalendarInformationen mit NSCalendarUnits versehen). NSDateComponentsenthalten keine Referenzinformationen an und für sich - es handelt sich lediglich um einfache Strukturen, die Nummern enthalten, auf die Sie zugreifen können. Wenn Sie beispielsweise auch eine Ära beenden möchten NSDateComponents, müssen Sie die Generatormethode NSCalendarmit dem NSCalendarUnitEraFlag füttern .

Itai Ferber
quelle
3
Um dies zu korrigieren, sollte die erste Zeile NSDayCalendarUnit anstelle von NSWeekCalendarUnit haben.
Whitehawk
@Erik Welchen Kalender benutzt du? Code?
Itai Ferber
7
@Jonny Die Ergebnisse hängen vom verwendeten Kalender ab. NSCalendarDie +currentCalendarMethode gibt den Systemkalender zurück. Wenn das Telefon des Benutzers auf den japanischen oder thailändischen Zeitmodus eingestellt ist, erhalten Sie ein anderes Jahr. Wenn Sie ein bestimmtes Kalendersystem erzwingen möchten, erstellen Sie einen Kalender und initialisieren Sie ihn mit dem richtigen Gebietsschema. Um beispielsweise einen Gregorianischen Kalender zu erzwingen, sollten Sie Folgendes verwenden:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
Itai Ferber
2
Aufzählungen NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit sind DEPRECATED Verwenden Sie stattdessen NSCalendarUnitDay.
Kunal Balani
2
Warnung: Verwenden Sie [NSCalendar currentCalendar] nur, wenn Sie versuchen, dem Benutzer einen Wert anzuzeigen. Bedenken Sie, dass Benutzer möglicherweise einem buddhistischen Kalender (das Jahr ist jetzt 2558 oder so) oder einer anderen Anzahl von ungeraden Kalendern folgen. Sie möchten in diesen Fällen nicht, dass Ihre App kaputt geht. Verwenden Sie den gregorianischen Kalender, es sei denn, Sie haben einen bestimmten Grund, dies nicht zu tun. Dieser Fehler ist schwer zu erkennen, da Sie und Ihre Tester möglicherweise alle gregorian als Standard verwenden.
n13
51

Mit NSDateFormatter können Sie eine separate Komponente eines NSDate abrufen:

NSDateFormatter *df = [[NSDateFormatter alloc] init];

[df setDateFormat:@"dd"];
myDayString = [df stringFromDate:[NSDate date]];

[df setDateFormat:@"MMM"];
myMonthString = [df stringFromDate:[NSDate date]];

[df setDateFormat:@"yy"];
myYearString = [df stringFromDate:[NSDate date]];

Wenn Sie die Monatsnummer anstelle der Abkürzung erhalten möchten, verwenden Sie "MM". Wenn Sie Ganzzahlen erhalten möchten, verwenden Sie[myDayString intValue];

skocko76
quelle
1
Erweitert auf seine mit diesem Kern . Viel Spaß - Sie können dies in Ihren Code einfügen.
DogEatDog
Ich habe mein Problem behoben, dass ich Daten zum Nachschlagen in einem Wörterbuch verwendet habe :) Danke!
mlunoe
1
Dies funktioniert nicht immer zu 100% wie erwartet. Wenn das NSDate beispielsweise 2013-12-31 00:00:00 +0000 ist, gibt das formatierte Datum 2014 für das Jahr zurück, selbst wenn die tatsächliche Zahl im Datum 2013 ist.
Margusholland
Wie kann ich den Tag des Jahres bekommen, zB der 10. April ist der aktuelle Tag ist der 99. Tag des laufenden Jahres? -
iOS-Entwickler
17

Um Itais exzellenten (und funktionierenden!) Code neu zu formulieren, würde eine Beispiel-Hilfsklasse wie folgt aussehen, um den Jahreswert einer bestimmten NSDate-Variablen zurückzugeben.

Wie Sie sehen können, ist es einfach genug, diesen Code zu ändern, um den Monat oder den Tag zu erhalten.

+(int)getYear:(NSDate*)date
{
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:date];

    int year = [components year];
    int month = [components month];
    int day = [components day];

    return year;
}

(Ich kann nicht glauben, dass wir 2013 unsere eigenen grundlegenden iOS-Datumsfunktionen wie diese schreiben müssen ...)

Eine andere Sache: Verwenden Sie niemals <und>, um zwei NSDate-Werte zu vergleichen.

XCode akzeptiert diesen Code gerne (ohne Fehler oder Warnungen), aber seine Ergebnisse sind eine Lotterie. Sie müssen die Funktion "Vergleichen" verwenden, um NSDates zu vergleichen:

if ([date1 compare:date2] == NSOrderedDescending) {
    // date1 is greater than date2        
}
Mike Gledhill
quelle
4
Die Ergebnisse des Zeigervergleichs sind weit entfernt von einer Lotterie - sie haben sehr gut definierte Ergebnisse, solange Sie sie für das verwenden, wofür sie bestimmt sind - den Vergleich von Zeigern, nicht von Objekten.
Richard J. Ross III
Es ist vielleicht keine Lotterie, aber C #s DateTime ist weitaus intuitiver. In iOS sollte der Operator "weniger als" wirklich zwei NSDates vergleichen ... möchte jemand wirklich die Zeiger von zwei NSDate-Variablen vergleichen? Zumindest zeigt XCode show eine Warnung an, um zu fragen, ob dies wirklich das ist, was der Benutzer wirklich meint.
Mike Gledhill
1
Das ist nur ein Zeichen für einen faulen Codierer, der die Grundlagen der Sprache, in der er schreibt, nicht versteht. Und es gab Situationen für mich, in denen Zeigervergleiche für ObjC-Objekte erforderlich sind - insbesondere, wenn Sie einen benutzerdefinierten Container erstellen (obwohl Mit ARC wird es seltsamer.
Richard J. Ross III
1
Ich muss ein fauler Programmierer sein, der die Grundlagen nicht versteht, aber das ist ein großartiger Tipp, Mike!
Pier-Luc Gendreau
4
Zeigervergleiche können erforderlich sein, sind jedoch der weitaus seltenere Anwendungsfall beim Vergleich zweier Daten. In 99,99% der Fälle wäre ein Programmierer eher daran interessiert, die Daten als die Zeiger zu vergleichen. Grundsätzlich wurden C # und das .NET-Framework entwickelt, um die gängigsten Szenarien zu vereinfachen und so die Produktivität von Programmierern zu steigern. In vielen Fällen scheint Objective-C die Dinge absichtlich schwieriger zu machen. Wenn Sie Zeit haben, ein 800-seitiges Buch über die Grundlagen jeder Sprache zu lesen, jubeln Sie, aber der Rest von uns hat Apps, die Sie pünktlich und im Rahmen des Budgets bereitstellen können.
Crake
16

In Swift 2.0:

    let date = NSDate()
    let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
    let components = calendar.components([.Month, .Day], fromDate: date)

    let (month, day) = (components.month, components.day)
NatashaTheRobot
quelle
11

Ich schreibe diese Antwort, weil es der einzige Ansatz ist, der Ihnen keine NSDateComponentOptionen von Variablen zurückgibt und / oder das Entpacken dieser Variablen erzwingt (auch für Swift 3).

Swift 3

let date = Date()
let cal = Calendar.current
let year = cal.component(.year, from: date)
let month = cal.component(.month, from: date)
let day = cal.component(.day, from: date)

Swift 2

let date = NSDate()
let cal = NSCalendar.currentCalendar()
let year = cal.component(.Year, fromDate: date)
let month = cal.component(.Month, fromDate: date)
let day = cal.component(.Day, fromDate: date)

Bonus Swift 3 lustige Version

let date = Date()
let component = { (unit) in return Calendar.current().component(unit, from: date) }
let year = component(.year)
let month = component(.month)
let day = component(.day)
Kevin
quelle
Wie kann ich den Tag des Jahres bekommen, zB der 10. April ist der aktuelle Tag ist der 99. Tag des laufenden Jahres? -
iOS-Entwickler
Und stellen Sie sicher, dass Sie den Gregorianischen Kalender verwenden, z. B. die
Jahreskomponente
8

Neu in iOS 8

ObjC

NSDate *date = [NSDate date];
NSInteger era, year, month, day;
[[NSCalendar currentCalendar] getEra:&era year:&year month:&month day:&day fromDate:date];

Schnell

let date = NSDate.init()
var era = 0, year = 0, month = 0, day = 0
NSCalendar.currentCalendar().getEra(&era, year:&year, month:&month, day:&day, fromDate: date)
Yuchen Zhong
quelle
2
Tolle! @ Yuchen Zhong
Lito
1
Brillant ! Viel bessere Syntax!
Joan
4

Wenn Sie auf iOS 8+ abzielen, können Sie die neuen NSCalendarKomfortmethoden verwenden, um dies in einem knapperen Format zu erreichen.

Erstellen Sie zuerst eine NSCalendarund verwenden Sie alles, was NSDateerforderlich ist.

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [NSDate date];

Sie können Komponenten einzeln über extrahieren component:fromDate:

NSInteger year = [calendar component:NSCalendarUnitYear fromDate:date];
NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:date];
NSInteger day = [calendar component:NSCalendarUnitDay fromDate:date];

Oder, noch prägnanter, verwenden Sie NSIntegerZeiger übergetEra:year:month:day:fromDate:

NSInteger year, month, day;
[calendar getEra:nil year:&year month:&month day:&day fromDate:date];

Weitere Informationen und Beispiele finden Sie unter NSDate-Manipulation leicht gemacht in iOS 8 . Haftungsausschluss, ich habe den Beitrag geschrieben.

Joe Masilotti
quelle
Wie kann ich den Tag des Jahres bekommen, zB der 10. April ist der aktuelle Tag ist der 99. Tag des laufenden Jahres? -
iOS-Entwickler
4

Ab iOS 8.0 (und OS X 10) können Sie die Komponentenmethode verwenden, um das Abrufen einer einzelnen Datumskomponente wie folgt zu vereinfachen:

int year = [[NSCalendar currentCalendar] component:NSCalendarUnitYear fromDate:[NSDate date]];

Sollte die Dinge einfacher machen und hoffentlich wird dies effizient umgesetzt.

Christopher King
quelle
2
    NSDate *currDate = [NSDate date];
    NSCalendar*       calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents* components = [calendar components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:currDate];
    NSInteger         day = [components day];
    NSInteger         month = [components month];
    NSInteger         year = [components year];
    NSLog(@"%d/%d/%d", day, month, year);
Linh Nguyen
quelle
Das gibt mir ganz klar nicht das Jahr, den Monat oder den Tag als Ganzzahl an, was ich im OP angefordert habe. -1.
Richard J. Ross III
1
Richard J. Ross III: Ich habe es gerade behoben. Es tut mir leid, weil meine Antwort Ihre Frage verloren hat.
Linh Nguyen
2

Hier ist die Lösung in Swift:

let todayDate = NSDate()
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!

// Use a mask to extract the required components. Extract only the required components, since it'll be expensive to compute all available values.
let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: todayDate)

var (year, month, date) = (components.year, components.month, components.day) 
Nitin Nain
quelle
2

Versuche dies . . .

Code-Auszug:

 NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
 int year = [components year];
 int month = [components month];
 int day = [components day];

Es gibt das aktuelle Jahr, den Monat und das Datum an

Yogeesh HT
quelle
1

Versuche Folgendes:

    NSString *birthday = @"06/15/1977";
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"MM/dd/yyyy"];
    NSDate *date = [formatter dateFromString:birthday];
    if(date!=nil) {
        NSInteger age = [date timeIntervalSinceNow]/31556926;
        NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
        NSInteger day = [components day];
        NSInteger month = [components month];
        NSInteger year = [components year];

        NSLog(@"Day:%d Month:%d Year:%d Age:%d",day,month,year,age);
    }
    [formatter release];
loretoparisi
quelle
1

Swift 2.x.

extension NSDate {
    func currentDateInDayMonthYear() -> String {
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "d LLLL yyyy"
        return dateFormatter.stringFromDate(self)
    }
}

Sie können es als verwenden

NSDate().currentDateInDayMonthYear()

Ausgabe

6 March 2016
Alserda
quelle
1

Schnell

Einfachere Möglichkeit, Datumselemente als optionale Zeichenfolge abzurufen.

extension Date {

  // Year 
  var currentYear: String? {
    return getDateComponent(dateFormat: "yy")
    //return getDateComponent(dateFormat: "yyyy")
  }

  // Month 
  var currentMonth: String? {
    return getDateComponent(dateFormat: "M")
    //return getDateComponent(dateFormat: "MM")
    //return getDateComponent(dateFormat: "MMM")
    //return getDateComponent(dateFormat: "MMMM")
  }


  // Day
  var currentDay: String? {
    return getDateComponent(dateFormat: "dd")
    //return getDateComponent(dateFormat: "d")
  }


  func getDateComponent(dateFormat: String) -> String? {
    let format = DateFormatter()
    format.dateFormat = dateFormat
    return format.string(from: self)
  }


}

let today = Date()
print("Current Year - \(today.currentYear)")  // result Current Year - Optional("2017")
print("Current Month - \(today.currentMonth)")  // result Current Month - Optional("7")
print("Current Day - \(today.currentDay)")  // result Current Day - Optional("10")
Krunal
quelle
0

ich mache auf diese Weise ....

NSDate * mydate = [NSDate date];

NSCalendar * mycalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSCalendarUnit units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;

NSDateComponents * myComponents  = [mycalendar components:units fromDate:mydate];

NSLog(@"%d-%d-%d",myComponents.day,myComponents.month,myComponents.year);
Shaik Riyaz
quelle
0

Um eine vom Menschen lesbare Zeichenfolge (Tag, Monat, Jahr) zu erhalten, können Sie Folgendes tun:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *string = [dateFormatter stringFromDate:dateEndDate];
Mirap
quelle