Question

J'utilise un NSDateFormatter pour analyser une date RFC 822 sur l'iPhone. Cependant, il n'y a aucun moyen de spécifier des éléments facultatifs dans le format de date. Il y a quelques pièces en option dans la spécification RFC 822 qui casse l'analyseur de date. Si rien ne fonctionne, j'aurais sans doute d'écrire un analyseur personnalisé pour obéir aux spécifications.

Par exemple, le nom du jour est facultative dans les spécifications. Donc, ces deux dates sont valables:

Tue, 01 Dec 2009 08:48:25 +0000 est analysé avec le format EEE, dd MMM yyyy HH:mm:ss z 01 Dec 2009 08:48:25 +0000 est analysé avec le format dd MMM yyyy HH:mm:ss z

est ce que je suis actuellement en utilisant:

+ (NSDateFormatter *)rfc822Formatter {
    static NSDateFormatter *formatter = nil;
    if (formatter == nil) {
        formatter = [[NSDateFormatter alloc] init];
        NSLocale *enUS = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
        [formatter setLocale:enUS];
        [enUS release];
        [formatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss z"];
    }
    return formatter;
}

+ (NSDate *)dateFromRFC822:(NSString *)date {
    NSDateFormatter *formatter = [NSDate rfc822Formatter];
    return [formatter dateFromString:date];
}

Et l'analyse syntaxique la date comme suit:

self.entry.published = [NSDate dateFromRFC822:self.currentString];

Une façon est d'essayer les deux formats, et prendre toutes les renvoie la valeur non nulle. Cependant, il y a deux parties en option dans les spécifications (nom du jour et secondes) et il y aurait 4 combinaisons possibles. Toujours pas trop mal, mais il est un peu hacky.

Était-ce utile?

La solution

Compter le nombre de caractères saillants avant de décider formatter à utiliser. Par exemple, les deux que vous donnez ont un nombre différent de virgules et des espaces. Si aucun format connu correspond aux comptes, alors vous connu même pas essayer l'analyse comme une date.

Autres conseils

Je l'ai utilisé méthode suivante pour analyser les dates RFC822. Je crois qu'il était à l'origine de MWFeedParser :

+ (NSDate *)dateFromRFC822String:(NSString *)dateString {

    // Create date formatter
    static NSDateFormatter *dateFormatter = nil;
    if (!dateFormatter) {
        NSLocale *en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
        dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setLocale:en_US_POSIX];
        [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
        [en_US_POSIX release];
    }

    // Process
    NSDate *date = nil;
    NSString *RFC822String = [[NSString stringWithString:dateString] uppercaseString];
    if ([RFC822String rangeOfString:@","].location != NSNotFound) {
        if (!date) { // Sun, 19 May 2002 15:21:36 GMT
            [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss zzz"]; 
            date = [dateFormatter dateFromString:RFC822String];
        }
        if (!date) { // Sun, 19 May 2002 15:21 GMT
            [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm zzz"]; 
            date = [dateFormatter dateFromString:RFC822String];
        }
        if (!date) { // Sun, 19 May 2002 15:21:36
            [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss"]; 
            date = [dateFormatter dateFromString:RFC822String];
        }
        if (!date) { // Sun, 19 May 2002 15:21
            [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm"]; 
            date = [dateFormatter dateFromString:RFC822String];
        }
    } else {
        if (!date) { // 19 May 2002 15:21:36 GMT
            [dateFormatter setDateFormat:@"d MMM yyyy HH:mm:ss zzz"]; 
            date = [dateFormatter dateFromString:RFC822String];
        }
        if (!date) { // 19 May 2002 15:21 GMT
            [dateFormatter setDateFormat:@"d MMM yyyy HH:mm zzz"]; 
            date = [dateFormatter dateFromString:RFC822String];
        }
        if (!date) { // 19 May 2002 15:21:36
            [dateFormatter setDateFormat:@"d MMM yyyy HH:mm:ss"]; 
            date = [dateFormatter dateFromString:RFC822String];
        }
        if (!date) { // 19 May 2002 15:21
            [dateFormatter setDateFormat:@"d MMM yyyy HH:mm"]; 
            date = [dateFormatter dateFromString:RFC822String];
        }
    }
    if (!date) NSLog(@"Could not parse RFC822 date: \"%@\" Possibly invalid format.", dateString);
    return date;

}

Je crois que la RFC 822 spécifie deux composants optionnels dans le temps de la date:. Jour de la semaine et les dernières secondes l'heure

En tant que hack, il est possible de symboles pour les courts jours de la semaine:

NSArray *shortWeekSymbols = [NSArray arrayWithObjects:@"Sun,", @"Mon,", @"Tue,", @"Wed,", @"Thu,", @"Fri,", @"Sat,", nil];
        [formatter setShortWeekdaySymbols:shortWeekSymbols];

Si vous changez ensuite le format de date à ceci: EEEdd MMM yyyy HH:mm:ss z. Vous serez en mesure d'analyser les temps avec environ sans le jour de la semaine. Cela semble laisser un espace après la virgule aussi.

Pour être sûr que vous ne devriez pas simplement mettre aveuglément les symboles comme celui-ci. Vous devriez obtenir l'aide setShortWeekdaySymbols et itérer sur les ajoutant la virgule à la fin. La raison étant qu'ils sont potentiellement différentes pour chaque environnement local et le premier jour pourrait ne pas être dimanche.

Il est intéressant le format EEE, dd MMM yyyy HH:mm:ss z analysera fois sans le jour de la semaine, mais la virgule doit être là, par exemple , 01 Dec 2009 08:48:25 +0000. Par conséquent, vous pouvez faire quelque chose comme Steve dit mais dépouiller la journée et passer bien à la formatter. Ne pas avoir la virgule dans le format ne semble pas permettre à la semaine pour être facultative. Étrange.

Malheureusement, cela ne fonctionne toujours pas avec l'aide en option: ss dans le format. Mais il peut vous permettre d'avoir deux formats plutôt que quatre.

Dans le cas où cela est utile à quelqu'un d'autre .. ici est une extension NSDate + RFC822String.swift fonction de la réponse Simucal .

Il met également en cache le dernier format de date utilisé qui a réussi, depuis la mise en l'dateFormatter.dateFormat est cher.

import Foundation

private let dateFormatter: NSDateFormatter = {
    let dateFormatter = NSDateFormatter()
    dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
    dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)

    return dateFormatter
}()

private let dateFormatsWithComma = ["EEE, d MMM yyyy HH:mm:ss zzz", "EEE, d MMM yyyy HH:mm zzz", "EEE, d MMM yyyy HH:mm:ss", "EEE, d MMM yyyy HH:mm"]
private let dateFormatsWithoutComma = ["d MMM yyyy HH:mm:ss zzz", "d MMM yyyy HH:mm zzz", "d MMM yyyy HH:mm:ss", "d MMM yyyy HH:mm"]

private var lastUsedDateFormatString: String?

extension NSDate {
    class func dateFromRFC822String(RFC822String: String) -> NSDate? {
        let RFC822String = RFC822String.uppercaseString

        if lastUsedDateFormatString != nil {
            if let date = dateFormatter.dateFromString(RFC822String) {
                return date
            }
        }

        if RFC822String.containsString(",") {
            for dateFormat in dateFormatsWithComma {
                dateFormatter.dateFormat = dateFormat
                if let date = dateFormatter.dateFromString(RFC822String) {
                    lastUsedDateFormatString = dateFormat
                    return date
                }
            }
        } else {
            for dateFormat in dateFormatsWithoutComma {
                dateFormatter.dateFormat = dateFormat
                if let date = dateFormatter.dateFromString(RFC822String) {
                    lastUsedDateFormatString = dateFormat
                    return date
                }
            }
        }

        return nil
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top