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

Last change on this file since 367 was 367, checked in by Nicholas Riley, 12 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.