Frage

Ich bin mit einem NSDateFormatter ein RFC 822 Datum auf dem iPhone zu analysieren. Allerdings gibt es keine Möglichkeit, optionale Elemente in dem Datumsformat zu spezifizieren. Es gibt ein paar optionale Teile in der RFC 822-Spezifikation, die das Datum Parser bricht. Wenn nichts klappt, würde ich wahrscheinlich einen benutzerdefinierten Parser schreiben müssen, um die Spezifikationen zu gehorchen.

Zum Beispiel ist der Tag Name in der Spezifikation optional. Also diese beiden Termine sind gültig:

Tue, 01 Dec 2009 08:48:25 +0000 wird mit dem Format EEE, dd MMM yyyy HH:mm:ss z analysiert 01 Dec 2009 08:48:25 +0000 wird mit dem Format dd MMM yyyy HH:mm:ss z analysiert

Das ist, was ich bin derzeit mit:

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

Und das Parsen das Datum wie folgt:

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

Eine Möglichkeit ist, beide Formate zu versuchen, und nehmen, was nicht null-Wert zurückgibt. Allerdings gibt es zwei optionale Teile in der Spezifikation (Tag Name und Sekunden) und es gäbe vier möglichen Kombinationen sein. Immer noch nicht allzu schlecht, aber es ist ein bisschen hacky.

War es hilfreich?

Lösung

Zählen Sie die Anzahl der ausgeprägten Zeichen vor der Entscheidung, welches Formatierungsprogramm zu verwenden. Zum Beispiel haben die beiden geben Sie eine unterschiedliche Anzahl von Kommas und Leerzeichen. Wenn kein bekanntes Format der Zählungen übereinstimmt, dann gewusst, dass Sie nicht einmal das Parsen es als Datum zu versuchen.

Andere Tipps

Ich habe die folgende Verfahren verwendet RFC822 Daten zu analysieren. Ich glaube, es war ursprünglich von 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;

}

Ich glaube, RFC 822 zwei optionale Komponenten in dem Datum Zeit angibt:. Tag der Woche und die Sekunden nach der vollen Stunde

Als Hack ist es möglich, auf die Symbole für die kurzen Tage der Woche:

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

Wenn Sie dann das Format Datum ändern, um diese: EEEdd MMM yyyy HH:mm:ss z. Sie werden in der Lage sein, mal ohne den Tag der Woche mit etwa zu analysieren. Dies scheint einen Raum hinter dem Komma zu ermöglichen.

Um sicher zu sein, sollten Sie nicht einfach blind die Symbole wie folgt festgelegt. Sie sollten am Ende mit setShortWeekdaySymbols und iterieren sie das Hinzufügen des Kommas bekommen. Der Grund dafür ist sie für jedes Gebietsschema möglicherweise unterschiedlich sind und dem ersten Tag vielleicht nicht Sonntag.

Interessanterweise wird das Format EEE, dd MMM yyyy HH:mm:ss z mal analysieren, ohne den Tag der Woche, aber das Komma muss es sein, zum Beispiel , 01 Dec 2009 08:48:25 +0000. Daher könnte tun Sie so etwas wie Steve sagte aber dann den Tag abzustreifen und zwar an den Formatierer übergeben. Nicht im Format das Komma mit scheint nicht der Woche zu ermöglichen optional zu sein. Seltsam.

Leider ist dies immer noch nicht mit dem optionalen helfen: ss im Format. Aber es könnte Ihnen ermöglichen, zwei Formate haben statt vier.

Falls dies hilfreich für jemand anderes .. hier ist ein NSDate + RFC822String.swift Erweiterung basiert auf Simucal Antwort .

Es speichert auch das zuletzt verwendete Datumsformat, das erfolgreich war, die dateFormatter.dateFormat seit Einstellung teuer ist.

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
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top