Skip to content

Commit

Permalink
Consolidated internet date parsing into an NSDate category.
Browse files Browse the repository at this point in the history
  • Loading branch information
mwaterfall committed Oct 7, 2010
1 parent e88f36c commit f2bb31c
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 265 deletions.
104 changes: 6 additions & 98 deletions Classes/MWFeedParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#import "MWFeedParser.h"
#import "MWFeedParser_Private.h"
#import "NSString+HTML.h"
#import "NSDate+InternetDateTime.h"

// NSXMLParser Logging
#if 0 // Set to 1 to enable XML parsing logs
Expand Down Expand Up @@ -475,9 +476,9 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName names
else if ([currentPath isEqualToString:@"/rss/channel/item/guid"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/content:encoded"]) { if (processedText.length > 0) item.content = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/pubDate"]) { if (processedText.length > 0) item.date = [self dateFromInternetString:processedText formatHint:DateFormatHintRFC822]; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/pubDate"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC822]; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/enclosure"]) { [self createEnclosureFromAttributes:currentElementAttributes andAddToItem:item]; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:date"]) { if (processedText.length > 0) item.date = [self dateFromInternetString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/rss/channel/item/dc:date"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
}

// Info
Expand All @@ -498,7 +499,7 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName names
else if ([currentPath isEqualToString:@"/rdf:RDF/item/dc:identifier"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rdf:RDF/item/description"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rdf:RDF/item/content:encoded"]) { if (processedText.length > 0) item.content = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/rdf:RDF/item/dc:date"]) { if (processedText.length > 0) item.date = [self dateFromInternetString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/rdf:RDF/item/dc:date"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/rdf:RDF/item/enc:enclosure"]) { [self createEnclosureFromAttributes:currentElementAttributes andAddToItem:item]; processed = YES; }
}

Expand All @@ -520,8 +521,8 @@ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName names
else if ([currentPath isEqualToString:@"/feed/entry/id"]) { if (processedText.length > 0) item.identifier = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/feed/entry/summary"]) { if (processedText.length > 0) item.summary = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/feed/entry/content"]) { if (processedText.length > 0) item.content = processedText; processed = YES; }
else if ([currentPath isEqualToString:@"/feed/entry/published"]) { if (processedText.length > 0) item.date = [self dateFromInternetString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/feed/entry/updated"]) { if (processedText.length > 0) item.updated = [self dateFromInternetString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/feed/entry/published"]) { if (processedText.length > 0) item.date = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
else if ([currentPath isEqualToString:@"/feed/entry/updated"]) { if (processedText.length > 0) item.updated = [NSDate dateFromInternetDateTimeString:processedText formatHint:DateFormatHintRFC3339]; processed = YES; }
}

// Info
Expand Down Expand Up @@ -785,97 +786,4 @@ - (BOOL)processAtomLink:(NSDictionary *)attributes andAddToMWObject:(id)MWObject
return NO;
}

// Get a date from a string - hit (from specs) can be used to speed up
- (NSDate *)dateFromInternetString:(NSString *)dateString formatHint:(DateFormatHint)hint {
NSDate *date = nil;
if (hint != DateFormatHintRFC3339) {
// Try RFC822 first
date = [self dateFromRFC822String:dateString];
if (!date) date = [self dateFromRFC3339String:dateString];
} else {
// Try RFC3339 first
date = [self dateFromRFC3339String:dateString];
if (!date) date = [self dateFromRFC822String:dateString];
}
return date;
}

