web-dev-qa-db-fra.com

Option de suffixe jour-mois ordinale pour NSDateFormatter setDateFormat

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

par exemple. l'extrait ci-dessous produit actuellement:
3:11 PM samedi 15 août

Que dois-je changer pour obtenir:
3: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 pour le cas ci-dessus:
<?php echo date('h:m A l F jS') ?>

Existe-t-il un équivalent NSDateFormatter de l'optionSdans la chaîne de formatage PHP?

55
Matt Andersen
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);
54
Matt Andersen

Aucune de ces réponses n’étant aussi esthétique que ce que j’utilise, 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"
    }
}

Objectif 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.

88
cbh2000

Cela se fait facilement à partir de iOS9

NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterOrdinalStyle;
NSArray<NSNumber *> *numbers = @[@1, @2, @3, @4, @5];

for (NSNumber *number in numbers) {
    NSLog(@"%@", [formatter stringFromNumber:number]);
}
// "1st", "2nd", "3rd", "4th", "5th"

Tiré de NSHipster

Swift 2.2:

let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .OrdinalStyle
let numbers: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for number in numbers {
    print(numberFormatter.stringFromNumber(number)!)
}
26
Ger

Voici une autre implémentation pour une méthode permettant de générer le suffixe. Les suffixes qu'il 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";
    }
}
16
SDJMcHattie

Les formateurs de date sur Mac OS 10.5 et l’iPhone utilisent TR35 comme spécificateur de format standard. Cette spécification ne permet pas un tel suffixe à aucune date; si vous en voulez un, vous devrez le générer vous-même.

9
Tim

La réponse de Matt Andersen est assez élaborée, de même que SDJMcHattie. Mais NSDateFormatter est assez lourd sur le processeur et si vous appelez cela 100x, vous voyez vraiment l'impact, voici donc 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 follement cher à créer. Créez une fois et réutilisez , mais méfiez-vous: ce 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: 15h11 PM Samedi 15 août

4
Edwin

Le formatage s’effectue en deux étapes: d’abord, créez une sous-chaîne avec le suffixe approprié correspondant au jour, puis créez une chaîne de format pour les parties restantes, en y intégrant le jour déjà formaté.

func ordinalDate(date: Date) -> String {
    let ordinalFormatter = NumberFormatter()
    ordinalFormatter.numberStyle = .ordinal
    let day = Calendar.current.component(.day, from: date)
    let dayOrdinal = ordinalFormatter.string(from: NSNumber(value: day))!

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "h:mm a EEEE MMMM '\(dayOrdinal)'"
    return dateFormatter.string(from: Date())
}

Puisque le jour ordinal est construit par NumberFormatter, il devrait fonctionner dans toutes les langues, pas seulement en anglais.

Vous pouvez obtenir une chaîne de format ordonnée pour l'environnement local actuel en remplaçant l'affectation par dateFormat par ceci:

dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "h:mm a EEEE MMMM d", options: 0, locale: dateFormatter.locale)?.replacingOccurrences(of: "d", with: "'\(dayOrdinal)'")

Notez les conseils de plusieurs autres utilisateurs selon lesquels la création de programmes de formatage est coûteuse. Vous devez donc les mettre en cache et les réutiliser dans un code appelé fréquemment.

3
Steve Madsen

