Skip to content

Commit

Permalink
NSDate+InternetDateTime
Browse files Browse the repository at this point in the history
  • Loading branch information
Jakey authored and Jakey committed Jul 10, 2015
1 parent 1713d6a commit e9aff9e
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 0 deletions.
31 changes: 31 additions & 0 deletions Categories/Foundation/NSDate/NSDate+InternetDateTime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// NSDate+InternetDateTime.h
// MWFeedParser
//
// Created by Michael Waterfall on 07/10/2010.
// Copyright 2010 Michael Waterfall. All rights reserved.
//

#import <Foundation/Foundation.h>

// Formatting hints
typedef enum {
DateFormatHintNone,
DateFormatHintRFC822,
DateFormatHintRFC3339
} DateFormatHint;

// A category to parse internet date & time strings
@interface NSDate (InternetDateTime)

// Get date from RFC3339 or RFC822 string
// - A format/specification hint can be used to speed up,
// otherwise both will be attempted in order to get a date
+ (NSDate *)dateFromInternetDateTimeString:(NSString *)dateString
formatHint:(DateFormatHint)hint;

// Get date from a string using a specific date specification
+ (NSDate *)dateFromRFC3339String:(NSString *)dateString;
+ (NSDate *)dateFromRFC822String:(NSString *)dateString;

@end
142 changes: 142 additions & 0 deletions Categories/Foundation/NSDate/NSDate+InternetDateTime.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//
// NSDate+InternetDateTime.m
// MWFeedParser
//
// Created by Michael Waterfall on 07/10/2010.
// Copyright 2010 Michael Waterfall. All rights reserved.
//

#import "NSDate+InternetDateTime.h"

// Always keep the formatter around as they're expensive to instantiate
static NSDateFormatter *_internetDateTimeFormatter = nil;

// Good info on internet dates here:
// http://developer.apple.com/iphone/library/qa/qa2010/qa1480.html
@implementation NSDate (InternetDateTime)

// Instantiate single date formatter
+ (NSDateFormatter *)internetDateTimeFormatter {
@synchronized(self) {
if (!_internetDateTimeFormatter) {
NSLocale *en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
_internetDateTimeFormatter = [[NSDateFormatter alloc] init];
[_internetDateTimeFormatter setLocale:en_US_POSIX];
[_internetDateTimeFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
}
}
return _internetDateTimeFormatter;
}

// Get a date from a string - hint can be used to speed up
+ (NSDate *)dateFromInternetDateTimeString:(NSString *)dateString formatHint:(DateFormatHint)hint {
// Keep dateString around a while (for thread-safety)
NSDate *date = nil;
if (dateString) {
if (hint != DateFormatHintRFC3339) {
// Try RFC822 first
date = [NSDate dateFromRFC822String:dateString];
if (!date) date = [NSDate dateFromRFC3339String:dateString];
} else {
// Try RFC3339 first
date = [NSDate dateFromRFC3339String:dateString];
if (!date) date = [NSDate dateFromRFC822String:dateString];
}
}
// Finished with date string
return date;
}

// See http://www.faqs.org/rfcs/rfc822.html
+ (NSDate *)dateFromRFC822String:(NSString *)dateString {
// Keep dateString around a while (for thread-safety)
NSDate *date = nil;
if (dateString) {
NSDateFormatter *dateFormatter = [NSDate internetDateTimeFormatter];
@synchronized(dateFormatter) {

// Process
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: \"%@\" Possible invalid format.", dateString);

}
}
// Finished with date string
return date;
}

