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
This commit is contained in:
richard 2001-01-30 12:05:02 +00:00
parent 0dd271945f
commit 0a534a99eb
4 changed files with 380 additions and 246 deletions

View file

@ -1,3 +1,11 @@
2001-01-30 Richard Frith-Macdonald <rfm@gnu.org>
* 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 <fedor@gnu.org> 2001-01-29 Adam Fedor <fedor@gnu.org>
* configure.in: Remove check for alternate libobjc and Headers * configure.in: Remove check for alternate libobjc and Headers

View file

@ -115,19 +115,15 @@ NSTimeInterval GSTime(int d, int m, int y, int hh, int mm, int ss, int mil);
@interface NSTimeZone : NSObject @interface NSTimeZone : NSObject
//Creating and Initializing an NSTimeZone //Creating and Initializing an NSTimeZone
+ (NSTimeZoneDetail*) defaultTimeZone;
+ (NSTimeZone*) localTimeZone; + (NSTimeZone*) localTimeZone;
+ (NSTimeZone*) timeZoneForSecondsFromGMT: (int)seconds; + (NSTimeZone*) timeZoneForSecondsFromGMT: (int)seconds;
+ (NSTimeZoneDetail*) timeZoneWithAbbreviation: (NSString*)abbreviation;
+ (NSTimeZone*) timeZoneWithName: (NSString*)aTimeZoneName; + (NSTimeZone*) timeZoneWithName: (NSString*)aTimeZoneName;
- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date;
//Managing Time Zones //Managing Time Zones
+ (void) setDefaultTimeZone: (NSTimeZone*)aTimeZone; + (void) setDefaultTimeZone: (NSTimeZone*)aTimeZone;
// Getting Time Zone Information // Getting Time Zone Information
+ (NSDictionary*) abbreviationDictionary; + (NSDictionary*) abbreviationDictionary;
- (NSString*) timeZoneName;
//Getting Arrays of Time Zones //Getting Arrays of Time Zones
+ (NSArray*) timeZoneArray; + (NSArray*) timeZoneArray;
@ -139,25 +135,40 @@ NSTimeInterval GSTime(int d, int m, int y, int hh, int mm, int ss, int mil);
+ (NSDictionary*) abbreviationMap; + (NSDictionary*) abbreviationMap;
#endif #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 @end
#ifndef STRICT_MACOS_X
@interface NSTimeZoneDetail : NSTimeZone @interface NSTimeZoneDetail : NSTimeZone
//Querying an NSTimeZoneDetail
- (BOOL) isDaylightSavingTimeZone; - (BOOL) isDaylightSavingTimeZone;
- (NSString*) timeZoneAbbreviation; - (NSString*) timeZoneAbbreviation;
- (int) timeZoneSecondsFromGMT; - (int) timeZoneSecondsFromGMT;
@end @end
#endif
@interface NSCalendarDate : NSDate @interface NSCalendarDate : NSDate
{ {
NSTimeInterval _seconds_since_ref; NSTimeInterval _seconds_since_ref;
NSString *_calendar_format; NSString *_calendar_format;
NSTimeZoneDetail *_time_zone; NSTimeZone *_time_zone;
} }
// Getting an NSCalendar Date // 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 // Getting and Setting Time Zones
- (void) setTimeZone: (NSTimeZone*)aTimeZone; - (void) setTimeZone: (NSTimeZone*)aTimeZone;
#ifndef STRICT_OPENSTEP
- (NSTimeZone*) timeZone;
#endif
#ifndef STRICT_MACOS_X
- (NSTimeZoneDetail*) timeZoneDetail; - (NSTimeZoneDetail*) timeZoneDetail;
#endif
@end @end

View file

