64 votes

Option de suffixe ordinal mois-jour pour NSDateFormatter setDateFormat

Quelle option setDateFormat pour NSDateFormatter dois-je utiliser pour obtenir le suffixe ordinal d'un jour du mois ?

Par exemple, l'extrait ci-dessous produit actuellement :
15:11 PM Samedi 15 août

Que dois-je changer pour obtenir :
15:11 PM Samedi 15 août th

NSDate *date = [NSDate date];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateFormat:@"h:mm a EEEE MMMM d"];
NSString *dateString = [dateFormatter stringFromDate:date]; 
NSLog(@"%@", dateString);

En PHP, je l'utiliserais dans le cas ci-dessus :
<?php echo date('h:m A l F jS') ?>

Existe-t-il un équivalent du NSDateFormatter à la fonction S dans la chaîne de formatage PHP ?

95voto

cbh2000 Points 829

Aucune de ces réponses n'était aussi esthétique que ce que j'utilise, alors j'ai pensé partager :


Swift 3 :

func daySuffix(from date: Date) -> String {
    let calendar = Calendar.current
    let dayOfMonth = calendar.component(.day, from: date)
    switch dayOfMonth {
    case 1, 21, 31: return "st"
    case 2, 22: return "nd"
    case 3, 23: return "rd"
    default: return "th"
    }
}

Objective-C :

- (NSString *)daySuffixForDate:(NSDate *)date {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSInteger dayOfMonth = [calendar component:NSCalendarUnitDay fromDate:date];
    switch (dayOfMonth) {
        case 1:
        case 21:
        case 31: return @"st";
        case 2:
        case 22: return @"nd";
        case 3:
        case 23: return @"rd";
        default: return @"th";
    }
}

Évidemment, cela ne fonctionne que pour l'anglais.

2 votes

C'est la meilleure réponse !

0 votes

@cbh2000 Pouvez-vous inclure comment concaténer ceci dans la chaîne de date. Je ne sais pas pourquoi dateFormatter.dateFormat = "F (daySuffix(date)) MM aa" ne fonctionne pas, merci !

3 votes

@BenSullivan Si vous allez le faire de cette façon, cela devrait être "F '\(daySuffix(date))' MM yy" . Remarquez les tics, qui indiquent à NSDateFormatter que "th", "st" et "rd" ne doivent pas être interprétés comme un symbole spécial.

51voto

Matt Andersen Points 2316
NSDate *date = [NSDate date];
NSDateFormatter *prefixDateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[prefixDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[prefixDateFormatter setDateFormat:@"h:mm a EEEE MMMM d"];
NSString *prefixDateString = [prefixDateFormatter stringFromDate:date];
NSDateFormatter *monthDayFormatter = [[[NSDateFormatter alloc] init] autorelease];
[monthDayFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[monthDayFormatter setDateFormat:@"d"];     
int date_day = [[monthDayFormatter stringFromDate:date] intValue];  
NSString *suffix_string = @"|st|nd|rd|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|th|st|nd|rd|th|th|th|th|th|th|th|st";
NSArray *suffixes = [suffix_string componentsSeparatedByString: @"|"];
NSString *suffix = [suffixes objectAtIndex:date_day];   
NSString *dateString = [prefixDateString stringByAppendingString:suffix];   
NSLog(@"%@", dateString);

2 votes

La seule amélioration que je pourrais apporter serait de créer simplement le tableau au lieu de le générer à partir de componentsSeparatedByString. Cela pourrait être fait facilement avec la syntaxe littérale Array @[ @"st", @"nd", @"rd", ... ] ;

1 votes

Vous avez un petit bug dans le code : NSString *suffix = [suffixes objectAtIndex:date_day] ; Cela devrait être changé en NSString *suffix = [suffixes objectAtIndex:date_day-1] ; parce que nous comptons toujours à partir de 0 :) . Sinon, bonne solution !

7 votes

En quoi cette réponse est-elle valable puisqu'elle ne tient absolument pas compte de la langue de l'utilisateur ? NSDateFormatter ne prend tout simplement pas en charge cette fonctionnalité.

15voto

SDJMcHattie Points 828

Voici une autre implémentation pour une méthode permettant de générer le suffixe. Les suffixes qu'elle produit ne sont valables qu'en anglais et peuvent ne pas être corrects dans d'autres langues :

- (NSString *)suffixForDayInDate:(NSDate *)date
{
    NSInteger day = [[[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] components:NSDayCalendarUnit fromDate:date] day];
    if (day >= 11 && day <= 13) {
        return @"th";
    } else if (day % 10 == 1) {
        return @"st";
    } else if (day % 10 == 2) {
        return @"nd";
    } else if (day % 10 == 3) {
        return @"rd";
    } else {
        return @"th";
    }
}

2 votes

Cela échoue pour un jour avec la valeur 11

1 votes

Correction facile, vérifiez d'abord si le jour = 11.

10voto

Tim Points 33042

Les formateurs de date sur Mac OS 10.5 et sur l'iPhone utilisent TR35 comme norme de spécification de format. Cette spécification ne permet pas l'utilisation d'un tel suffixe pour une date quelconque ; si vous en voulez un, vous devrez le générer vous-même.

4voto

boz Points 1175

La réponse de Matt Andersen est assez élaborée, tout comme celle de SDJMcHattie. Mais NSDateFormatter est assez lourd sur le cpu et si vous appelez cela 100x vous voyez vraiment l'impact, donc voici une solution combinée dérivée des réponses ci-dessus. (Veuillez noter que les réponses ci-dessus sont toujours correctes)

NSDateFormatter est complètement fou. coûteux pour créer. Créer une fois y réutiliser mais attention : il n'est pas thread safe, donc un par thread.

En supposant que self.date = [NSDate date] ;

   - (NSString *)formattedDate{

    static NSDateFormatter *_dateFormatter = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _dateFormatter = [[NSDateFormatter alloc] init];
        _dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
        _dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
    });

    _dateFormatter.dateFormat = [NSString stringWithFormat:@"h:mm a EEEE MMMM d'%@'", [self suffixForDayInDate:self.date]];
   NSString *date = [_dateFormatter stringFromDate:self.date];

    return date;
}

/* Le code de SDJMcHattie, c'est plus pratique que d'utiliser un tableau */.

- (NSString *)suffixForDayInDate:(NSDate *)date{
    NSInteger day = [[[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] components:NSDayCalendarUnit fromDate:date] day];
    if (day >= 11 && day <= 13) {
        return @"th";
    } else if (day % 10 == 1) {
        return @"st";
    } else if (day % 10 == 2) {
        return @"nd";
    } else if (day % 10 == 3) {
        return @"rd";
    } else {
        return @"th";
    }
}

Sortie : 15 h 11, samedi 15 août

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X