// See http://www.faqs.org/rfcs/rfc3339.html
+ (NSDate *)dateFromRFC3339String:(NSString *)dateString {
// Keep dateString around a while (for thread-safety)
NSDate *date = nil;
if (dateString) {
NSDateFormatter *dateFormatter = [NSDate internetDateTimeFormatter];
@synchronized(dateFormatter) {

// Process date
NSString *RFC3339String = [[NSString stringWithString:dateString] uppercaseString];
RFC3339String = [RFC3339String stringByReplacingOccurrencesOfString:@"Z" withString:@"-0000"];
// Remove colon in timezone as it breaks NSDateFormatter in iOS 4+.
// - 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
[dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZ"];
date = [dateFormatter dateFromString:RFC3339String];
}
if (!date) { // 1937-01-01T12:00:27.87+0020
[dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZ"];
date = [dateFormatter dateFromString:RFC3339String];
}
if (!date) { // 1937-01-01T12:00:27
[dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss"];
date = [dateFormatter dateFromString:RFC3339String];
}
if (!date) NSLog(@"Could not parse RFC3339 date: \"%@\" Possible invalid format.", dateString);

}
}
// Finished with date string
return date;
}

@end
6 changes: 6 additions & 0 deletions IOS-Categories.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
A20A5A6C1B4E2886004E2474 /* NSFileHandleDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A20A5A6A1B4E2886004E2474 /* NSFileHandleDemoViewController.m */; };
A20A5A6D1B4E2886004E2474 /* NSFileHandleDemoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A20A5A6B1B4E2886004E2474 /* NSFileHandleDemoViewController.xib */; };
A20A5A6F1B4E28CE004E2474 /* NSFileHandleSampleFile.txt in Resources */ = {isa = PBXBuildFile; fileRef = A20A5A6E1B4E28CE004E2474 /* NSFileHandleSampleFile.txt */; };
A20FFDFA1B4F944A00600093 /* NSDate+InternetDateTime.m in Sources */ = {isa = PBXBuildFile; fileRef = A20FFDF91B4F944A00600093 /* NSDate+InternetDateTime.m */; };
A218D8D71A479E9C00AB83CA /* UIColor+Web.m in Sources */ = {isa = PBXBuildFile; fileRef = A218D8D61A479E9C00AB83CA /* UIColor+Web.m */; };
A218D8DF1A47A25100AB83CA /* UIWebView+Canvas.m in Sources */ = {isa = PBXBuildFile; fileRef = A218D8DC1A47A25100AB83CA /* UIWebView+Canvas.m */; };
A218D8E01A47A25100AB83CA /* UIWebView+JS.m in Sources */ = {isa = PBXBuildFile; fileRef = A218D8DE1A47A25100AB83CA /* UIWebView+JS.m */; };
Expand Down Expand Up @@ -412,6 +413,8 @@
A20A5A6A1B4E2886004E2474 /* NSFileHandleDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSFileHandleDemoViewController.m; sourceTree = "<group>"; };
A20A5A6B1B4E2886004E2474 /* NSFileHandleDemoViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NSFileHandleDemoViewController.xib; sourceTree = "<group>"; };
A20A5A6E1B4E28CE004E2474 /* NSFileHandleSampleFile.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NSFileHandleSampleFile.txt; sourceTree = "<group>"; };
A20FFDF81B4F944A00600093 /* NSDate+InternetDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+InternetDateTime.h"; sourceTree = "<group>"; };
A20FFDF91B4F944A00600093 /* NSDate+InternetDateTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+InternetDateTime.m"; sourceTree = "<group>"; };
A218D8D51A479E9C00AB83CA /* UIColor+Web.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+Web.h"; sourceTree = "<group>"; };
A218D8D61A479E9C00AB83CA /* UIColor+Web.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Web.m"; sourceTree = "<group>"; };
A218D8DB1A47A25100AB83CA /* UIWebView+Canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIWebView+Canvas.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1421,6 +1424,8 @@
A202D9611B0F6C4400EAB199 /* NSDate+Reporting.m */,
A202D9A91B102F0F00EAB199 /* NSDate+Formatter.h */,
A202D9AA1B102F0F00EAB199 /* NSDate+Formatter.m */,
A20FFDF81B4F944A00600093 /* NSDate+InternetDateTime.h */,
A20FFDF91B4F944A00600093 /* NSDate+InternetDateTime.m */,
);
path = NSDate;
sourceTree = "<group>";
Expand Down Expand Up @@ -2912,6 +2917,7 @@
A28BE2ED1A3E9F48005C4AC6 /* NSString+DictionaryValue.m in Sources */,
A21F34C11B0F229700D73A91 /* UIScreen+Frame.m in Sources */,
BCB79A051AFDE19200C12525 /* NSString+Contains.m in Sources */,
A20FFDFA1B4F944A00600093 /* NSDate+InternetDateTime.m in Sources */,
A2958D271B359A5E00D7AA0F /* UIImage+BetterFace.m in Sources */,
A2958D001B358F0200D7AA0F /* UIApplication+Permissions.m in Sources */,
A218D8DF1A47A25100AB83CA /* UIWebView+Canvas.m in Sources */,
Expand Down

0 comments on commit e9aff9e

Please sign in to comment.