16

NSDateFormatter を使用して、iPhone で RFC 822 の日付を解析しています。ただし、日付形式でオプション要素を指定する方法はありません。RFC 822 仕様には、日付パーサーを壊しているオプションの部分がいくつかあります。何もうまくいかない場合は、おそらく仕様に従うカスタム パーサーを作成する必要があります。

たとえば、仕様では曜日名はオプションです。したがって、これらの日付は両方とも有効です。

Tue, 01 Dec 2009 08:48:25 +0000 形式EEE, dd MMM yyyy HH:mm:ss z 01 Dec 2009 08:48:25 +0000で解析されます 形式で解析されますdd MMM yyyy HH:mm:ss z

これは私が現在使用しているものです:

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

そして、次のように日付を解析します。

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

1 つの方法は、両方の形式を試して、null 以外の値を返すものをすべて取得することです。ただし、仕様には 2 つのオプション部分 (曜日名と秒) があり、4 つの可能な組み合わせがあります。それでも悪くはありませんが、少しハッキーです。

4

4 に答える 4

4

使用するフォーマッタを決定する前に、顕著な文字の数を数えます。たとえば、指定した 2 つのコンマとスペースの数が異なります。既知の形式がカウントに一致しない場合、それを日付として解析しようとさえしないことがわかっています。

于 2009-12-05T06:00:09.663 に答える
1

RFC 822 では、日時の 2 つのオプション コンポーネントが指定されていると思います。曜日と正時からの秒数です。

ハックとして、短い曜日の記号を使用することができます。

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

その後、日付形式を次のように変更すると: EEEdd MMM yyyy HH:mm:ss z. 曜日なしで about を使用して時間を解析できます。これにより、コンマの後にスペースも許可されるようです。

安全のために、シンボルをこのように盲目的に設定しないでください。最後にカンマを追加して、それらを使用setShortWeekdaySymbolsして反復する必要があります。その理由は、ロケールごとに異なる可能性があり、初日が日曜日ではない可能性があるためです。

興味深いことに、この形式EEE, dd MMM yyyy HH:mm:ss zは曜日なしで時刻を解析しますが、コンマが必要です (例: , 01 Dec 2009 08:48:25 +0000. したがって、Steve が言ったようなことを行ってから、その日を取り除いてフォーマッタに渡すことができます。形式にコンマがないため、週をオプションにすることはできません。変。

残念ながら、これはフォーマットのオプションの :ss にはまだ役に立ちません。ただし、4 つではなく 2 つのフォーマットを持つことができる場合があります。

于 2009-12-05T11:56:15.437 に答える
0

これが他の人に役立つ場合..これは、 Simucalの回答に基づく NSDate+RFC822String.swift 拡張です。

また、dateFormatter.dateFormat の設定はコストがかかるため、最後に使用されて成功した日付形式もキャッシュします。

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
    }
}
于 2016-04-20T15:42:50.533 に答える