Changeset 43 for trunk/Cocoa/Pester/Source/NJRDateFormatter.m
- Timestamp:
- 11/10/02 05:34:08 (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Cocoa/Pester/Source/NJRDateFormatter.m
r21 r43 9 9 #import "NJRDateFormatter.h" 10 10 11 NSUserDefaults *locale; 11 12 12 13 @implementation NJRDateFormatter 14 15 + (void)initialize; 16 { 17 locale = [[NSUserDefaults standardUserDefaults] retain]; 18 } 19 20 + (NSString *)format:(NSString *)format withoutComponent:(unichar)component; 21 { 22 NSScanner *scanner = [NSScanner scannerWithString: format]; 23 NSRange range; 24 [scanner setCharactersToBeSkipped: [NSCharacterSet characterSetWithCharactersInString: @""]]; 25 while ([scanner scanUpToString: @"%" intoString: nil] || ![scanner isAtEnd]) { 26 range.location = [scanner scanLocation]; 27 [scanner scanUpToCharactersFromSet: [NSCharacterSet letterCharacterSet] intoString: nil]; 28 if ([format characterAtIndex: [scanner scanLocation]] == component) { 29 if ([scanner scanUpToString: @"%" intoString: nil] && ![scanner isAtEnd]) { 30 NSMutableString *mutableFormat = [format mutableCopy]; 31 if (range.location != 0 && [[NSCharacterSet punctuationCharacterSet] characterIsMember: [format characterAtIndex: range.location - 1]]) { 32 range.location--; // "%I:%M:%S%p" -> "%I:%M%p" 33 } 34 range.length = [scanner scanLocation] - range.location; 35 [mutableFormat deleteCharactersInRange: range]; 36 format = [mutableFormat copy]; 37 [mutableFormat release]; 38 return [format autorelease]; 39 } else { 40 range = [format rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet] options: NSBackwardsSearch range: NSMakeRange(0, range.location)]; 41 return [format substringToIndex: NSMaxRange(range)]; 42 } 43 } 44 } 45 return format; 46 } 47 48 + (NSString *)localizedDateFormatIncludingWeekday:(BOOL)weekday; 49 { 50 NSString *format = [locale stringForKey: NSDateFormatString]; 51 if (weekday) return format; 52 return [self format: format withoutComponent: (unichar)'A']; 53 } 54 55 + (NSString *)localizedShortDateFormatIncludingWeekday:(BOOL)weekday; 56 { 57 NSString *format = [locale stringForKey: NSShortDateFormatString]; 58 if (weekday) return format; 59 return [self format: format withoutComponent: (unichar)'A']; 60 } 61 62 NSString *stringByInsertingStringAtLocation(NSString *string, NSString *insert, int location) { 63 return [NSString stringWithFormat: @"%@%@%@", [string substringToIndex: location], insert, 64 [string substringFromIndex: location]]; 65 } 66 67 + (NSString *)localizedTimeFormatIncludingSeconds:(BOOL)seconds; 68 { 69 NSString *format = [locale stringForKey: NSTimeFormatString]; 70 NSArray *ampm = [locale arrayForKey: NSAMPMDesignation]; 71 NSString *am = [ampm objectAtIndex: 0], *pm = [ampm objectAtIndex: 1]; 72 // work around bug with inconsistent AM/PM and time format 73 if ([am isEqualToString: @""] && [pm isEqualToString: @""]) 74 format = [self format: format withoutComponent: 'p']; 75 else { 76 NSRange ampmComponentRange = [format rangeOfString: @"%p"]; 77 NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet]; 78 BOOL needSpaceInFormatString = ![whitespace characterIsMember: [am characterAtIndex: 0]]; 79 if (ampmComponentRange.location == NSNotFound) // "%1I:%M:%S" -> "%1I:%M:%S%p", "%1I:%M:%S %p" 80 format = [format stringByAppendingString: (needSpaceInFormatString ? @" %p" : @"%p")]; 81 else { 82 NSRange whitespaceRange = [format rangeOfCharacterFromSet: whitespace options: NSBackwardsSearch range: NSMakeRange(0, ampmComponentRange.location)]; 83 if (whitespaceRange.location == NSNotFound) { 84 if (needSpaceInFormatString) // "%1I:%M:%S%p" -> "%1I:%M:%S %p" 85 format = stringByInsertingStringAtLocation(format, @" ", ampmComponentRange.location); 86 // else "%1I:%M:%S%p" -> no change 87 } else { 88 if (NSMaxRange(whitespaceRange) == ampmComponentRange.location) { 89 if (!needSpaceInFormatString) // "%1I:%M:%S %p" -> "%1I:%M:%S%p" 90 format = [[format substringToIndex: whitespaceRange.location] stringByAppendingString: [format substringFromIndex: ampmComponentRange.location]]; 91 // else "%1I:%M:%S %p" -> no change 92 } else { 93 if (needSpaceInFormatString) 94 format = stringByInsertingStringAtLocation(format, @" ", ampmComponentRange.location); 95 // else "%1I %M:%S%p" -> no change 96 } 97 } 98 } 99 } 100 if (seconds) return format; 101 return [self format: format withoutComponent: 'S']; 102 } 13 103 14 104 // workaround for bug in Jaguar (and earlier?) NSCalendarDate dateWithNaturalLanguageString: … … 25 115 if (firstValidCharacter.length == 0) 26 116 return @""; 27 lastValidCharacter = [string rangeOfCharacterFromSet:nonWhitespace options: NSBackwardsSearch];117 lastValidCharacter = [string rangeOfCharacterFromSet:nonWhitespace options: NSBackwardsSearch]; 28 118 29 119 if (firstValidCharacter.location == 0 && lastValidCharacter.location == [string length] - 1) 30 120 return string; 31 121 else 32 return [string substringWithRange: NSUnionRange(firstValidCharacter, lastValidCharacter)];122 return [string substringWithRange: NSUnionRange(firstValidCharacter, lastValidCharacter)]; 33 123 } 34 124 125 - (id)initWithDateFormat:(NSString *)format allowNaturalLanguage:(BOOL)flag; 126 { 127 if ( (self = [super initWithDateFormat: format allowNaturalLanguage: flag]) != nil) { 128 NSRange ampmRange = [format rangeOfString: @"%p"]; 129 NSArray *ampm = [locale arrayForKey: NSAMPMDesignation]; 130 NSString *am = [ampm objectAtIndex: 0], *pm = [ampm objectAtIndex: 1]; 131 if (flag && ampmRange.location != NSNotFound && 132 [[locale stringForKey: NSTimeFormatString] rangeOfString: @"%p"].location == NSNotFound && ![am isEqualToString: pm]) { 133 // workaround for bug in NSCalendarDate dateWithNaturalLanguageString: discarding AM/PM value when AM/PM designations have spaces in them (of which the use thereof is a workaround for NSDateFormatter discarding the AM/PM value) 134 NSMutableString *paddedFormat = [format mutableCopy]; 135 [paddedFormat replaceCharactersInRange: ampmRange withString: @" %p"]; 136 alteredLocale = [[locale dictionaryRepresentation] mutableCopy]; 137 [(NSMutableDictionary *)alteredLocale setObject: paddedFormat forKey: NSTimeFormatString]; 138 [(NSMutableDictionary *)alteredLocale setObject: 139 [NSArray arrayWithObjects: stringByRemovingSurroundingWhitespace(am), 140 stringByRemovingSurroundingWhitespace(pm)] forKey: NSAMPMDesignation]; 141 [paddedFormat release]; 142 } else { 143 alteredLocale = [(NSDictionary *)locale retain]; 144 } 145 } 146 return self; 147 } 148 149 - (void)dealloc; 150 { 151 [alteredLocale release]; 152 [super dealloc]; 153 } 35 154 36 155 - (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error … … 41 160 if (string == nil) return nil; 42 161 NS_DURING // dateWithNaturalLanguageString: can throw an exception 43 date = [NSCalendarDate dateWithNaturalLanguageString: stringByRemovingSurroundingWhitespace(string)]; 162 date = [NSCalendarDate dateWithNaturalLanguageString: stringByRemovingSurroundingWhitespace(string) locale: alteredLocale]; 163 // NSLog(@"%@: natural language date is %@", string, date); 44 164 NS_HANDLER 45 165 if (error != nil) *error = [localException reason]; 46 166 NS_VALUERETURN(NO, BOOL); 47 167 NS_ENDHANDLER 168 // [super getObjectValue: anObject forString: string errorDescription: error]; 169 // NSLog(@"%@: formatter date is %@", string, anObject == nil ? @"(null)" : *anObject); 48 170 if (date == nil) return [super getObjectValue: anObject forString: string errorDescription: error]; 49 171 *anObject = date;
Note:
See TracChangeset
for help on using the changeset viewer.