From 0a534a99eb4259db61d4bbd6ac9f6a1f47445812 Mon Sep 17 00:00:00 2001 From: richard Date: Tue, 30 Jan 2001 12:05:02 +0000 Subject: [PATCH] Move some way towards support of MacOS-X timezone compatibility. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@8921 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 8 + Headers/gnustep/base/NSDate.h | 36 ++- Source/NSCalendarDate.m | 72 ++--- Source/NSTimeZone.m | 510 ++++++++++++++++++++-------------- 4 files changed, 380 insertions(+), 246 deletions(-) diff --git a/ChangeLog b/ChangeLog index e1931fb15..0f1c0e146 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2001-01-30 Richard Frith-Macdonald + + * Headers/Foundation/NSDate.h: Partial support added for MacOS-X + * Source/NSTimeZone.m: Updates to encode all time zones as the + abstract class, and added MacOS-X methods. + * Source/NSCalendarDate.m: Use NSTimeZone rather than NSTimeZoneDetail + throughout ... provide MacOS-X compatibility. + 2001-01-29 Adam Fedor * configure.in: Remove check for alternate libobjc and Headers diff --git a/Headers/gnustep/base/NSDate.h b/Headers/gnustep/base/NSDate.h index 41da850c0..f52fa4ffa 100644 --- a/Headers/gnustep/base/NSDate.h +++ b/Headers/gnustep/base/NSDate.h @@ -115,19 +115,15 @@ NSTimeInterval GSTime(int d, int m, int y, int hh, int mm, int ss, int mil); @interface NSTimeZone : NSObject //Creating and Initializing an NSTimeZone -+ (NSTimeZoneDetail*) defaultTimeZone; + (NSTimeZone*) localTimeZone; + (NSTimeZone*) timeZoneForSecondsFromGMT: (int)seconds; -+ (NSTimeZoneDetail*) timeZoneWithAbbreviation: (NSString*)abbreviation; + (NSTimeZone*) timeZoneWithName: (NSString*)aTimeZoneName; -- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date; //Managing Time Zones + (void) setDefaultTimeZone: (NSTimeZone*)aTimeZone; // Getting Time Zone Information + (NSDictionary*) abbreviationDictionary; -- (NSString*) timeZoneName; //Getting Arrays of Time Zones + (NSArray*) timeZoneArray; @@ -139,25 +135,40 @@ NSTimeInterval GSTime(int d, int m, int y, int hh, int mm, int ss, int mil); + (NSDictionary*) abbreviationMap; #endif +#ifndef STRICT_OPENSTEP +- (NSString*) abbreviation; +- (NSString*) abbreviationForDate: (NSDate*)aDate; +- (BOOL) isDaylightSavingTime; +- (BOOL) isDaylightSavingTimeForDate: (NSDate*)aDate; +- (BOOL) isEqualToTimeZone: (NSTimeZone*)aTimeZone; +- (NSString*) name; +- (int) secondsFromGMT; +- (int) secondsFromGMTForDate: (NSDate*)aDate; +#endif + +#ifndef STRICT_MACOS_X ++ (NSTimeZoneDetail*) defaultTimeZone; ++ (NSTimeZoneDetail*) timeZoneWithAbbreviation: (NSString*)abbreviation; +- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date; +- (NSString*) timeZoneName; +#endif + @end - +#ifndef STRICT_MACOS_X @interface NSTimeZoneDetail : NSTimeZone - -//Querying an NSTimeZoneDetail - (BOOL) isDaylightSavingTimeZone; - (NSString*) timeZoneAbbreviation; - (int) timeZoneSecondsFromGMT; - @end +#endif @interface NSCalendarDate : NSDate - { NSTimeInterval _seconds_since_ref; NSString *_calendar_format; - NSTimeZoneDetail *_time_zone; + NSTimeZone *_time_zone; } // Getting an NSCalendar Date @@ -222,7 +233,12 @@ NSTimeInterval GSTime(int d, int m, int y, int hh, int mm, int ss, int mil); // Getting and Setting Time Zones - (void) setTimeZone: (NSTimeZone*)aTimeZone; +#ifndef STRICT_OPENSTEP +- (NSTimeZone*) timeZone; +#endif +#ifndef STRICT_MACOS_X - (NSTimeZoneDetail*) timeZoneDetail; +#endif @end diff --git a/Source/NSCalendarDate.m b/Source/NSCalendarDate.m index 546afab4f..1676dd7f3 100644 --- a/Source/NSCalendarDate.m +++ b/Source/NSCalendarDate.m @@ -931,19 +931,28 @@ static inline int getDigits(const char *from, char *to, int limit) second: (unsigned int)second timeZone: (NSTimeZone *)aTimeZone { - int c; - NSTimeInterval s; + int c; + NSDate *d; + NSTimeInterval s; + NSTimeInterval oldOffset; // Calculate date as GMT s = GSTime(day, month, year, hour, minute, second, 0); // Assign time zone detail - _time_zone = RETAIN([aTimeZone - timeZoneDetailForDate: - [NSDate dateWithTimeIntervalSinceReferenceDate: s]]); + if (aTimeZone == nil) + { + _time_zone = RETAIN([NSTimeZone localTimeZone]); + } + else + { + _time_zone = RETAIN(aTimeZone); + } + d = [NSDate dateWithTimeIntervalSinceReferenceDate: s]; // Adjust date so it is correct for time zone. - s -= [_time_zone timeZoneSecondsFromGMT]; + oldOffset = [_time_zone secondsFromGMTForDate: d]; + s -= oldOffset; self = [self initWithTimeIntervalSinceReferenceDate: s]; /* Now permit up to five cycles of adjustment to allow for daylight savings. @@ -953,26 +962,19 @@ static inline int getDigits(const char *from, char *to, int limit) for (c = 0; c < 5 && self != nil; c++) { int y, m, d, h, mm, ss; - NSTimeZoneDetail *z; + NSTimeInterval newOffset; [self getYear: &y month: &m day: &d hour: &h minute: &mm second: &ss]; if (y==year && m==month && d==day && h==hour && mm==minute && ss==second) return self; - /* Has the time-zone detail changed? If so - adjust time for it, + /* Has the time-zone offset changed? If so - adjust time for it, other wise - try to adjust to the correct time. */ - z = [aTimeZone - timeZoneDetailForDate: - [NSDate dateWithTimeIntervalSinceReferenceDate: s]]; - if (z != _time_zone) + newOffset = [_time_zone secondsFromGMTForDate: self]; + if (newOffset != oldOffset) { - NSTimeInterval oldOffset; - NSTimeInterval newOffset; - - oldOffset = [_time_zone timeZoneSecondsFromGMT]; - ASSIGN(_time_zone, z); - newOffset = [_time_zone timeZoneSecondsFromGMT]; s += newOffset - oldOffset; + oldOffset = newOffset; } else { @@ -1011,11 +1013,10 @@ static inline int getDigits(const char *from, char *to, int limit) - (id) initWithTimeIntervalSinceReferenceDate: (NSTimeInterval)seconds { _seconds_since_ref = seconds; - if (!_calendar_format) + if (_calendar_format == nil) _calendar_format = @"%Y-%m-%d %H:%M:%S %z"; - if (!_time_zone) - _time_zone = RETAIN([[NSTimeZone localTimeZone] - timeZoneDetailForDate: self]); + if (_time_zone == nil) + _time_zone = RETAIN([NSTimeZone localTimeZone]); return self; } @@ -1036,7 +1037,7 @@ static inline int getDigits(const char *from, char *to, int limit) // Calculate hour, minute, and seconds d -= GREGORIAN_REFERENCE; d *= 86400; - a = abs(d - (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT])); + a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self])); b = a / 3600; *hour = (int)b; h = *hour; @@ -1056,7 +1057,7 @@ static inline int getDigits(const char *from, char *to, int limit) int r; // Get reference date in terms of days - a = (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT]) / 86400.0; + a = (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self]) / 86400.0; // Offset by Gregorian reference a += GREGORIAN_REFERENCE; r = (int)a; @@ -1107,7 +1108,7 @@ static inline int getDigits(const char *from, char *to, int limit) double a, d = [self dayOfCommonEra]; d -= GREGORIAN_REFERENCE; d *= 86400; - a = abs(d - (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT])); + a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self])); a = a / 3600; h = (int)a; @@ -1125,7 +1126,7 @@ static inline int getDigits(const char *from, char *to, int limit) double a, b, d = [self dayOfCommonEra]; d -= GREGORIAN_REFERENCE; d *= 86400; - a = abs(d - (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT])); + a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self])); b = a / 3600; h = (int)b; h = h * 3600; @@ -1152,7 +1153,7 @@ static inline int getDigits(const char *from, char *to, int limit) double a, b, c, d = [self dayOfCommonEra]; d -= GREGORIAN_REFERENCE; d *= 86400; - a = abs(d - (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT])); + a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self])); b = a / 3600; h = (int)b; h = h * 3600; @@ -1328,7 +1329,8 @@ static inline int getDigits(const char *from, char *to, int limit) case 'F': // milliseconds s = ([self dayOfCommonEra] - GREGORIAN_REFERENCE) * 86400.0; - s -= (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT]); + s -= (_seconds_since_ref + + [_time_zone secondsFromGMTForDate: self]); s = abs(s); s -= floor(s); ++i; @@ -1429,13 +1431,13 @@ static inline int getDigits(const char *from, char *to, int limit) case 'Z': ++i; k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", - [[_time_zone timeZoneAbbreviation] cString])); + [[_time_zone abbreviationForDate: self] cString])); j += k; break; case 'z': ++i; - z = [_time_zone timeZoneSecondsFromGMT]; + z = [_time_zone secondsFromGMTForDate: self]; if (z < 0) { z = -z; z /= 60; @@ -1511,14 +1513,18 @@ static inline int getDigits(const char *from, char *to, int limit) // Getting and Setting Time Zones - (void) setTimeZone: (NSTimeZone *)aTimeZone { - NSTimeZoneDetail *detail = [aTimeZone timeZoneDetailForDate: self]; + ASSIGN(_time_zone, aTimeZone); +} - ASSIGN(_time_zone, detail); +- (NSTimeZone*) timeZone +{ + return _time_zone; } - (NSTimeZoneDetail*) timeZoneDetail { - return _time_zone; + NSTimeZoneDetail *detail = [_time_zone timeZoneDetailForDate: self]; + return detail; } @end diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index e6671d098..4a986e386 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -107,7 +107,7 @@ struct ttinfo /* The local time zone. */ -static id localTimeZone; +static id localTimeZone; /* Dictionary for time zones. Each time zone must have a unique name. */ @@ -119,6 +119,7 @@ static NSDictionary *fake_abbrev_dict; /* Lock for creating time zones. */ static NSRecursiveLock *zone_mutex; +static Class NSTimeZoneClass; /* Decode the four bytes at PTR as a signed integer in network byte order. Based on code included in the GNU C Library 2.0.3. */ @@ -308,20 +309,6 @@ decode (const void *ptr) @implementation NSConcreteTimeZone -- (id) initWithName: (NSString*)aName - withTransitions: (NSArray*)trans - withDetails: (NSArray*)zoneDetails -{ - NSZone *z; - - [super init]; - z = [self zone]; - name = [aName copyWithZone: z]; - transitions = RETAIN(trans); - details = RETAIN(zoneDetails); - return self; -} - - (void) dealloc { RELEASE(name); @@ -338,21 +325,30 @@ decode (const void *ptr) [aCoder encodeObject: name]; } -- (id) awakeAfterUsingCoder: (NSCoder*)aCoder +- (id) initWithName: (NSString*)aName + withTransitions: (NSArray*)trans + withDetails: (NSArray*)zoneDetails { - if ([name isEqual: @"NSLocalTimeZone"]) + self = [super init]; + if (self != nil) { - return localTimeZone; + name = [aName copyWithZone: [self zone]]; + transitions = RETAIN(trans); + details = RETAIN(zoneDetails); } - return [NSTimeZone timeZoneWithName: name]; -} - -- (id) initWithCoder: (NSCoder*)aDecoder -{ - [aDecoder decodeValueOfObjCType: @encode(id) at: &name]; return self; } +- (NSString*) name +{ + return name; +} + +- (NSArray*) timeZoneDetailArray +{ + return details; +} + - (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date { unsigned index; @@ -388,16 +384,6 @@ decode (const void *ptr) return [details objectAtIndex: index]; } -- (NSArray*) timeZoneDetailArray -{ - return details; -} - -- (NSString*) timeZoneName -{ - return name; -} - @end @@ -414,32 +400,6 @@ static NSMapTable *absolutes = 0; } } -- (id) initWithOffset: (int)anOffset -{ - NSConcreteAbsoluteTimeZone *z; - - [zone_mutex lock]; - z = (NSConcreteAbsoluteTimeZone*)NSMapGet(absolutes, (void*)(gsaddr)anOffset); - if (z) - { - IF_NO_GC(RETAIN(z)); - RELEASE(self); - } - else - { - [super init]; - name = [[NSString alloc] initWithFormat: @"%d", anOffset]; - detail = [[NSConcreteTimeZoneDetail alloc] - initWithTimeZone: self withAbbrev: name - withOffset: anOffset withDST: NO]; - offset = anOffset; - z = self; - NSMapInsert(absolutes, (void*)(gsaddr)anOffset, (void*)z); - } - [zone_mutex unlock]; - return z; -} - - (void) dealloc { [zone_mutex lock]; @@ -455,49 +415,53 @@ static NSMapTable *absolutes = 0; [aCoder encodeObject: name]; } -- (id) initWithCoder: (NSCoder*)aDecoder +- (id) initWithOffset: (int)anOffset { - [aDecoder decodeValueOfObjCType: @encode(id) at: &name]; - offset = [name intValue]; - detail = [[NSConcreteTimeZoneDetail alloc] - initWithTimeZone: self withAbbrev: name - withOffset: offset withDST: NO]; - return self; + NSConcreteAbsoluteTimeZone *z; + + [zone_mutex lock]; + z = (NSConcreteAbsoluteTimeZone*)NSMapGet(absolutes, (void*)(gsaddr)anOffset); + if (z) + { + IF_NO_GC(RETAIN(z)); + RELEASE(self); + } + else + { + [super init]; + name = [[NSString alloc] initWithFormat: @"NSAbsoluteTimeZone:%d", + anOffset]; + detail = [[NSConcreteTimeZoneDetail alloc] + initWithTimeZone: self withAbbrev: name + withOffset: anOffset withDST: NO]; + offset = anOffset; + z = self; + NSMapInsert(absolutes, (void*)(gsaddr)anOffset, (void*)z); + } + [zone_mutex unlock]; + return z; } -- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date -{ - return detail; -} - -- (NSString*) timeZoneName +- (NSString*) name { return name; } - + - (NSArray*) timeZoneDetailArray { return [NSArray arrayWithObject: detail]; } +- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date +{ + return detail; +} + @end @implementation NSConcreteTimeZoneDetail -- (id) initWithTimeZone: (NSTimeZone*)aZone - withAbbrev: (NSString*)anAbbrev - withOffset: (int)anOffset - withDST: (BOOL)isDST -{ - [super init]; - timeZone = RETAIN(aZone); - abbrev = RETAIN(anAbbrev); - offset = anOffset; - is_dst = isDST; - return self; -} - - (void) dealloc { RELEASE(timeZone); @@ -519,48 +483,123 @@ static NSMapTable *absolutes = 0; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &is_dst]; return self; } + +- (id) initWithTimeZone: (NSTimeZone*)aZone + withAbbrev: (NSString*)anAbbrev + withOffset: (int)anOffset + withDST: (BOOL)isDST +{ + [super init]; + timeZone = RETAIN(aZone); + abbrev = RETAIN(anAbbrev); + offset = anOffset; + is_dst = isDST; + return self; +} -- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date -{ - return [timeZone timeZoneDetailForDate: date]; -} - -- (NSString*) timeZoneName -{ - return [timeZone timeZoneName]; -} - -- (NSArray*) timeZoneDetailArray -{ - return [timeZone timeZoneDetailArray]; -} - - (BOOL) isDaylightSavingTimeZone { return is_dst; } +- (NSString*) name +{ + return [timeZone name]; +} + - (NSString*) timeZoneAbbreviation { return abbrev; } +- (NSArray*) timeZoneDetailArray +{ + return [timeZone timeZoneDetailArray]; +} + +- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date +{ + return [timeZone timeZoneDetailForDate: date]; +} + - (int) timeZoneSecondsFromGMT { return offset; } + +- (int) timeZoneSecondsFromGMTForDate: (NSDate*)aDate +{ + return offset; +} @end @implementation NSTimeZone ++ (NSDictionary*) abbreviationDictionary +{ + return fake_abbrev_dict; +} + ++ (NSDictionary*) abbreviationMap +{ + /* Instead of creating the abbreviation dictionary when the class is + initialized, we create it when we first need it, since the + dictionary can be potentially very large, considering that it's + almost never used. */ + + static NSMutableDictionary *abbreviationDictionary = nil; + FILE *file; // For the file containing the abbreviation dictionary + char abbrev[80], name[80]; + NSString *fileName; + + if (abbreviationDictionary != nil) + return abbreviationDictionary; + + /* Read dictionary from file. */ + abbreviationDictionary = [[NSMutableDictionary alloc] init]; + fileName = [NSTimeZone getAbbreviationFile]; +#if defined(__WIN32__) + file = fopen([fileName fileSystemRepresentation], "rb"); +#else + file = fopen([fileName fileSystemRepresentation], "r"); +#endif + if (file == NULL) + [NSException + raise: NSInternalInconsistencyException + format: @"Failed to open time zone abbreviation dictionary."]; + while (fscanf(file, "%79s %79s", abbrev, name) == 2) + { + id a, the_name, the_abbrev; + + the_name = [NSString stringWithCString: name]; + the_abbrev = [NSString stringWithCString: abbrev]; + a = [abbreviationDictionary objectForKey: the_abbrev]; + if (a == nil) + { + a = [[NSMutableArray alloc] init]; + [abbreviationDictionary setObject: a forKey: the_abbrev]; + } + [a addObject: the_name]; + } + fclose(file); + + return abbreviationDictionary; +} + ++ (NSTimeZoneDetail*) defaultTimeZone +{ + return [localTimeZone timeZoneDetailForDate: [NSDate date]]; +} + + (void) initialize { if (self == [NSTimeZone class]) { - id localZoneString = nil; + id localZoneString = nil; + NSTimeZoneClass = self; zone_mutex = [NSRecursiveLock new]; zoneDictionary = [[NSMutableDictionary alloc] init]; @@ -579,7 +618,7 @@ static NSMapTable *absolutes = 0; /* * Try to get timezone from LOCAL_TIME_FILE. */ - NSString *f = [NSTimeZone getLocalTimeFile]; + NSString *f = [NSTimeZoneClass getLocalTimeFile]; char zone_name[80]; FILE *fp; @@ -608,7 +647,7 @@ static NSMapTable *absolutes = 0; } if (localZoneString != nil) { - localTimeZone = [NSTimeZone timeZoneWithName: localZoneString]; + localTimeZone = [NSTimeZoneClass timeZoneWithName: localZoneString]; } else { @@ -623,7 +662,7 @@ static NSMapTable *absolutes = 0; if (localTimeZone == nil) { NSLog(@"Using time zone with absolute offset 0."); - localTimeZone = [NSTimeZone timeZoneForSecondsFromGMT: 0]; + localTimeZone = [NSTimeZoneClass timeZoneForSecondsFromGMT: 0]; } IF_NO_GC(RETAIN(localTimeZone)); @@ -631,21 +670,53 @@ static NSMapTable *absolutes = 0; } } -- (NSString*) description -{ - return [self timeZoneName]; -} - -+ (NSTimeZoneDetail*) defaultTimeZone -{ - return [localTimeZone timeZoneDetailForDate: [NSDate date]]; -} - + (NSTimeZone*) localTimeZone { return localTimeZone; } ++ (void) setDefaultTimeZone: (NSTimeZone*)aTimeZone +{ + if (aTimeZone == nil) + [NSException raise: NSInvalidArgumentException + format: @"Nil time zone specified."]; + ASSIGN(localTimeZone, aTimeZone); +} + ++ (NSArray*) timeZoneArray +{ + /* We create the array only when we need it to reduce overhead. */ + + static NSArray *regionsArray = nil; + int index, i; + char name[80]; + FILE *file; + id temp_array[24]; + NSString *fileName; + + if (regionsArray != nil) + return regionsArray; + + for (i = 0; i < 24; i++) + temp_array[i] = [NSMutableArray array]; + + fileName = [NSTimeZoneClass getRegionsFile]; +#if defined(__WIN32__) + file = fopen([fileName fileSystemRepresentation], "rb"); +#else + file = fopen([fileName fileSystemRepresentation], "r"); +#endif + if (file == NULL) + [NSException + raise: NSInternalInconsistencyException + format: @"Failed to open time zone regions array file."]; + while (fscanf(file, "%d %s", &index, name) == 2) + [temp_array[index] addObject: [NSString stringWithCString: name]]; + fclose(file); + regionsArray = [[NSArray alloc] initWithObjects: temp_array count: 24]; + return regionsArray; +} + + (NSTimeZone*) timeZoneForSecondsFromGMT: (int)seconds { /* We simply return the following because an existing time zone with @@ -702,23 +773,42 @@ static NSMapTable *absolutes = 0; return zone; } - /* Make sure that only time zone files are accessed. - FIXME: Make this more robust. */ - if ([aTimeZoneName length] == 0 - || ([aTimeZoneName cString])[0] == '/' - || strchr([aTimeZoneName cString], '.') != NULL) + i = [aTimeZoneName length]; + if (i == 0) { - NSLog(@"Disallowed time zone name `%@'.", aTimeZoneName); + NSLog(@"Disallowed null time zone name"); [zone_mutex unlock]; return nil; } + else + { + const char *str = [aTimeZoneName lossyCString]; + + if ([aTimeZoneName hasPrefix: @"NSAbsoluteTimeZone:"] == YES) + { + i = atoi(&str[19]); + [zone_mutex unlock]; + zone = [[NSConcreteAbsoluteTimeZone alloc] initWithOffset: i]; + AUTORELEASE(zone); + return zone; + } + + /* Make sure that only time zone files are accessed. + FIXME: Make this more robust. */ + if ((str)[0] == '/' || strchr(str, '.') != NULL) + { + NSLog(@"Disallowed time zone name `%@'.", aTimeZoneName); + [zone_mutex unlock]; + return nil; + } + } NS_DURING { zone = [NSConcreteTimeZone alloc]; /* Open file. */ - fileName = [NSTimeZone getTimeZoneFile: aTimeZoneName]; + fileName = [NSTimeZoneClass getTimeZoneFile: aTimeZoneName]; #if defined(__WIN32__) file = fopen([fileName fileSystemRepresentation], "rb"); #else @@ -799,7 +889,7 @@ static NSMapTable *absolutes = 0; [zone initWithName: aTimeZoneName withTransitions: transArray withDetails: detailsArray]; - [zoneDictionary setObject: zone forKey: [zone timeZoneName]]; + [zoneDictionary setObject: zone forKey: [zone name]]; } NS_HANDLER { @@ -820,107 +910,111 @@ static NSMapTable *absolutes = 0; return zone; } -- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date + +- (NSString*) abbreviation { - return [self subclassResponsibility: _cmd]; + return [self abbreviationForDate: [NSDate date]]; } -+ (void) setDefaultTimeZone: (NSTimeZone*)aTimeZone +- (NSString*) abbreviationForDate: (NSDate*)when { - if (aTimeZone == nil) - [NSException raise: NSInvalidArgumentException - format: @"Nil time zone specified."]; - ASSIGN(localTimeZone, aTimeZone); + NSTimeZoneDetail *detail; + + detail = [self timeZoneDetailForDate: when]; + return [detail timeZoneAbbreviation]; } -+ (NSDictionary*) abbreviationDictionary +- (Class) classForCoder { - return fake_abbrev_dict; + return NSTimeZoneClass; } -+ (NSDictionary*) abbreviationMap +- (id) copyWithZone: (NSZone*)z { - /* Instead of creating the abbreviation dictionary when the class is - initialized, we create it when we first need it, since the - dictionary can be potentially very large, considering that it's - almost never used. */ + return RETAIN(self); +} - static NSMutableDictionary *abbreviationDictionary = nil; - FILE *file; // For the file containing the abbreviation dictionary - char abbrev[80], name[80]; - NSString *fileName; +- (NSString*) description +{ + return [self name]; +} - if (abbreviationDictionary != nil) - return abbreviationDictionary; - - /* Read dictionary from file. */ - abbreviationDictionary = [[NSMutableDictionary alloc] init]; - fileName = [NSTimeZone getAbbreviationFile]; -#if defined(__WIN32__) - file = fopen([fileName fileSystemRepresentation], "rb"); -#else - file = fopen([fileName fileSystemRepresentation], "r"); -#endif - if (file == NULL) - [NSException - raise: NSInternalInconsistencyException - format: @"Failed to open time zone abbreviation dictionary."]; - while (fscanf(file, "%79s %79s", abbrev, name) == 2) +- (void) encodeWithCoder: (NSCoder*)aCoder +{ + if (self == localTimeZone) { - id a, the_name, the_abbrev; - - the_name = [NSString stringWithCString: name]; - the_abbrev = [NSString stringWithCString: abbrev]; - a = [abbreviationDictionary objectForKey: the_abbrev]; - if (a == nil) - { - a = [[NSMutableArray alloc] init]; - [abbreviationDictionary setObject: a forKey: the_abbrev]; - } - [a addObject: the_name]; + [aCoder encodeObject: @"NSLocalTimeZone"]; + } + else + { + [aCoder encodeObject: [self name]]; } - fclose(file); - - return abbreviationDictionary; } -- (NSString*) timeZoneName +- (id) initWithCoder: (NSCoder*)aDecoder +{ + NSString *name; + + [aDecoder decodeValueOfObjCType: @encode(id) at: &name]; + RELEASE(self); + if ([name isEqual: @"NSLocalTimeZone"]) + { + self = RETAIN(localTimeZone); + } + else + { + self = RETAIN([NSTimeZoneClass timeZoneWithName: name]); + } + return self; +} + +- (BOOL) isDaylightSavingTime +{ + return [self isDaylightSavingTimeForDate: [NSDate date]]; +} + +- (BOOL) isDaylightSavingTimeForDate: (NSDate*)aDate +{ + NSTimeZoneDetail *detail; + + detail = [self timeZoneDetailForDate: aDate]; + return [detail isDaylightSavingTimeZone]; +} + +- (BOOL) isEqual: (id)other +{ + if (other == self) + return YES; + if ([other isKindOfClass: NSTimeZoneClass] == NO) + return NO; + return [self isEqualToTimeZone: other]; +} + +- (BOOL) isEqualToTimeZone: (NSTimeZone*)aTimeZone +{ + if (aTimeZone == self) + return YES; + if ([[self name] isEqual: [aTimeZone name]] == YES) + return YES; + return NO; +} + +- (NSString*) name { return [self subclassResponsibility: _cmd]; } -+ (NSArray*) timeZoneArray +- (int) secondsFromGMT { - /* We create the array only when we need it to reduce overhead. */ + return [self secondsFromGMTForDate: [NSDate date]]; +} - static NSArray *regionsArray = nil; - int index, i; - char name[80]; - FILE *file; - id temp_array[24]; - NSString *fileName; +- (int) secondsFromGMTForDate: (NSDate*)when +{ + NSTimeZoneDetail *detail; - if (regionsArray != nil) - return regionsArray; - - for (i = 0; i < 24; i++) - temp_array[i] = [NSMutableArray array]; - - fileName = [NSTimeZone getRegionsFile]; -#if defined(__WIN32__) - file = fopen([fileName fileSystemRepresentation], "rb"); -#else - file = fopen([fileName fileSystemRepresentation], "r"); -#endif - if (file == NULL) - [NSException - raise: NSInternalInconsistencyException - format: @"Failed to open time zone regions array file."]; - while (fscanf(file, "%d %s", &index, name) == 2) - [temp_array[index] addObject: [NSString stringWithCString: name]]; - fclose(file); - regionsArray = [[NSArray alloc] initWithObjects: temp_array count: 24]; - return regionsArray; + detail = [self timeZoneDetailForDate: when]; + return [detail timeZoneSecondsFromGMT]; } - (NSArray*) timeZoneDetailArray @@ -928,6 +1022,16 @@ static NSMapTable *absolutes = 0; return [self subclassResponsibility: _cmd]; } +- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date +{ + return [self subclassResponsibility: _cmd]; +} + +- (NSString*) timeZoneName +{ + return [self name]; +} + @end @@ -937,7 +1041,7 @@ static NSMapTable *absolutes = 0; { return [NSString stringWithFormat: @"%@(%@, %s%d)", - [self timeZoneName], + [self name], [self timeZoneAbbreviation], ([self isDaylightSavingTimeZone]? "IS_DST, ": ""), [self timeZoneSecondsFromGMT]];