source: trunk/Cocoa/Pester/Source/NJRDateFormatter.m@ 572

Last change on this file since 572 was 367, checked in by Nicholas Riley, 16 years ago

DynaLoader-10.[45].a: Tiger and Leopard versions, since Tiger's
DynaLoader.a crashes on Leopard ppc.

DynaLoader.a: Renamed to DynaLoader-10.4.a.

English.lproj/InfoPlist.strings: Updated for 1.1b7.

Info-Pester.plist: Updated for 1.1b7.

NJRDateFormatter.m: Conditionally load ParseDate dylib (see above).

ParseDate.[hm]: Split out from NJRDateFormatter.m.

Read Me.rtfd/TXT.rtf: Updated for 1.1b7.

File size: 4.8 KB
Line 
1//
2// NJRDateFormatter.m
3// Pester
4//
5// Created by Nicholas Riley on Wed Oct 09 2002.
6// Copyright (c) 2002 Nicholas Riley. All rights reserved.
7//
8
9#import "NJRDateFormatter.h"
10#import "ParseDate.h"
11#include <dlfcn.h>
12
13// workaround for bug in Jaguar (and earlier?) NSCalendarDate dateWithNaturalLanguageString:
14NSString *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)];
32}
33
34static const NSDateFormatterStyle formatterStyles[] = {
35 NSDateFormatterShortStyle,
36 NSDateFormatterMediumStyle,
37 NSDateFormatterLongStyle,
38 NSDateFormatterFullStyle,
39 NSDateFormatterNoStyle
40};
41
42@implementation NJRDateFormatter
43
44#pragma mark initialize-release
45
46+ (void)initialize;
47{
48 long minorVersion, majorVersion;
49 Gestalt(gestaltSystemVersionMajor, &majorVersion);
50 Gestalt(gestaltSystemVersionMinor, &minorVersion);
51 if (majorVersion != 10)
52 return;
53
54 NSString *libName;
55 if (minorVersion == 4) {
56 libName = @"libParseDate-10.4";
57 } else if (minorVersion == 5) {
58 libName = @"libParseDate-10.5";
59 } else {
60 return;
61 }
62
63 NSString *libPath = [[NSBundle mainBundle] pathForResource: libName ofType: @"dylib"];
64 if (libPath == nil)
65 return;
66
67 void *lib = dlopen([libPath fileSystemRepresentation], RTLD_LAZY | RTLD_GLOBAL);
68 const char *libError;
69 if ( (libError = dlerror()) != NULL) {
70 NSLog(@"failed to dlopen %@: %s", libPath, libError);
71 return;
72 }
73
74 parse_natural_language_date = dlsym(lib, "parse_natural_language_date");
75 if ( (libError = dlerror()) != NULL) {
76 NSLog(@"failed to look up parse_natural_language_date in %@: %s", libPath, libError);
77 parse_natural_language_date = NULL;
78 return;
79 }
80}
81
82+ (NJRDateFormatter *)dateFormatter;
83{
84 NJRDateFormatter *formatter = [[self alloc] init];
85 NSMutableArray *tryFormatters = [[NSMutableArray alloc] init];
86
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];
92 [tryFormatters addObject: tryFormatter];
93 [tryFormatter release];
94 }
95 // XXX do this in init
96 formatter->tryFormatters = tryFormatters;
97
98 return [formatter autorelease];
99}
100
101+ (NJRDateFormatter *)timeFormatter;
102{
103 NJRDateFormatter *formatter = [[self alloc] init];
104 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];
111 [tryFormatters addObject: tryFormatter];
112 [tryFormatter release];
113 }
114 formatter->tryFormatters = tryFormatters;
115
116 return [formatter autorelease];
117}
118
119- (void)dealloc;
120{
121 [tryFormatters release]; tryFormatters = nil;
122 [super dealloc];
123}
124
125#pragma mark primitive formatter
126
127- (NSString *)stringForObjectValue:(id)obj;
128{
129 return [super stringForObjectValue: obj];
130}
131
132- (NSAttributedString *)attributedStringForObjectValue:(id)obj withDefaultAttributes:(NSDictionary *)attrs;
133{
134 return [super attributedStringForObjectValue: obj
135 withDefaultAttributes: attrs];
136}
137
138- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
139{
140 if ([super getObjectValue: anObject forString: string errorDescription: error])
141 return YES;
142
143 NSDate *date;
144 NSEnumerator *e = [tryFormatters objectEnumerator];
145 NSDateFormatter *tryFormatter;
146
147 // XXX untested; does this work?
148 while ( (tryFormatter = [e nextObject]) != nil) {
149 date = [tryFormatter dateFromString: string];
150 if (date != nil) goto success;
151 }
152
153 if (parse_natural_language_date == NULL) return nil;
154
155 date = parse_natural_language_date(string);
156 if (date != nil) goto success;
157
158 return NO;
159
160success:
161 *anObject = date;
162 if (error != NULL) *error = nil;
163 return YES;
164}
165
166#pragma mark miscellaneous
167
168+ (BOOL)naturalLanguageParsingAvailable;
169{
170 return (parse_natural_language_date != NULL);
171}
172@end
Note: See TracBrowser for help on using the repository browser.