// See http://www.faqs.org/rfcs/rfc822.html
- (NSDate *)dateFromRFC822String:(NSString *)dateString {
NSDate *date = nil;
NSString *RFC822String = [[NSString stringWithString:dateString] uppercaseString];
if ([RFC822String rangeOfString:@","].location != NSNotFound) {
if (!date) { // Sun, 19 May 2002 15:21:36 GMT
[dateFormatterRFC822 setDateFormat:@"EEE, d MMM yyyy HH:mm:ss zzz"];
date = [dateFormatterRFC822 dateFromString:RFC822String];
}
if (!date) { // Sun, 19 May 2002 15:21 GMT
[dateFormatterRFC822 setDateFormat:@"EEE, d MMM yyyy HH:mm zzz"];
date = [dateFormatterRFC822 dateFromString:RFC822String];
}
if (!date) { // Sun, 19 May 2002 15:21:36
[dateFormatterRFC822 setDateFormat:@"EEE, d MMM yyyy HH:mm:ss"];
date = [dateFormatterRFC822 dateFromString:RFC822String];
}
if (!date) { // Sun, 19 May 2002 15:21
[dateFormatterRFC822 setDateFormat:@"EEE, d MMM yyyy HH:mm"];
date = [dateFormatterRFC822 dateFromString:RFC822String];
}
} else {
if (!date) { // 19 May 2002 15:21:36 GMT
[dateFormatterRFC822 setDateFormat:@"d MMM yyyy HH:mm:ss zzz"];
date = [dateFormatterRFC822 dateFromString:RFC822String];
}
if (!date) { // 19 May 2002 15:21 GMT
[dateFormatterRFC822 setDateFormat:@"d MMM yyyy HH:mm zzz"];
date = [dateFormatterRFC822 dateFromString:RFC822String];
}
if (!date) { // 19 May 2002 15:21:36
[dateFormatterRFC822 setDateFormat:@"d MMM yyyy HH:mm:ss"];
date = [dateFormatterRFC822 dateFromString:RFC822String];
}
if (!date) { // 19 May 2002 15:21
[dateFormatterRFC822 setDateFormat:@"d MMM yyyy HH:mm"];
date = [dateFormatterRFC822 dateFromString:RFC822String];
}
}
if (!date) { // Failed so Debug log
MWLog(@"MWFeedParser: Could not parse RFC822 date: \"%@\" Possibly invalid format.", dateString);
}
return date;
}

// See http://www.faqs.org/rfcs/rfc3339.html
- (NSDate *)dateFromRFC3339String:(NSString *)dateString {
NSDate *date = nil;
NSString *RFC3339String = [[NSString stringWithString:dateString] uppercaseString];
RFC3339String = [RFC3339String stringByReplacingOccurrencesOfString:@"Z" withString:@"-0000"];

// Remove colon in timezone as iOS 4+ NSDateFormatter breaks
// See https://devforums.apple.com/thread/45837
if (RFC3339String.length > 20) {
RFC3339String = [RFC3339String stringByReplacingOccurrencesOfString:@":"
withString:@""
options:0
range:NSMakeRange(20, RFC3339String.length-20)];
}

if (!date) { // 1996-12-19T16:39:57-0800
[dateFormatterRFC3339 setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZ"];
date = [dateFormatterRFC3339 dateFromString:RFC3339String];
}
if (!date) { // 1937-01-01T12:00:27.87+0020
[dateFormatterRFC3339 setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZ"];
date = [dateFormatterRFC3339 dateFromString:RFC3339String];
}
if (!date) { // 1937-01-01T12:00:27
[dateFormatterRFC3339 setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss"];
date = [dateFormatterRFC3339 dateFromString:RFC3339String];
}
if (!date) { // Failed so Debug log
MWLog(@"MWFeedParser: Could not parse RFC3339 date: \"%@\" Possibly invalid format.", dateString);
}
return date;
}

@end
6 changes: 0 additions & 6 deletions Classes/MWFeedParser_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@
// THE SOFTWARE.
//

// Date format hints for parsing date from internet string
typedef enum {DateFormatHintNone, DateFormatHintRFC822, DateFormatHintRFC3339} DateFormatHint;

@interface MWFeedParser ()

#pragma mark Private Properties
Expand Down Expand Up @@ -66,8 +63,5 @@ typedef enum {DateFormatHintNone, DateFormatHintRFC822, DateFormatHintRFC3339} D
// Misc
- (BOOL)createEnclosureFromAttributes:(NSDictionary *)attributes andAddToItem:(MWFeedItem *)currentItem;
- (BOOL)processAtomLink:(NSDictionary *)attributes andAddToMWObject:(id)MWObject;
- (NSDate *)dateFromInternetString:(NSString *)dateString formatHint:(DateFormatHint)hint;
- (NSDate *)dateFromRFC822String:(NSString *)dateString;
- (NSDate *)dateFromRFC3339String:(NSString *)dateString;

@end
2 changes: 2 additions & 0 deletions Classes/NSString+HTML.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

#import <Foundation/Foundation.h>

// Dependant upon GTMNSString+HTML

@interface NSString (HTML)

// Instance Methods
Expand Down
2 changes: 1 addition & 1 deletion MWFeedParser-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<string>Icon.png</string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
Expand Down
Loading

0 comments on commit f2bb31c

Please sign in to comment.