@ -931,19 +931,28 @@ static inline int getDigits(const char *from, char *to, int limit)
second: (unsigned int)second second: (unsigned int)second
timeZone: (NSTimeZone *)aTimeZone timeZone: (NSTimeZone *)aTimeZone
{ {
int c; int c;
NSTimeInterval s; NSDate *d;
NSTimeInterval s;
NSTimeInterval oldOffset;
// Calculate date as GMT // Calculate date as GMT
s = GSTime(day, month, year, hour, minute, second, 0); s = GSTime(day, month, year, hour, minute, second, 0);
// Assign time zone detail // Assign time zone detail
_time_zone = RETAIN([aTimeZone if (aTimeZone == nil)
timeZoneDetailForDate: {
[NSDate dateWithTimeIntervalSinceReferenceDate: s]]); _time_zone = RETAIN([NSTimeZone localTimeZone]);
}
else
{
_time_zone = RETAIN(aTimeZone);
}
d = [NSDate dateWithTimeIntervalSinceReferenceDate: s];
// Adjust date so it is correct for time zone. // Adjust date so it is correct for time zone.
s -= [_time_zone timeZoneSecondsFromGMT]; oldOffset = [_time_zone secondsFromGMTForDate: d];
s -= oldOffset;
self = [self initWithTimeIntervalSinceReferenceDate: s]; self = [self initWithTimeIntervalSinceReferenceDate: s];
/* Now permit up to five cycles of adjustment to allow for daylight savings. /* 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++) for (c = 0; c < 5 && self != nil; c++)
{ {
int y, m, d, h, mm, ss; int y, m, d, h, mm, ss;
NSTimeZoneDetail *z; NSTimeInterval newOffset;
[self getYear: &y month: &m day: &d hour: &h minute: &mm second: &ss]; [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) if (y==year && m==month && d==day && h==hour && mm==minute && ss==second)
return self; 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. */ other wise - try to adjust to the correct time. */
z = [aTimeZone newOffset = [_time_zone secondsFromGMTForDate: self];
timeZoneDetailForDate: if (newOffset != oldOffset)
[NSDate dateWithTimeIntervalSinceReferenceDate: s]];
if (z != _time_zone)
{ {
NSTimeInterval oldOffset;
NSTimeInterval newOffset;
oldOffset = [_time_zone timeZoneSecondsFromGMT];
ASSIGN(_time_zone, z);
newOffset = [_time_zone timeZoneSecondsFromGMT];
s += newOffset - oldOffset; s += newOffset - oldOffset;
oldOffset = newOffset;
} }
else else
{ {
@ -1011,11 +1013,10 @@ static inline int getDigits(const char *from, char *to, int limit)
- (id) initWithTimeIntervalSinceReferenceDate: (NSTimeInterval)seconds - (id) initWithTimeIntervalSinceReferenceDate: (NSTimeInterval)seconds
{ {
_seconds_since_ref = seconds; _seconds_since_ref = seconds;
if (!_calendar_format) if (_calendar_format == nil)
_calendar_format = @"%Y-%m-%d %H:%M:%S %z"; _calendar_format = @"%Y-%m-%d %H:%M:%S %z";
if (!_time_zone) if (_time_zone == nil)
_time_zone = RETAIN([[NSTimeZone localTimeZone] _time_zone = RETAIN([NSTimeZone localTimeZone]);
timeZoneDetailForDate: self]);
return self; return self;
} }
@ -1036,7 +1037,7 @@ static inline int getDigits(const char *from, char *to, int limit)
// Calculate hour, minute, and seconds // Calculate hour, minute, and seconds
d -= GREGORIAN_REFERENCE; d -= GREGORIAN_REFERENCE;
d *= 86400; d *= 86400;
a = abs(d - (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT])); a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self]));
b = a / 3600; b = a / 3600;
*hour = (int)b; *hour = (int)b;
h = *hour; h = *hour;
@ -1056,7 +1057,7 @@ static inline int getDigits(const char *from, char *to, int limit)
int r; int r;
// Get reference date in terms of days // 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 // Offset by Gregorian reference
a += GREGORIAN_REFERENCE; a += GREGORIAN_REFERENCE;
r = (int)a; r = (int)a;
@ -1107,7 +1108,7 @@ static inline int getDigits(const char *from, char *to, int limit)
double a, d = [self dayOfCommonEra]; double a, d = [self dayOfCommonEra];
d -= GREGORIAN_REFERENCE; d -= GREGORIAN_REFERENCE;
d *= 86400; d *= 86400;
a = abs(d - (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT])); a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self]));
a = a / 3600; a = a / 3600;
h = (int)a; h = (int)a;
@ -1125,7 +1126,7 @@ static inline int getDigits(const char *from, char *to, int limit)
double a, b, d = [self dayOfCommonEra]; double a, b, d = [self dayOfCommonEra];
d -= GREGORIAN_REFERENCE; d -= GREGORIAN_REFERENCE;
d *= 86400; d *= 86400;
a = abs(d - (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT])); a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self]));
b = a / 3600; b = a / 3600;
h = (int)b; h = (int)b;
h = h * 3600; 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]; double a, b, c, d = [self dayOfCommonEra];
d -= GREGORIAN_REFERENCE; d -= GREGORIAN_REFERENCE;
d *= 86400; d *= 86400;
a = abs(d - (_seconds_since_ref+[_time_zone timeZoneSecondsFromGMT])); a = abs(d - (_seconds_since_ref+[_time_zone secondsFromGMTForDate: self]));
b = a / 3600; b = a / 3600;
h = (int)b; h = (int)b;
h = h * 3600; h = h * 3600;
@ -1328,7 +1329,8 @@ static inline int getDigits(const char *from, char *to, int limit)
case 'F': // milliseconds case 'F': // milliseconds
s = ([self dayOfCommonEra] - GREGORIAN_REFERENCE) * 86400.0; 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 = abs(s);
s -= floor(s); s -= floor(s);
++i; ++i;
@ -1429,13 +1431,13 @@ static inline int getDigits(const char *from, char *to, int limit)
case 'Z': case 'Z':
++i; ++i;
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s",
[[_time_zone timeZoneAbbreviation] cString])); [[_time_zone abbreviationForDate: self] cString]));
j += k; j += k;
break; break;
case 'z': case 'z':
++i; ++i;
z = [_time_zone timeZoneSecondsFromGMT]; z = [_time_zone secondsFromGMTForDate: self];
if (z < 0) { if (z < 0) {
z = -z; z = -z;
z /= 60; z /= 60;
@ -1511,14 +1513,18 @@ static inline int getDigits(const char *from, char *to, int limit)
// Getting and Setting Time Zones // Getting and Setting Time Zones
- (void) setTimeZone: (NSTimeZone *)aTimeZone - (void) setTimeZone: (NSTimeZone *)aTimeZone
{ {
NSTimeZoneDetail *detail = [aTimeZone timeZoneDetailForDate: self]; ASSIGN(_time_zone, aTimeZone);
}
ASSIGN(_time_zone, detail); - (NSTimeZone*) timeZone
{
return _time_zone;
} }
- (NSTimeZoneDetail*) timeZoneDetail - (NSTimeZoneDetail*) timeZoneDetail
{ {
return _time_zone; NSTimeZoneDetail *detail = [_time_zone timeZoneDetailForDate: self];
return detail;
} }
@end @end

View file

@ -107,7 +107,7 @@ struct ttinfo
/* The local time zone. */ /* The local time zone. */
static id localTimeZone; static id localTimeZone;
/* Dictionary for time zones. Each time zone must have a unique /* Dictionary for time zones. Each time zone must have a unique
name. */ name. */
@ -119,6 +119,7 @@ static NSDictionary *fake_abbrev_dict;
/* Lock for creating time zones. */ /* Lock for creating time zones. */
static NSRecursiveLock *zone_mutex; static NSRecursiveLock *zone_mutex;
static Class NSTimeZoneClass;
/* Decode the four bytes at PTR as a signed integer in network byte order. /* 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. */ Based on code included in the GNU C Library 2.0.3. */
@ -308,20 +309,6 @@ decode (const void *ptr)
@implementation NSConcreteTimeZone @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 - (void) dealloc
{ {
RELEASE(name); RELEASE(name);
@ -338,21 +325,30 @@ decode (const void *ptr)
[aCoder encodeObject: name]; [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; return self;
} }
- (NSString*) name
{
return name;
}
- (NSArray*) timeZoneDetailArray
{
return details;
}
- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date - (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date
{ {
unsigned index; unsigned index;
@ -388,16 +384,6 @@ decode (const void *ptr)
return [details objectAtIndex: index]; return [details objectAtIndex: index];
} }
- (NSArray*) timeZoneDetailArray
{
return details;
}
- (NSString*) timeZoneName
{
return name;
}
@end @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 - (void) dealloc
{ {
[zone_mutex lock]; [zone_mutex lock];
@ -455,49 +415,53 @@ static NSMapTable *absolutes = 0;
[aCoder encodeObject: name]; [aCoder encodeObject: name];
} }
- (id) initWithCoder: (NSCoder*)aDecoder - (id) initWithOffset: (int)anOffset
{ {
[aDecoder decodeValueOfObjCType: @encode(id) at: &name]; NSConcreteAbsoluteTimeZone *z;
offset = [name intValue];
detail = [[NSConcreteTimeZoneDetail alloc] [zone_mutex lock];
initWithTimeZone: self withAbbrev: name z = (NSConcreteAbsoluteTimeZone*)NSMapGet(absolutes, (void*)(gsaddr)anOffset);
withOffset: offset withDST: NO]; if (z)
return self; {
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 - (NSString*) name
{
return detail;
}
- (NSString*) timeZoneName
{ {
return name; return name;
} }
- (NSArray*) timeZoneDetailArray - (NSArray*) timeZoneDetailArray
{ {
return [NSArray arrayWithObject: detail]; return [NSArray arrayWithObject: detail];
} }
- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date
{
return detail;
}
@end @end
@implementation NSConcreteTimeZoneDetail @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 - (void) dealloc
{ {
RELEASE(timeZone); RELEASE(timeZone);
@ -519,48 +483,123 @@ static NSMapTable *absolutes = 0;
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &is_dst]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &is_dst];
return self; 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 - (BOOL) isDaylightSavingTimeZone
{ {
return is_dst; return is_dst;
} }
- (NSString*) name
{
return [timeZone name];
}
- (NSString*) timeZoneAbbreviation - (NSString*) timeZoneAbbreviation
{ {
return abbrev; return abbrev;
} }
- (NSArray*) timeZoneDetailArray
{
return [timeZone timeZoneDetailArray];
}
- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date
{
return [timeZone timeZoneDetailForDate: date];
}
- (int) timeZoneSecondsFromGMT - (int) timeZoneSecondsFromGMT
{ {
return offset; return offset;
} }
- (int) timeZoneSecondsFromGMTForDate: (NSDate*)aDate
{
return offset;
}
@end @end
@implementation NSTimeZone @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 + (void) initialize
{ {
if (self == [NSTimeZone class]) if (self == [NSTimeZone class])
{ {
id localZoneString = nil; id localZoneString = nil;
NSTimeZoneClass = self;
zone_mutex = [NSRecursiveLock new]; zone_mutex = [NSRecursiveLock new];
zoneDictionary = [[NSMutableDictionary alloc] init]; zoneDictionary = [[NSMutableDictionary alloc] init];
@ -579,7 +618,7 @@ static NSMapTable *absolutes = 0;
/* /*
* Try to get timezone from LOCAL_TIME_FILE. * Try to get timezone from LOCAL_TIME_FILE.
*/ */
NSString *f = [NSTimeZone getLocalTimeFile]; NSString *f = [NSTimeZoneClass getLocalTimeFile];
char zone_name[80]; char zone_name[80];
FILE *fp; FILE *fp;
@ -608,7 +647,7 @@ static NSMapTable *absolutes = 0;
} }
if (localZoneString != nil) if (localZoneString != nil)
{ {
localTimeZone = [NSTimeZone timeZoneWithName: localZoneString]; localTimeZone = [NSTimeZoneClass timeZoneWithName: localZoneString];
} }
else else
{ {
@ -623,7 +662,7 @@ static NSMapTable *absolutes = 0;
if (localTimeZone == nil) if (localTimeZone == nil)
{ {
NSLog(@"Using time zone with absolute offset 0."); NSLog(@"Using time zone with absolute offset 0.");
localTimeZone = [NSTimeZone timeZoneForSecondsFromGMT: 0]; localTimeZone = [NSTimeZoneClass timeZoneForSecondsFromGMT: 0];
} }
IF_NO_GC(RETAIN(localTimeZone)); 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 + (NSTimeZone*) localTimeZone
{ {
return 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 + (NSTimeZone*) timeZoneForSecondsFromGMT: (int)seconds
{ {
/* We simply return the following because an existing time zone with /* We simply return the following because an existing time zone with
@ -702,23 +773,42 @@ static NSMapTable *absolutes = 0;
return zone; return zone;
} }
/* Make sure that only time zone files are accessed. i = [aTimeZoneName length];
FIXME: Make this more robust. */ if (i == 0)
if ([aTimeZoneName length] == 0
|| ([aTimeZoneName cString])[0] == '/'
|| strchr([aTimeZoneName cString], '.') != NULL)
{ {
NSLog(@"Disallowed time zone name `%@'.", aTimeZoneName); NSLog(@"Disallowed null time zone name");
[zone_mutex unlock]; [zone_mutex unlock];
return nil; 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 NS_DURING
{ {
zone = [NSConcreteTimeZone alloc]; zone = [NSConcreteTimeZone alloc];
/* Open file. */ /* Open file. */
fileName = [NSTimeZone getTimeZoneFile: aTimeZoneName]; fileName = [NSTimeZoneClass getTimeZoneFile: aTimeZoneName];
#if defined(__WIN32__) #if defined(__WIN32__)
file = fopen([fileName fileSystemRepresentation], "rb"); file = fopen([fileName fileSystemRepresentation], "rb");
#else #else
@ -799,7 +889,7 @@ static NSMapTable *absolutes = 0;
[zone initWithName: aTimeZoneName [zone initWithName: aTimeZoneName
withTransitions: transArray withTransitions: transArray
withDetails: detailsArray]; withDetails: detailsArray];
[zoneDictionary setObject: zone forKey: [zone timeZoneName]]; [zoneDictionary setObject: zone forKey: [zone name]];
} }
NS_HANDLER NS_HANDLER
{ {
@ -820,107 +910,111 @@ static NSMapTable *absolutes = 0;
return zone; 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) NSTimeZoneDetail *detail;
[NSException raise: NSInvalidArgumentException
format: @"Nil time zone specified."]; detail = [self timeZoneDetailForDate: when];
ASSIGN(localTimeZone, aTimeZone); 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 return RETAIN(self);
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; - (NSString*) description
FILE *file; // For the file containing the abbreviation dictionary {
char abbrev[80], name[80]; return [self name];
NSString *fileName; }
if (abbreviationDictionary != nil) - (void) encodeWithCoder: (NSCoder*)aCoder
return abbreviationDictionary; {
if (self == localTimeZone)
/* 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; [aCoder encodeObject: @"NSLocalTimeZone"];
}
the_name = [NSString stringWithCString: name]; else
the_abbrev = [NSString stringWithCString: abbrev]; {
a = [abbreviationDictionary objectForKey: the_abbrev]; [aCoder encodeObject: [self name]];
if (a == nil)
{
a = [[NSMutableArray alloc] init];
[abbreviationDictionary setObject: a forKey: the_abbrev];
}
[a addObject: the_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]; 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) secondsFromGMTForDate: (NSDate*)when
int index, i; {
char name[80]; NSTimeZoneDetail *detail;
FILE *file;
id temp_array[24];
NSString *fileName;
if (regionsArray != nil) detail = [self timeZoneDetailForDate: when];
return regionsArray; return [detail timeZoneSecondsFromGMT];
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;
} }
- (NSArray*) timeZoneDetailArray - (NSArray*) timeZoneDetailArray
@ -928,6 +1022,16 @@ static NSMapTable *absolutes = 0;
return [self subclassResponsibility: _cmd]; return [self subclassResponsibility: _cmd];
} }
- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date
{
return [self subclassResponsibility: _cmd];
}
- (NSString*) timeZoneName
{
return [self name];
}
@end @end
@ -937,7 +1041,7 @@ static NSMapTable *absolutes = 0;
{ {
return [NSString return [NSString
stringWithFormat: @"%@(%@, %s%d)", stringWithFormat: @"%@(%@, %s%d)",
[self timeZoneName], [self name],
[self timeZoneAbbreviation], [self timeZoneAbbreviation],
([self isDaylightSavingTimeZone]? "IS_DST, ": ""), ([self isDaylightSavingTimeZone]? "IS_DST, ": ""),
[self timeZoneSecondsFromGMT]]; [self timeZoneSecondsFromGMT]];