Cela donnera une chaîne au format "10:10 PM samedi 2 août"

   -(NSString*) getTimeInString:(NSDate*)date
    {
        NSString* string=@"";
        NSDateComponents *components = [[NSCalendar currentCalendar] components: NSCalendarUnitDay fromDate:date];

        if(components.day == 1 || components.day == 21 || components.day == 31){
             string = @"st";
        }else if (components.day == 2 || components.day == 22){
            string = @"nd";
        }else if (components.day == 3 || components.day == 23){
             string = @"rd";
        }else{
             string = @"th";
        }

        NSDateFormatter *prefixDateFormatter = [[NSDateFormatter alloc] init];    [prefixDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
        [prefixDateFormatter setDateFormat:[NSString stringWithFormat:@"h:mm a EEEE, d'%@' MMMM",string]];

        NSString *dateString = [prefixDateFormatter stringFromDate:date];

        return dateString;
    }
3
Yogesh Lolusare

Ceci est déjà implémenté dans la Fondation.

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .ordinal
numberFormatter.locale = Locale.current

numberFormatter.string(for: 1) //Should produce 1st
numberFormatter.string(for: 2) //Should produce 2nd
numberFormatter.string(for: 3) //Should produce 3rd
numberFormatter.string(for: 4) //Should produce 4th
2
ogantopkaya

Ou si vous voulez le suffixe pour n'importe quel nombre:

extension Int {

    public func suffix() -> String {
        let absSelf = abs(self)

        switch (absSelf % 100) {

        case 11...13:
            return "th"
        default:
            switch (absSelf % 10) {
            case 1:
                return "st"
            case 2:
                return "nd"
            case 3:
                return "rd"
            default:
                return "th"
            }
        }
    }
}

La pensée étant qu'il y a 5 possibilités pour les nombres positifs. Son premier chiffre est 1 étant "st". Son chiffre de deuxième place est 2 étant "2e". Son chiffre de troisième place est 3 étant "rd". Tout autre cas est "th", ou si le chiffre à la deuxième place est 1, les règles ci-dessus ne s'appliquent pas et il s'agit de "th".

Modulo 100 nous donne les deux derniers chiffres du chiffre, nous pouvons donc en vérifier les numéros 11 à 13. Modulo 10 nous donne le dernier chiffre du chiffre afin que nous puissions rechercher 1, 2, 3 si la première condition ne l’a pas capturée.

Essayez cette extension dans les terrains de jeux:

let a = -1 

a.suffix() // "st"

let b = 1112 

b.suffix() // "th"

let c = 32 

c.suffix() // "nd"

J'adorerais voir s'il existe un moyen encore plus court d'écrire ceci en utilisant des opérations binaires et/ou un tableau!

2
Dave Thomas
- (NSString *)dayWithSuffixForDate:(NSDate *)date {

    NSInteger day = [[[NSCalendar currentCalendar] components:NSDayCalendarUnit fromDate:date] day];

    NSString *dayOfMonthWithSuffix, *suffix  = nil ;

    if(day>0 && day <=31)
    {

        switch (day)
        {
            case 1:
            case 21:
            case 31: suffix =  @"st";
                break;
            case 2:
            case 22: suffix = @"nd";
                break;
            case 3:
            case 23: suffix = @"rd";
                break;
            default: suffix = @"th";
                break;
        }


            dayOfMonthWithSuffix = [NSString stringWithFormat:@"%ld%@", (long)day , suffix];
    }


    return dayOfMonthWithSuffix;
}
1
Prosenjit Goswami
   - (void)viewDidLoad
{ 
  NSDate *date = [NSDate date];
        NSDateFormatter *prefixDateFormatter = [[[NSDateFormatter alloc] init] autorelease];
        [prefixDateFormatter setDateFormat:@"yyy-dd-MM"];
        date = [prefixDateFormatter dateFromString:@"2014-6-03"]; //enter yourdate
        [prefixDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
        [prefixDateFormatter setDateFormat:@"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);

}
1
Paresh Hirpara

Aucune des réponses n'utilise le style de nombre ordinal déjà présent dans Number Formatter dans Swift.

    var dateString: String {
       let calendar = Calendar.current
       let dateComponents = calendar.component(.day, from: date)
       let numberFormatter = NumberFormatter()
       numberFormatter.numberStyle = .ordinal
       let day = numberFormatter.string(from: dateComponents as NSNumber)
       let dateFormatter = DateFormatter()
       dateFormatter.dateFormat = "MMM"
       return day! + dateFormatter.string(from: date)
    }
0
Dhiraj Das

J'ai ajouté ces deux méthodes à NSDate avec une catégorie NSDate + Additions.

\- (NSString *)monthDayYear 
{

    NSDateFormatter * dateFormatter = NSDateFormatter.new;
    [dateFormatter setDateFormat:@"MMMM d*, YYYY"];
    NSString *dateString = [dateFormatter stringFromDate:self];

    return [dateString stringByReplacingOccurrencesOfString:@"*" withString:[self ordinalSuffixForDay]];
}

\- (NSString *)ordinalSuffixForDay {

NSDateFormatter * dateFormatter = NSDateFormatter.new;
[dateFormatter setDateFormat:@"d"];
NSString *dateString = [dateFormatter stringFromDate:self];
NSString *suffix = @"th";

if ([dateString length] == 2 && [dateString characterAtIndex:0] == '1') {
    return suffix;
}

switch ([dateString characterAtIndex:[dateString length]-1]) {
    case '1':
        suffix = @"st";
        break;
    case '2':
        suffix = @"nd";
        break;
    case '3':
        suffix = @"rd";
        break;
}

return suffix;
}

Vous pouvez les rendre plus efficaces en les combinant et en indexant le chiffre du jour du lieu dans votre chaîne de format comme point de commutation. J'ai choisi de séparer les fonctionnalités afin que les suffixes ordinaux puissent être appelés séparément pour différents formats de date.

0
Lytic