NSDate obtenir année / mois / jour

291

Comment puis-je obtenir l'année / mois / jour d'un NSDateobjet, sans autre information? Je me rends compte que je pourrais probablement faire cela avec quelque chose de similaire à ceci:

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

Mais cela semble être beaucoup de tracas pour quelque chose d'aussi simple que d'obtenir une NSDateannée / mois / jour. N 'y a-t-il pas une autre solution?

Richard J. Ross III
la source
4
J'ai eu un peu de mal à utiliser ce code jusqu'à ce que je change la première ligne en "NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];" Il doit y avoir eu un changement dans l'API depuis que cette question a été posée.
Russell Thackston
@ futureelite7 est revenu à la révision 1. Le code qu'il contient est à des fins historiques et était une simple explication de mon idée initiale.
Richard J. Ross III
Le code ne fonctionne plus. Pouvez-vous noter le bon code?
futureelite7
@ futureelite7 no. Ce code était une démonstration de ma première tentative, il n'a jamais été conçu pour fonctionner. Si vous pensez que cela est ambigu, n'hésitez pas à modifier le contexte entourant ce bloc de code, mais ne modifiez pas le code lui-même. Si vous êtes extrêmement convaincu de la modification du code lui-même, veuillez prendre cette couverture en méta et nous verrons ce que les autres mods ont à dire.
Richard J. Ross III
8
@mike c'est pourquoi vous lisez les réponses, pas la question.
Richard J. Ross III

Réponses:

615

Parce que c'est apparemment ma réponse la plus populaire, je vais essayer de la modifier pour contenir un peu plus d'informations.

Malgré son nom, NSDateen soi, il marque simplement un point dans le temps de la machine, pas une date. Il n'y a pas de corrélation entre le moment spécifié par un NSDateet un an, un mois ou un jour. Pour cela, vous devez vous référer à un calendrier. Tout moment donné renverra des informations de date différentes en fonction du calendrier que vous regardez (les dates ne sont pas les mêmes dans les calendriers grégorien et juif, par exemple), et bien que le calendrier grégorien soit le calendrier le plus utilisé dans le monde - je suppose - nous sommes un peu biaisés qui NSDatedevraient toujours l'utiliser. NSDate, heureusement, est beaucoup plus bipartite.


Obtenir la date et l'heure devra passer NSCalendar, comme vous l'avez mentionné, mais il existe un moyen plus simple de le faire:

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

Cela génère un NSDateComponentsobjet contenant le jour, le mois et l'année à partir du calendrier système actuel pour le jour en cours. ( Remarque: ce n'est pas nécessairement le calendrier actuel spécifié par l'utilisateur , juste celui par défaut du système.)

Bien sûr, si vous utilisez un calendrier ou une date différents, vous pouvez facilement changer cela. Une liste des calendriers et des unités de calendrier disponibles se trouve dans la NSCalendarréférence de classe . Plus d'informations sur NSDateComponentspeuvent être trouvées dans la NSDateComponentsréférence de classe .


Pour référence, l'accès à des composants individuels depuis le NSDateComponentsest assez simple:

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

Vous devez juste être conscient: NSDateComponentsne contiendra pas d'informations valides pour les champs que vous demandez, sauf si vous les avez générés avec ces informations valides (c'est- NSCalendarà- dire demander à fournir ces informations avec NSCalendarUnits). NSDateComponentsne contiennent aucune information de référence en soi - ce ne sont que de simples structures qui contiennent des numéros auxquels vous pouvez accéder. Si vous voulez également sortir une ère, par exemple NSDateComponents, vous devrez alimenter la méthode du générateur NSCalendaravec le NSCalendarUnitEradrapeau.

