سؤال

أنا أستخدم NSDateFormatter لتحليل تاريخ RFC 822 على iPhone. ومع ذلك، لا توجد طريقة لتحديد العناصر الاختيارية في تنسيق التاريخ. هناك أجزاء بضعة اختيارية في مواصفات 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];

طريقة واحدة هي تجربة كل من التنسيقات، واتخاذ أي قيمة غير فارغة. ومع ذلك، هناك قطعان اختياريان في المواصفات (اسم اليوم والثواني) وهناك 4 مجموعات ممكنة. لا تزال ليست سيئة للغاية، لكنها تتبع قليلا.

هل كانت مفيدة؟

المحلول

عد عدد الأحرف البارزة قبل تحديد أي تكوين للاستخدام. على سبيل المثال، الاثنان الذي تقدم له عدد مختلف من الفواصل والمساحات. إذا كان أي تنسيق معروف يطابق التهم، فأنت تعرف أنه لا تحاول تحليله كتاريخ.

نصائح أخرى

لقد استخدمت الطريقة التالية لتحليل تواريخ RFC822. أعتقد أنه كان في الأصل من 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;

}

أعتقد أن RFC 822 يحدد مكونين اختياريين في وقت التاريخ: يوم الأسبوع والثواني الماضية الساعة.

كخانت، من الممكن أن تكون الرموز للأيام القصيرة من الأسبوع:

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

إذا قمت بتغيير تنسيق التاريخ إلى هذا: EEEdd MMM yyyy HH:mm:ss z. وبعد ستكون قادرا على تحليل الأوقات معها دون يوم من أيام الأسبوع. يبدو أن هذا يسمح للمساحة بعد الفاصلة أيضا.

أن تكون آمنة لا يجب عليك ضبط الرموز بشكل أعمى مثل هذا. يجب أن تحصل على استخدام setShortWeekdaySymbols وتكرر معهم إضافة الفاصلة في النهاية. السبب في أن تكون مختلفا يحتمل أن يكون كل لغة وفي اليوم الأول قد لا يكون يوم الأحد.

ومن المثير للاهتمام الشكل EEE, dd MMM yyyy HH:mm:ss z سوف تحليل مرات دون يوم الأسبوع، ولكن يجب أن تكون الفاصلة موجودة، على سبيل المثال , 01 Dec 2009 08:48:25 +0000. وبعد لذلك، يمكنك أن تفعل شيئا مثل ستيف قال ولكن بعد ذلك تجريد اليوم والمرور على الرغم من الصدد. لا يبدو أن عدم وجود فاصلة بالتنسيق يسمح للأسبوع بأن يكون اختياري. غريب.

لسوء الحظ، هذا لا يزال لا يساعد في الاختياري: SS في التنسيق. لكن قد يسمح لك أن يكون لديك تنسيقتين بدلا من أربعة.

في حال كان هذا مفيدا لأي شخص آخر .. هنا هو ملحق NSDate + RFC822STRING.SWIFT إجابة simucal.

كما أنه يخفف من آخر تنسيق تاريخ المستخدم الذي كان ناجحا، نظرا لأن إعداد deadformatter.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
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top