/app/iOSBlogReader/ThirdParty/MWFeedParser/NSDate+InternetDateTime.m

https://github.com/everettjf/TomatoRead · Objective C · 157 lines · 118 code · 13 blank · 26 comment · 28 complexity · bf718477d1e6c344a155e403b31f8a77 MD5 · raw file

  1. //
  2. // NSDate+InternetDateTime.m
  3. // MWFeedParser
  4. //
  5. // Created by Michael Waterfall on 07/10/2010.
  6. // Copyright 2010 Michael Waterfall. All rights reserved.
  7. //
  8. #import "NSDate+InternetDateTime.h"
  9. // Always keep the formatter around as they're expensive to instantiate
  10. static NSDateFormatter *_internetDateTimeFormatter = nil;
  11. // Good info on internet dates here:
  12. // http://developer.apple.com/iphone/library/qa/qa2010/qa1480.html
  13. @implementation NSDate (InternetDateTime)
  14. // Instantiate single date formatter
  15. + (NSDateFormatter *)internetDateTimeFormatter {
  16. @synchronized(self) {
  17. if (!_internetDateTimeFormatter) {
  18. NSLocale *en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  19. _internetDateTimeFormatter = [[NSDateFormatter alloc] init];
  20. [_internetDateTimeFormatter setLocale:en_US_POSIX];
  21. [_internetDateTimeFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
  22. }
  23. }
  24. return _internetDateTimeFormatter;
  25. }
  26. // Get a date from a string - hint can be used to speed up
  27. + (NSDate *)dateFromInternetDateTimeString:(NSString *)dateString formatHint:(DateFormatHint)hint {
  28. // Keep dateString around a while (for thread-safety)
  29. NSDate *date = nil;
  30. if (dateString) {
  31. if (hint != DateFormatHintRFC3339) {
  32. // Try RFC822 first
  33. date = [NSDate dateFromRFC822String:dateString];
  34. if (!date) date = [NSDate dateFromRFC3339String:dateString];
  35. } else {
  36. // Try RFC3339 first
  37. date = [NSDate dateFromRFC3339String:dateString];
  38. if (!date) date = [NSDate dateFromRFC822String:dateString];
  39. }
  40. }
  41. // Finished with date string
  42. return date;
  43. }
  44. // See http://www.faqs.org/rfcs/rfc822.html
  45. + (NSDate *)dateFromRFC822String:(NSString *)dateString {
  46. // Keep dateString around a while (for thread-safety)
  47. NSDate *date = nil;
  48. if (dateString) {
  49. NSDateFormatter *dateFormatter = [NSDate internetDateTimeFormatter];
  50. @synchronized(dateFormatter) {
  51. // Process
  52. NSString *RFC822String = [[NSString stringWithString:dateString] uppercaseString];
  53. if ([RFC822String rangeOfString:@","].location != NSNotFound) {
  54. if (!date) { // Sun, 19 May 2002 15:21:36 GMT
  55. [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss zzz"];
  56. date = [dateFormatter dateFromString:RFC822String];
  57. }
  58. if (!date) { // Sun, 19 May 2002 15:21 GMT
  59. [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm zzz"];
  60. date = [dateFormatter dateFromString:RFC822String];
  61. }
  62. if (!date) { // Sun, 19 May 2002 15:21:36
  63. [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss"];
  64. date = [dateFormatter dateFromString:RFC822String];
  65. }
  66. if (!date) { // Sun, 19 May 2002 15:21
  67. [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm"];
  68. date = [dateFormatter dateFromString:RFC822String];
  69. }
  70. } else {
  71. if (!date) { // 19 May 2002 15:21:36 GMT
  72. [dateFormatter setDateFormat:@"d MMM yyyy HH:mm:ss zzz"];
  73. date = [dateFormatter dateFromString:RFC822String];
  74. }
  75. if (!date) { // 19 May 2002 15:21 GMT
  76. [dateFormatter setDateFormat:@"d MMM yyyy HH:mm zzz"];
  77. date = [dateFormatter dateFromString:RFC822String];
  78. }
  79. if (!date) { // 19 May 2002 15:21:36
  80. [dateFormatter setDateFormat:@"d MMM yyyy HH:mm:ss"];
  81. date = [dateFormatter dateFromString:RFC822String];
  82. }
  83. if (!date) { // 19 May 2002 15:21
  84. [dateFormatter setDateFormat:@"d MMM yyyy HH:mm"];
  85. date = [dateFormatter dateFromString:RFC822String];
  86. }
  87. }
  88. if(!date){
  89. NSArray<NSString*> *dateFormats = @[
  90. @"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZ", // 1996-12-19T16:39:57-0800
  91. @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZ", // 1937-01-01T12:00:27.87+0020
  92. @"yyyy'-'MM'-'dd'T'HH':'mm':'ss", // 1937-01-01T12:00:27
  93. @"yyyy'/'MM'/'dd' 'HH':'mm':'ss", // 2012/12/19 11:00:31
  94. @"yyyy'-'MM'-'dd", // 1937-01-01
  95. ];
  96. for (NSString *format in dateFormats) {
  97. [dateFormatter setDateFormat:format];
  98. date = [dateFormatter dateFromString:RFC822String];
  99. if(date)break;
  100. }
  101. }
  102. if (!date) NSLog(@"Could not parse RFC822 date: \"%@\" Possible invalid format.", dateString);
  103. }
  104. }
  105. // Finished with date string
  106. return date;
  107. }
  108. // See http://www.faqs.org/rfcs/rfc3339.html
  109. + (NSDate *)dateFromRFC3339String:(NSString *)dateString {
  110. // Keep dateString around a while (for thread-safety)
  111. NSDate *date = nil;
  112. if (dateString) {
  113. NSDateFormatter *dateFormatter = [NSDate internetDateTimeFormatter];
  114. @synchronized(dateFormatter) {
  115. // Process date
  116. NSString *RFC3339String = [[NSString stringWithString:dateString] uppercaseString];
  117. RFC3339String = [RFC3339String stringByReplacingOccurrencesOfString:@"Z" withString:@"-0000"];
  118. // Remove colon in timezone as it breaks NSDateFormatter in iOS 4+.
  119. // - see https://devforums.apple.com/thread/45837
  120. if (RFC3339String.length > 20) {
  121. RFC3339String = [RFC3339String stringByReplacingOccurrencesOfString:@":"
  122. withString:@""
  123. options:0
  124. range:NSMakeRange(20, RFC3339String.length-20)];
  125. }
  126. NSArray<NSString*> *dateFormats = @[
  127. @"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZ", // 1996-12-19T16:39:57-0800
  128. @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZ", // 1937-01-01T12:00:27.87+0020
  129. @"yyyy'-'MM'-'dd'T'HH':'mm':'ss", // 1937-01-01T12:00:27
  130. @"yyyy'/'MM'/'dd' 'HH':'mm':'ss", // 2012/12/19 11:00:31
  131. @"yyyy'-'MM'-'dd", // 1937-01-01
  132. ];
  133. for (NSString *format in dateFormats) {
  134. [dateFormatter setDateFormat:format];
  135. date = [dateFormatter dateFromString:RFC3339String];
  136. if(date)break;
  137. }
  138. if (!date) NSLog(@"Could not parse RFC3339 date: \"%@\" Possible invalid format.", dateString);
  139. }
  140. }
  141. // Finished with date string
  142. return date;
  143. }
  144. @end