Itai Ferber
la source
3
Une correction à cela, la première ligne devrait avoir NSDayCalendarUnit au lieu de NSWeekCalendarUnit.
whitehawk
@Erik Quel calendrier utilisez-vous? Code?
Itai Ferber
7
@Jonny Les résultats que vous obtenez dépendent du calendrier que vous utilisez. NSCalendarLa +currentCalendarméthode de retourne le calendrier système, et donc si le téléphone de l'utilisateur est réglé sur le mode japonais ou thaïlandais, vous obtiendrez une année différente. Si vous souhaitez forcer un système de calendrier spécifique, créez un calendrier et initialisez-le avec les paramètres régionaux appropriés. Par exemple, pour forcer un calendrier grégorien, vous voudrez utiliser ce qui suit:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
Itai Ferber
2
énumère NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit sont obsolètes, utilisez plutôt NSCalendarUnitDay.
Kunal Balani
2
Avertissement: n'utilisez pas [NSCalendar currentCalendar] sauf si vous essayez d'afficher une valeur à l'utilisateur. Considérez que les utilisateurs peuvent suivre un calendrier bouddhiste (l'année est maintenant 2558 ou quelque chose), ou tout autre nombre de calendriers impairs. Vous ne voulez pas que votre application se casse dans ces cas. Utilisez le calendrier grégorien, sauf si vous avez une raison très spécifique de ne pas le faire. Ce bogue est difficile à détecter car vous et vos testeurs pouvez tous utiliser gregorian par défaut.
n13
51

Vous pouvez obtenir un composant distinct d'une NSDate à l'aide de NSDateFormatter:

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

Si vous souhaitez obtenir le numéro du mois au lieu de l'abréviation, utilisez "MM". Si vous souhaitez obtenir des entiers, utilisez[myDayString intValue];

skocko76
la source
1
Développé le sien avec cet essentiel . Amusez-vous --- vous pouvez le déposer dans votre code.
DogEatDog
Résolu mon problème d'utilisation de dates pour rechercher dans un dictionnaire :) Merci!
mlunoe
1
Cela ne fonctionne pas à 100% comme prévu tout le temps. Par exemple, si le NSDate est 2013-12-31 00:00:00 +0000, la date formatée renverra 2014 pour l'année, même si le nombre réel dans la date est 2013.
margusholland
comment puis-je obtenir le jour de l'année, par exemple le 10 avril est le jour actuel est le 99e jour de l'année en cours ?? -
Développeur iOS
17

Juste pour reformuler l'excellent code d'Itai (et qui fonctionne!), Voici à quoi ressemblerait un exemple de classe d'aide, pour renvoyer la valeur de l' année d'une variable NSDate donnée.

Comme vous pouvez le voir, il est assez facile de modifier ce code pour obtenir le mois ou le jour.

+(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;
}

(Je ne peux pas croire que nous devions écrire nos propres fonctions de date iOS de base comme ça, en 2013 ...)

Autre chose: n'utilisez jamais <et> pour comparer deux valeurs NSDate.

XCode acceptera volontiers ce code (sans erreur ni avertissement), mais ses résultats sont une loterie. Vous devez utiliser la fonction "comparer" pour comparer les NSDates:

if ([date1 compare:date2] == NSOrderedDescending) {
    // date1 is greater than date2        
}
Mike Gledhill
la source
4
Les résultats de la comparaison de pointeurs sont loin d'être une loterie - ils ont des résultats très bien définis, tant que vous les utilisez pour ce à quoi ils sont destinés - comparer des pointeurs, pas des objets.
Richard J. Ross III
Ce n'est peut-être pas une loterie, mais DateTime de C # est beaucoup plus intuitif. Dans iOS, l'opérateur inférieur à devrait vraiment comparer deux NSDates ... quelqu'un voudrait-il vraiment comparer les pointeurs de deux variables NSDate? À tout le moins, XCode show affiche un avertissement pour demander si c'est vraiment ce que l'utilisateur veut vraiment dire.
Mike Gledhill
1
C'est juste le signe d'un codeur paresseux qui ne comprend pas les principes fondamentaux de la langue dans laquelle il écrit. Et il y a eu des situations pour moi où des comparaisons de pointeurs sont nécessaires pour les objets ObjC - surtout si vous créez un conteneur personnalisé (bien que les choses deviennent plus étranges avec ARC).
Richard J. Ross III
1
Je dois être un codeur paresseux qui ne comprend pas les principes fondamentaux, mais c'est un excellent conseil Mike!
Pier-Luc Gendreau
4
Des comparaisons de pointeurs peuvent être nécessaires, mais elles constituent le cas d'utilisation beaucoup moins courant lors de la comparaison de deux dates. 99,99% du temps, tout programmeur serait plus intéressé à comparer les dates plutôt que les pointeurs. Fondamentalement, C # et le framework .NET ont été conçus pour faciliter les scénarios les plus courants, rendant ainsi les programmeurs plus productifs, et dans de nombreux cas, objective-c a l'impression que cela rend les choses intentionnellement plus ardues. Si vous avez le temps de lire un livre de 800 pages sur les principes fondamentaux de chaque langue, merci, mais le reste d'entre nous ont des applications à livrer dans les délais et le budget.
Crake
16

Dans 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
la source
11

J'écris cette réponse parce que c'est la seule approche qui ne vous redonne pas les options des NSDateComponentvariables et / ou ne force pas le déballage de ces variables (également pour 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)

Version amusante bonus Swift 3

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
la source
comment puis-je obtenir le jour de l'année, par exemple le 10 avril est le jour actuel est le 99e jour de l'année en cours ?? -
Développeur iOS
Et assurez-vous d'utiliser le calendrier grégorien, par exemple le composant année pour le calendrier japonais renvoie 1 chiffre.
Flovettee
8

Nouveau dans iOS 8

ObjC

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

Rapide

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
la source
2
Incroyable! @Yuchen Zhong
Lito
1
Brillant ! Bien meilleure syntaxe!
joan
4

Si vous ciblez iOS 8+, vous pouvez utiliser les nouvelles NSCalendarméthodes pratiques pour y parvenir dans un format plus concis.

Créez d'abord un NSCalendaret utilisez ce qui NSDateest nécessaire.

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

Vous pouvez extraire les composants individuellement via component:fromDate:

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

Ou, encore plus succinctement, utilisez des NSIntegerpointeurs viagetEra:year:month:day:fromDate:

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

Pour plus d'informations et d'exemples, consultez NSDate Manipulation Made Easy dans iOS 8 . Avertissement, j'ai écrit le message.

Joe Masilotti
la source
comment puis-je obtenir le jour de l'année, par exemple le 10 avril est le jour actuel est le 99e jour de l'année en cours ?? -
Développeur iOS
4

Depuis iOS 8.0 (et OS X 10), vous pouvez utiliser la méthode des composants pour simplifier l'obtention d'un composant de date unique comme ceci:

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

Cela devrait simplifier les choses et, espérons-le, cela sera mis en œuvre efficacement.

Christopher King
la source
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
la source
Cela ne me donne clairement pas l'année, le mois ou le jour sous forme d'entier, ce que j'ai demandé dans le PO. -1.
Richard J. Ross III
1
Richard J. Ross III: Je viens de le corriger, je suis désolé car ma réponse a été perdue votre question.
Linh Nguyen du
2

Voici la solution dans 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
la source
2

Essaye ça . . .

Extrait de code:

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

Il donne l'année en cours, le mois, la date

Yogeesh HT
la source
1

Essayez ce qui suit:

    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
la source
1

Swift 2.x

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

Vous pouvez l'utiliser comme

NSDate().currentDateInDayMonthYear()

Production

6 March 2016
Alserda
la source
1

Rapide

Un moyen plus simple d'obtenir tous les éléments de la date sous forme de chaîne facultative.

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
la source
0

je fais de cette façon ....

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
la source
0

Pour obtenir une chaîne lisible par l'homme (jour, mois, année), vous pouvez faire:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *string = [dateFormatter stringFromDate:dateEndDate];
mirap
la source