2009-12-05 16 views
15

के साथ एक आरएफसी 822 दिनांक को पार्स करना मैं आईफोन पर आरएफसी 822 की तारीख को पार्स करने के लिए एनएसडीएटीफॉर्मेटर का उपयोग कर रहा हूं। हालांकि, दिनांक प्रारूप में वैकल्पिक तत्व निर्दिष्ट करने का कोई तरीका नहीं है। आरएफसी 822 विनिर्देशन में कुछ वैकल्पिक भाग हैं जो दिनांक पार्सर को तोड़ रहे हैं। अगर कुछ भी काम नहीं करता है, तो मुझे शायद चश्मे का पालन करने के लिए एक कस्टम पार्सर लिखना होगा।NSDateFormatter

उदाहरण के लिए, दिन का नाम स्पेक में वैकल्पिक है। इसलिए इन दोनों तिथियां मान्य हैं:

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]; 

एक तरीका दोनों रूपों को आजमाएं चींटियों, और जो भी शून्य शून्य मूल्य देता है ले लो। हालांकि, spec (दिन का नाम और सेकंड) में दो वैकल्पिक भाग हैं और 4 संभावित संयोजन होंगे। अभी भी बहुत बुरा नहीं है, लेकिन यह थोड़ा हैकी है।

उत्तर

4

कौन सा फॉर्मेटर उपयोग करने का निर्णय लेने से पहले प्रमुख वर्णों की संख्या की गणना करें। उदाहरण के लिए, आपके द्वारा दिए गए दो में अल्पविराम और रिक्त स्थान की अलग-अलग संख्याएं होती हैं। यदि कोई ज्ञात प्रारूप गणना से मेल नहीं खाता है, तो आप इसे किसी तारीख के रूप में पार्स करने का प्रयास करने के लिए भी नहीं जानते हैं।

+0

यह मेरे लिए सबसे व्यावहारिक समाधान जैसा लगता है, महीने और दिन के नाम निश्चित लंबाई के हैं और अन्य सभी मान निश्चित-लंबाई संख्यात्मक हैं। एक काम करता है जब तक प्रारूपों की कोशिश करने से कहीं ज्यादा सस्ता! –

+0

एक बुनियादी समाधान लागू किया गया। इसके साथ बहुत खुश नहीं है, लेकिन अब तक यह सबसे अच्छा है :) एक कॉमा सप्ताहांत की उपस्थिति की पहचान करता है, और दो कोलन सेकंड की पहचान करने में मदद करते हैं। यह बहुत अच्छा होगा अगर तिथि में उस स्पेक का संदर्भ शामिल था, जिसकी तारीख निम्नलिखित थी, क्योंकि प्रारूपों की संख्या कई भाषाओं में वास्तव में बोझिल है। – Anurag

1

मेरा मानना ​​है कि आरएफसी 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। इसलिए, आप कुछ ऐसा कर सकते हैं जैसे स्टीव ने कहा लेकिन फिर दिन को बंद कर दें और फॉर्मेटर को पास करें। प्रारूप में अल्पविराम नहीं होने के कारण सप्ताह को वैकल्पिक होने की अनुमति नहीं मिलती है। अजीब।

दुर्भाग्यवश, यह अभी भी वैकल्पिक में मदद नहीं करता है: प्रारूप में एसएस। लेकिन यह आपको चार प्रारूपों के बजाय दो प्रारूपों की अनुमति दे सकता है।

+0

टिप के लिए धन्यवाद। मुझे लगता है कि आरएफसी 822 स्थानीयकरण का जिक्र नहीं करता है, और केवल अंग्रेजी प्रारूप का उपयोग करता है। यद्यपि मूल्यों को कड़ी-कोड करने के बजाए अल्पविराम को जोड़ना अभी भी एक अच्छा विचार है। लेकिन चूंकि मुझे अभी भी दो संयोजनों की जांच करने की आवश्यकता होगी, इसलिए शायद दो बार कोशिश करने के बजाय पात्रों की जांच करना एक अच्छा विचार है। – Anurag

5

मैंने आरएफसी 822 तिथियों को पार्स करने के लिए following method का उपयोग किया है। मेरा मानना ​​है कि यह मूल रूप से 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; 

} 
+0

डेट प्रारूप स्ट्रिंग को बदलना महंगा है, आप प्रत्येक के लिए डेट फॉर्मेटर बनाना चाहते हैं और ऐप के जीवनकाल के लिए उस पर लटका सकते हैं। – SomeGuy

0

मामले में यह किसी और के लिए उपयोगी है .. यहाँ एक NSDate + RFC822String.swift Simucal's answer के आधार पर विस्तार है।

यह आखिरी प्रयुक्त दिनांक प्रारूप भी कैश करता है जो सफल था, क्योंकि तिथि सेट करने के बाद Formatter.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 
    } 
} 
संबंधित मुद्दे