Changeset 577
- Timestamp:
- 08/03/09 08:10:19 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Cocoa/Pester/Source/NJRDateFormatter.m
r367 r577 11 11 #include <dlfcn.h> 12 12 13 // workaround for bug in Jaguar (and earlier?) NSCalendarDate dateWithNaturalLanguageString: 14 NSString *stringByRemovingSurroundingWhitespace(NSString *string) { 15 static NSCharacterSet *nonWhitespace = nil; 16 NSRange firstValidCharacter, lastValidCharacter; 17 18 if (!nonWhitespace) { 19 nonWhitespace = [[[NSCharacterSet characterSetWithCharactersInString: 20 @" \t\r\n"] invertedSet] retain]; 21 } 22 23 firstValidCharacter = [string rangeOfCharacterFromSet:nonWhitespace]; 24 if (firstValidCharacter.length == 0) 25 return @""; 26 lastValidCharacter = [string rangeOfCharacterFromSet:nonWhitespace options: NSBackwardsSearch]; 27 28 if (firstValidCharacter.location == 0 && lastValidCharacter.location == [string length] - 1) 29 return string; 30 else 31 return [string substringWithRange: NSUnionRange(firstValidCharacter, lastValidCharacter)]; 13 static NSDateFormatter *protoFormatter() { 14 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 15 [formatter setLenient: YES]; 16 return formatter; 17 } 18 19 static NSDateFormatter *dateFormatterWithStyle(NSDateFormatterStyle style) { 20 NSDateFormatter *formatter = protoFormatter(); 21 [formatter setTimeStyle: NSDateFormatterNoStyle]; 22 [formatter setDateStyle: style]; 23 return formatter; 24 } 25 26 static NSDateFormatter *timeFormatterWithStyle(NSDateFormatterStyle style) { 27 NSDateFormatter *formatter = protoFormatter(); 28 [formatter setTimeStyle: style]; 29 [formatter setDateStyle: NSDateFormatterNoStyle]; 30 return formatter; 31 } 32 33 static NSDateFormatter *timeFormatterWithFormat(NSString *format) { 34 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 35 [formatter setDateFormat: format]; 36 [formatter setLenient: NO]; 37 return formatter; 32 38 } 33 39 … … 40 46 }; 41 47 48 // note: these formats must be 0-padded where appropriate and contain no spaces 49 // or attempts to force them into strict interpretation will fail 50 static const NSString *timeFormats[] = { 51 @"hha", 52 @"HHmmss", 53 @"HHmm", 54 @"HH", 55 nil 56 }; 57 42 58 @implementation NJRDateFormatter 43 59 … … 85 101 NSMutableArray *tryFormatters = [[NSMutableArray alloc] init]; 86 102 87 for (const NSDateFormatterStyle *s = formatterStyles ; *s < NSDateFormatterNoStyle ; *s++) { 88 NSDateFormatter *tryFormatter = [[NSDateFormatter alloc] init]; 89 [tryFormatter setLenient: YES]; 90 [tryFormatter setTimeStyle: NSDateFormatterNoStyle]; 91 [tryFormatter setDateStyle: *s]; 103 for (const NSDateFormatterStyle *s = formatterStyles ; *s != NSDateFormatterNoStyle ; *s++) { 104 NSDateFormatter *tryFormatter = dateFormatterWithStyle(*s); 92 105 [tryFormatters addObject: tryFormatter]; 93 106 [tryFormatter release]; … … 103 116 NJRDateFormatter *formatter = [[self alloc] init]; 104 117 NSMutableArray *tryFormatters = [[NSMutableArray alloc] init]; 105 106 for (const NSDateFormatterStyle *s = formatterStyles ; *s < NSDateFormatterNoStyle ; *s++) { 107 NSDateFormatter *tryFormatter = [[NSDateFormatter alloc] init]; 108 [tryFormatter setLenient: YES]; 109 [tryFormatter setTimeStyle: *s]; 110 [tryFormatter setDateStyle: NSDateFormatterNoStyle]; 118 NSDateFormatter *tryFormatter; 119 120 for (const NSDateFormatterStyle *s = formatterStyles ; *s != NSDateFormatterNoStyle ; *s++) { 121 tryFormatter = timeFormatterWithStyle(*s); 122 [tryFormatters addObject: tryFormatter]; 123 [tryFormatter release]; 124 } 125 for (NSString **s = timeFormats ; *s != nil ; *s++) { 126 tryFormatter = timeFormatterWithFormat(*s); 111 127 [tryFormatters addObject: tryFormatter]; 112 128 [tryFormatter release]; … … 144 160 NSEnumerator *e = [tryFormatters objectEnumerator]; 145 161 NSDateFormatter *tryFormatter; 146 147 // XXX untested; does this work? 162 NSString *cleaned = nil; 163 164 // don't let time specifications ending in "a" or "p" trigger Date::Manip 165 if ([self timeStyle] != NSDateFormatterNoStyle && 166 [string length] > 1 && 167 ![[NSCharacterSet letterCharacterSet] 168 characterIsMember: [string characterAtIndex: [string length] - 2]]) { 169 170 NSString *am = [self AMSymbol], *pm = [self PMSymbol]; 171 if (am != nil && [am length] > 1 && pm != nil && [pm length] > 1) { 172 173 NSString *a = [am substringToIndex: 1], *p = [pm substringToIndex: 1]; 174 if (![a isCaseInsensitiveLike: p]) { 175 176 NSString *last = [string substringFromIndex: [string length] - 1]; 177 if ([last isCaseInsensitiveLike: a]) 178 string = [string stringByAppendingString: [am substringFromIndex: 1]]; 179 if ([last isCaseInsensitiveLike: p]) 180 string = [string stringByAppendingString: [pm substringFromIndex: 1]]; 181 } 182 } 183 } 184 148 185 while ( (tryFormatter = [e nextObject]) != nil) { 149 186 date = [tryFormatter dateFromString: string]; 150 if (date != nil) goto success; 151 } 152 153 if (parse_natural_language_date == NULL) return nil; 187 188 if (date == nil) 189 continue; 190 191 if (([tryFormatter dateStyle] != NSDateFormatterNoStyle) || 192 ([tryFormatter timeStyle] != NSDateFormatterNoStyle)) 193 goto success; 194 195 // XXX ICU-based "format" formatters return 0 instead of nil 196 if ([date timeIntervalSince1970] == 0) 197 continue; 198 199 // even non-lenient ICU-based "format" formatters are insufficiently strict, 200 // permitting arbitrary characters before and after the parsed string 201 NSString *formatted = [tryFormatter stringFromDate: date]; 202 if (cleaned == nil) 203 cleaned = [[string componentsSeparatedByString: @" "] componentsJoinedByString: @""]; 204 if ([cleaned characterAtIndex: 0] != '0' && [formatted characterAtIndex: 0] == '0') 205 formatted = [formatted substringFromIndex: 1]; 206 207 if ([formatted isCaseInsensitiveLike: cleaned]) 208 goto success; 209 } 210 211 if (parse_natural_language_date == NULL) return NO; 154 212 155 213 date = parse_natural_language_date(string);
Note:
See TracChangeset
for help on using the changeset viewer.