--- ../core/base/Source/NSTimeZone.m.cvs 2003-11-19 17:39:06.000000000 +0800 +++ ../core/base/Source/NSTimeZone.m 2003-12-14 12:30:54.000000000 +0800 @@ -39,13 +39,45 @@ eventually have to change the implementation to prevent the year 2038 problem.) - The local time zone can be specified with the user defaults - database, the GNUSTEP_TZ environment variable, the file LOCAL_TIME_FILE, - the TZ environment variable, or the fallback time zone (which is UTC), + The local time zone can be specified with: + 1) the user defaults database + 2) the GNUSTEP_TZ environment variable + 3) the file LOCAL_TIME_FILE in _time_zone_path() + 4) the TZ environment variable + 5) or the fallback time zone (which is UTC) with the ones listed first having precedence. Any time zone must be a file name in ZONES_DIR. + Files & File System Heirarchy info: + =================================== + + Default place for the NSTimeZone directory is _time_zone_path(): + {$(GNUSTEP_SYSTEM_ROOT)Libary/Libraries/Resources/TIME_ZONE_DIR} + + LOCAL_TIME_FILE is a text file with the name of the time zone file. + + ZONES_DIR is a sub-directory under TIME_ZONE_DIR + + (dir) ../System/Library/Libraries/Resources/.. + (dir) NSTimeZone + (file) localtime {text; time zone eg Australia/Perth} + (dir) zones + + Since NSTimeZone gets the name from LOCAL_TIME_FILE it's sufficient + to symlink this to the time zone name used elsewhere. For example: + Debian uses "/etc/timezone" + + A number of POSIX systems have the zone files already installed. + For these systems it is sufficient to symlink ZONES_DIR to the + platform specific location. + For (g)libc6 this is /usr/share/zoneinfo + For Solaris this is /usr/share/lib/zoneinfo + + Note that full zone info is required, especially the various "GMT" + files which are created especially for OPENSTEP compatibility. + Zone info comes from the Olson time database. + FIXME?: use leap seconds? */ #include "config.h" @@ -87,7 +119,8 @@ /* Key for local time zone in user defaults. */ #define LOCALDBKEY @"Local Time Zone" -/* Directory that contains the time zone data. */ +/* Directory that contains the time zone data. + Expected in Resources directory for library bundle. */ #define TIME_ZONE_DIR @"NSTimeZones" /* Location of time zone abbreviation dictionary. It is a text file @@ -113,13 +146,13 @@ @class GSTimeZoneDetail; @class GSAbsTimeZoneDetail; -@class GSPlaceholderTimeZone; +@class GSPlaceholderTimeZone; /* * Information for abstract placeholder class. */ -static GSPlaceholderTimeZone *defaultPlaceholderTimeZone; -static NSMapTable *placeholderMap; +static GSPlaceholderTimeZone *defaultPlaceholderTimeZone; +static NSMapTable *placeholderMap; /* * Temporary structure for holding time zone details. @@ -127,8 +160,8 @@ */ struct ttinfo { - char offset[4]; // Seconds east of UTC - unsigned char isdst; // Daylight savings time? + char offset[4]; // Seconds east of UTC + unsigned char isdst; // Daylight savings time? unsigned char abbr_idx; // Index into time zone abbreviations string }; @@ -136,30 +169,30 @@ * And this is the structure used in the time zone instances. */ typedef struct { - gss32 offset; - BOOL isdst; - unsigned char abbr_idx; - char pad[2]; - NSString *abbreviation; + gss32 offset; + BOOL isdst; + unsigned char abbr_idx; + char pad[2]; + NSString *abbreviation; } TypeInfo; -@interface GSTimeZone : NSTimeZone +@interface GSTimeZone : NSTimeZone { @public - NSString *timeZoneName; - NSData *timeZoneData; - unsigned int n_trans; - unsigned int n_types; - gss32 *trans; - TypeInfo *types; - unsigned char *idxs; + NSString *timeZoneName; + NSData *timeZoneData; + unsigned int n_trans; + unsigned int n_types; + gss32 *trans; + TypeInfo *types; + unsigned char *idxs; } @end -static NSTimeZone *defaultTimeZone = nil; -static NSTimeZone *localTimeZone = nil; -static NSTimeZone *systemTimeZone = nil; +static NSTimeZone *defaultTimeZone = nil; +static NSTimeZone *localTimeZone = nil; +static NSTimeZone *systemTimeZone = nil; /* Dictionary for time zones. Each time zone must have a unique name. */ @@ -171,8 +204,8 @@ /* Lock for creating time zones. */ static NSRecursiveLock *zone_mutex = nil; -static Class NSTimeZoneClass; -static Class GSPlaceholderTimeZoneClass; +static Class NSTimeZoneClass; +static Class GSPlaceholderTimeZoneClass; /* 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. */ @@ -205,8 +238,8 @@ NSBundle *gbundle; gbundle = [NSBundle bundleForLibrary: @"gnustep-base"]; return [gbundle pathForResource: subpath - ofType: @"" - inDirectory: TIME_ZONE_DIR]; + ofType: @"" + inDirectory: TIME_ZONE_DIR]; } /* Object enumerator for NSInternalAbbrevDict. */ @@ -230,9 +263,9 @@ @interface GSAbsTimeZone : NSTimeZone { @public - NSString *name; - id detail; - int offset; // Offset from UTC in seconds. + NSString *name; + id detail; + int offset; // Offset from UTC in seconds. } - (id) initWithOffset: (int)anOffset; @@ -243,21 +276,21 @@ @interface GSTimeZoneDetail : NSTimeZoneDetail { - NSTimeZone *timeZone; // Time zone which created this object. - NSString *abbrev; // Abbreviation for time zone detail. - int offset; // Offset from UTC in seconds. - BOOL is_dst; // Is it daylight savings time? + NSTimeZone *timeZone; // Time zone which created this object. + NSString *abbrev; // Abbreviation for time zone detail. + int offset; // Offset from UTC in seconds. + BOOL is_dst; // Is it daylight savings time? } - (id) initWithTimeZone: (NSTimeZone*)aZone - withAbbrev: (NSString*)anAbbrev - withOffset: (int)anOffset - withDST: (BOOL)isDST; + withAbbrev: (NSString*)anAbbrev + withOffset: (int)anOffset + withDST: (BOOL)isDST; @end @interface GSAbsTimeZoneDetail : NSTimeZoneDetail { - GSAbsTimeZone *zone; // Time zone which created this object. + GSAbsTimeZone *zone; // Time zone which created this object. } - (id) initWithTimeZone: (GSAbsTimeZone*)aZone; @@ -324,7 +357,7 @@ - (NSEnumerator*) objectEnumerator { return AUTORELEASE([[NSInternalAbbrevDictObjectEnumerator alloc] - initWithDict: [NSTimeZone abbreviationMap]]); + initWithDict: [NSTimeZone abbreviationMap]]); } - (id) objectForKey: (NSString*)key @@ -340,18 +373,18 @@ - (id) autorelease { NSWarnLog(@"-autorelease sent to uninitialised time zone"); - return self; // placeholders never get released. + return self; // placeholders never get released. } - (void) dealloc { - return; // placeholders never get deallocated. + return; // placeholders never get deallocated. } - (id) initWithName: (NSString*)name data: (NSData*)data { - NSTimeZone *zone; - unsigned length = [name length]; + NSTimeZone *zone; + unsigned length = [name length]; if (length == 0) { @@ -386,68 +419,68 @@ if (zone == nil) { - unichar c; - unsigned i; + unichar c; + unsigned i; if (length == 8 && [name hasPrefix: @"GMT"] == YES - && ((c = [name characterAtIndex: 3]) == '+' || c == '-')) - { - c = [name characterAtIndex: 4]; - if (c >= '0' && c <= '9') - { - i = c - '0'; - c = [name characterAtIndex: 5]; - if (c >= '0' && c <= '9') - { - i = i * 10 + (c - '0'); - c = [name characterAtIndex: 6]; - if (c >= '0' && c <= '9') - { - i = i * 6 + (c - '0'); - c = [name characterAtIndex: 7]; - if (c >= '0' && c <= '9') - { - i = i * 10 + (c - '0'); - zone = [[GSAbsTimeZone alloc] initWithOffset: i*60]; - } - } - } - } - } + && ((c = [name characterAtIndex: 3]) == '+' || c == '-')) + { + c = [name characterAtIndex: 4]; + if (c >= '0' && c <= '9') + { + i = c - '0'; + c = [name characterAtIndex: 5]; + if (c >= '0' && c <= '9') + { + i = i * 10 + (c - '0'); + c = [name characterAtIndex: 6]; + if (c >= '0' && c <= '9') + { + i = i * 6 + (c - '0'); + c = [name characterAtIndex: 7]; + if (c >= '0' && c <= '9') + { + i = i * 10 + (c - '0'); + zone = [[GSAbsTimeZone alloc] initWithOffset: i*60]; + } + } + } + } + } if (zone == nil && length > 19 - && [name hasPrefix: @"NSAbsoluteTimeZone:"] == YES) - { - i = [[name substringFromIndex: 19] intValue]; + && [name hasPrefix: @"NSAbsoluteTimeZone:"] == YES) + { + i = [[name substringFromIndex: 19] intValue]; - zone = [[GSAbsTimeZone alloc] initWithOffset: i]; - } + zone = [[GSAbsTimeZone alloc] initWithOffset: i]; + } if (zone == nil) - { - if (data == nil) - { - NSString *fileName; - const char *str = [name UTF8String]; - - /* 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 `%@'.", name); - return nil; - } - - fileName = [NSTimeZoneClass getTimeZoneFile: name]; - if (fileName == nil) - { - NSLog(@"Unknown time zone name `%@'.", name); - return nil; - } - data = [NSData dataWithContentsOfFile: fileName]; - } - zone = [[GSTimeZone alloc] initWithName: name data: data]; - } + { + if (data == nil) + { + NSString *fileName; + const char *str = [name UTF8String]; + + /* 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 `%@'.", name); + return nil; + } + + fileName = [NSTimeZoneClass getTimeZoneFile: name]; + if (fileName == nil) + { + NSLog(@"Unknown time zone name `%@'.", name); + return nil; + } + data = [NSData dataWithContentsOfFile: fileName]; + } + zone = [[GSTimeZone alloc] initWithName: name data: data]; + } } RELEASE(self); return zone; @@ -455,18 +488,18 @@ - (void) release { - return; // placeholders never get released. + return; // placeholders never get released. } - (id) retain { - return self; // placeholders never get retained. + return self; // placeholders never get retained. } @end -@implementation NSLocalTimeZone +@implementation NSLocalTimeZone - (NSString*) abbreviation { @@ -551,15 +584,15 @@ @implementation GSAbsTimeZone -static int uninitialisedOffset = 100000; -static NSMapTable *absolutes = 0; +static int uninitialisedOffset = 100000; +static NSMapTable *absolutes = 0; + (void) initialize { if (self == [GSAbsTimeZone class]) { absolutes = NSCreateMapTable(NSIntMapKeyCallBacks, - NSNonOwnedPointerMapValueCallBacks, 0); + NSNonOwnedPointerMapValueCallBacks, 0); } } @@ -573,10 +606,10 @@ if (offset != uninitialisedOffset) { if (zone_mutex != nil) - [zone_mutex lock]; + [zone_mutex lock]; NSMapRemove(absolutes, (void*)(gsaddr)offset); if (zone_mutex != nil) - [zone_mutex unlock]; + [zone_mutex unlock]; } RELEASE(name); RELEASE(detail); @@ -590,9 +623,9 @@ - (id) initWithOffset: (int)anOffset { - GSAbsTimeZone *z; - int extra; - int sign = anOffset >= 0 ? 1 : -1; + GSAbsTimeZone *z; + int extra; + int sign = anOffset >= 0 ? 1 : -1; /* * Set the uninitialised offset so that dealloc before full @@ -634,25 +667,25 @@ else { if (anOffset % 60 == 0) - { - char s = (anOffset >= 0) ? '+' : '-'; - int i = (anOffset >= 0) ? anOffset / 60 : -anOffset / 60; - int h = i / 60; - int m = i % 60; - char buf[9]; - - sprintf(buf, "GMT%c%02d%02d", s, h, m); - name = [[NSString alloc] initWithCString: buf]; - } + { + char s = (anOffset >= 0) ? '+' : '-'; + int i = (anOffset >= 0) ? anOffset / 60 : -anOffset / 60; + int h = i / 60; + int m = i % 60; + char buf[9]; + + sprintf(buf, "GMT%c%02d%02d", s, h, m); + name = [[NSString alloc] initWithCString: buf]; + } else - { - /* - * Should never happen now we round to the minute - * for MacOS-X compatibnility. - */ - name = [[NSString alloc] initWithFormat: @"NSAbsoluteTimeZone:%d", - anOffset]; - } + { + /* + * Should never happen now we round to the minute + * for MacOS-X compatibnility. + */ + name = [[NSString alloc] initWithFormat: @"NSAbsoluteTimeZone:%d", + anOffset]; + } detail = [[GSAbsTimeZoneDetail alloc] initWithTimeZone: self]; offset = anOffset; z = self; @@ -715,12 +748,12 @@ } - (id) initWithTimeZone: (NSTimeZone*)aZone - withAbbrev: (NSString*)anAbbrev - withOffset: (int)anOffset - withDST: (BOOL)isDST + withAbbrev: (NSString*)anAbbrev + withOffset: (int)anOffset + withDST: (BOOL)isDST { timeZone = RETAIN(aZone); - abbrev = anAbbrev; // NB. Depend on this being retained in aZone + abbrev = anAbbrev; // NB. Depend on this being retained in aZone offset = anOffset; is_dst = isDST; return self; @@ -856,14 +889,23 @@ * wildly between OSes (this could be a big problem when * archiving is used between different systems). *

+ * On platforms where the zone info files are already installed + * elsewhere it is sufficient to use a symlink provided the GMT+/- + * zones are added. */ @implementation NSTimeZone +/* + * DEPRICATED. + */ + (NSDictionary*) abbreviationDictionary { return fake_abbrev_dict; } +/* + * Returns an abbreviation to time zone map which is quite large. + */ + (NSDictionary*) abbreviationMap { /* Instead of creating the abbreviation dictionary when the class is @@ -882,7 +924,7 @@ /* Read dictionary from file. */ abbreviationDictionary = [[NSMutableDictionary alloc] init]; fileName = [NSTimeZone getAbbreviationFile]; -#if defined(__WIN32__) +#if defined(__WIN32__) file = fopen([fileName fileSystemRepresentation], "rb"); #else file = fopen([fileName fileSystemRepresentation], "r"); @@ -899,10 +941,10 @@ the_abbrev = [NSString stringWithCString: abbrev]; a = [abbreviationDictionary objectForKey: the_abbrev]; if (a == nil) - { - a = [[NSMutableArray alloc] init]; - [abbreviationDictionary setObject: a forKey: the_abbrev]; - } + { + a = [[NSMutableArray alloc] init]; + [abbreviationDictionary setObject: a forKey: the_abbrev]; + } [a addObject: the_name]; } fclose(file); @@ -920,42 +962,42 @@ * is called. */ if (z == NSDefaultMallocZone() || z == 0) - { - /* - * As a special case, we can return a placeholder for a time zone - * in the default malloc zone extremely efficiently. - */ - return defaultPlaceholderTimeZone; - } + { + /* + * As a special case, we can return a placeholder for a time zone + * in the default malloc zone extremely efficiently. + */ + return defaultPlaceholderTimeZone; + } else - { - id obj; + { + id obj; - /* - * For anything other than the default zone, we need to - * locate the correct placeholder in the (lock protected) - * table of placeholders. - */ - if (zone_mutex != nil) - { - [zone_mutex lock]; - } - obj = (id)NSMapGet(placeholderMap, (void*)z); - if (obj == nil) - { - /* - * There is no placeholder object for this zone, so we - * create a new one and use that. - */ - obj = (id)NSAllocateObject(GSPlaceholderTimeZoneClass, 0, z); - NSMapInsert(placeholderMap, (void*)z, (void*)obj); - } - if (zone_mutex != nil) - { - [zone_mutex unlock]; - } - return obj; - } + /* + * For anything other than the default zone, we need to + * locate the correct placeholder in the (lock protected) + * table of placeholders. + */ + if (zone_mutex != nil) + { + [zone_mutex lock]; + } + obj = (id)NSMapGet(placeholderMap, (void*)z); + if (obj == nil) + { + /* + * There is no placeholder object for this zone, so we + * create a new one and use that. + */ + obj = (id)NSAllocateObject(GSPlaceholderTimeZoneClass, 0, z); + NSMapInsert(placeholderMap, (void*)z, (void*)obj); + } + if (zone_mutex != nil) + { + [zone_mutex unlock]; + } + return obj; + } } else { @@ -968,7 +1010,7 @@ */ + (NSTimeZone*) defaultTimeZone { - NSTimeZone *zone; + NSTimeZone *zone; if (zone_mutex != nil) { @@ -981,13 +1023,13 @@ else { if (zone_mutex != nil) - { - zone = AUTORELEASE(RETAIN(defaultTimeZone)); - } + { + zone = AUTORELEASE(RETAIN(defaultTimeZone)); + } else - { - zone = defaultTimeZone; - } + { + zone = defaultTimeZone; + } } if (zone_mutex != nil) { @@ -1008,25 +1050,25 @@ * Set up infrastructure for placeholder timezones. */ defaultPlaceholderTimeZone = (GSPlaceholderTimeZone*) - NSAllocateObject(GSPlaceholderTimeZoneClass, 0, NSDefaultMallocZone()); - placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, - NSNonRetainedObjectMapValueCallBacks, 0); + NSAllocateObject(GSPlaceholderTimeZoneClass, 0, NSDefaultMallocZone()); + placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, + NSNonRetainedObjectMapValueCallBacks, 0); localTimeZone = [[NSLocalTimeZone alloc] init]; fake_abbrev_dict = [[NSInternalAbbrevDict alloc] init]; if ([NSThread isMultiThreaded]) - { - [self _becomeThreaded: nil]; - } + { + [self _becomeThreaded: nil]; + } else - { - [[NSNotificationCenter defaultCenter] - addObserver: self - selector: @selector(_becomeThreaded:) - name: NSWillBecomeMultiThreadedNotification - object: nil]; - } + { + [[NSNotificationCenter defaultCenter] + addObserver: self + selector: @selector(_becomeThreaded:) + name: NSWillBecomeMultiThreadedNotification + object: nil]; + } } } @@ -1067,18 +1109,18 @@ * cause recursion ... */ if (aTimeZone == localTimeZone) - { - aTimeZone = [self systemTimeZone]; - } + { + aTimeZone = [self systemTimeZone]; + } if (zone_mutex != nil) - { - [zone_mutex lock]; - } + { + [zone_mutex lock]; + } ASSIGN(defaultTimeZone, aTimeZone); if (zone_mutex != nil) - { - [zone_mutex unlock]; - } + { + [zone_mutex unlock]; + } } } @@ -1087,7 +1129,7 @@ */ + (NSTimeZone*) systemTimeZone { - NSTimeZone *zone = nil; + NSTimeZone *zone = nil; if (zone_mutex != nil) { @@ -1095,63 +1137,66 @@ } if (systemTimeZone == nil) { - NSString *localZoneString = nil; + NSString *localZoneString = nil; /* * setup default value in case something goes wrong. */ systemTimeZone = RETAIN([NSTimeZoneClass timeZoneForSecondsFromGMT: 0]); + /* + * Try to get timezone from user defaults database + */ localZoneString = [[NSUserDefaults standardUserDefaults] - stringForKey: LOCALDBKEY]; + stringForKey: LOCALDBKEY]; + /* + * Try to get timezone from GNUSTEP_TZ environment variable. + */ if (localZoneString == nil) - { - /* - * Try to get timezone from GNUSTEP_TZ environment variable. - */ - localZoneString = [[[NSProcessInfo processInfo] - environment] objectForKey: @"GNUSTEP_TZ"]; - } + { + localZoneString = [[[NSProcessInfo processInfo] + environment] objectForKey: @"GNUSTEP_TZ"]; + } + /* + * Try to get timezone from LOCAL_TIME_FILE + */ if (localZoneString == nil) - { - /* - * Try to get timezone from LOCAL_TIME_FILE. - */ - NSString *f = _time_zone_path(LOCAL_TIME_FILE); - if (f != nil) - { - localZoneString = [NSString stringWithContentsOfFile: f]; - localZoneString = [localZoneString stringByTrimmingSpaces]; - } - } + { + NSString *f = _time_zone_path(LOCAL_TIME_FILE); + if (f != nil) + { + localZoneString = [NSString stringWithContentsOfFile: f]; + localZoneString = [localZoneString stringByTrimmingSpaces]; + } + } #if HAVE_TZSET + /* + * Try to get timezone from tzset and tzname + */ if (localZoneString == nil) - { - /* - * Try to get timezone from tzset and tzname - */ - tzset(); - if (tzname[0] != NULL && *tzname[0] != '\0') - localZoneString = [NSString stringWithCString: tzname[0]]; - } + { + tzset(); + if (tzname[0] != NULL && *tzname[0] != '\0') + localZoneString = [NSString stringWithCString: tzname[0]]; + } #else + /* + * Try to get timezone from standard unix environment variable. + */ if (localZoneString == nil) - { - /* - * Try to get timezone from standard unix environment variable. - */ - localZoneString = [[[NSProcessInfo processInfo] - environment] objectForKey: @"TZ"]; - } + { + localZoneString = [[[NSProcessInfo processInfo] + environment] objectForKey: @"TZ"]; + } #endif if (localZoneString != nil) - { - zone = [defaultPlaceholderTimeZone initWithName: localZoneString]; - } + { + zone = [defaultPlaceholderTimeZone initWithName: localZoneString]; + } else - { - NSLog(@"No local time zone specified."); - } + { + NSLog(@"No local time zone specified."); + } /* * If local time zone fails to allocate, then allocate something @@ -1177,10 +1222,14 @@ return zone; } +/** + * Returns an array of all the known regions.
+ * There are 24 elements, of course, one for each time zone. + * Each element contains an array of NSStrings which are + * the region names. + */ + (NSArray*) timeZoneArray { - /* We create the array only when we need it to reduce overhead. */ - static NSArray *regionsArray = nil; int index, i; char name[80]; @@ -1188,6 +1237,7 @@ id temp_array[24]; NSString *fileName; + /* We create the array only when we need it to reduce overhead. */ if (regionsArray != nil) return regionsArray; @@ -1195,7 +1245,7 @@ temp_array[i] = [NSMutableArray array]; fileName = [NSTimeZoneClass getRegionsFile]; -#if defined(__WIN32__) +#if defined(__WIN32__) file = fopen([fileName fileSystemRepresentation], "rb"); #else file = fopen([fileName fileSystemRepresentation], "r"); @@ -1221,21 +1271,23 @@ */ + (NSTimeZone*) timeZoneForSecondsFromGMT: (int)seconds { - NSTimeZone *zone; + NSTimeZone *zone; zone = [[GSAbsTimeZone alloc] initWithOffset: seconds]; return AUTORELEASE(zone); } /** - * Returns a timezone for the specified abbrevition, + * Returns a timezone for the specified abbrevition. The same abbreviations + * are used in different regions so this isn't particularly useful.
+ * Calls NSTimeZone-abbreviation dictionary an so uses a lot of memory. */ + (NSTimeZone*) timeZoneWithAbbreviation: (NSString*)abbreviation { - NSTimeZone *zone; + NSTimeZone *zone; zone = [self timeZoneWithName: [[self abbreviationDictionary] - objectForKey: abbreviation] data: nil]; + objectForKey: abbreviation] data: nil]; return zone; } @@ -1244,20 +1296,21 @@ */ + (NSTimeZone*) timeZoneWithName: (NSString*)aTimeZoneName { - NSTimeZone *zone; + NSTimeZone *zone; zone = [defaultPlaceholderTimeZone initWithName: aTimeZoneName data: nil]; return AUTORELEASE(zone); } /** - * Returns a timezone for the specified name, created from the supplied data. + * Returns a timezone for aTimeZoneName, created from the supplied + * time zone data. Data must be in TZ format as per the Olson database. */ -+ (NSTimeZone*) timeZoneWithName: (NSString*)name data: (NSData*)data ++ (NSTimeZone*) timeZoneWithName: (NSString*)aTimeZoneName data: (NSData*)data { - NSTimeZone *zone; + NSTimeZone *zone; - zone = [defaultPlaceholderTimeZone initWithName: name data: nil]; + zone = [defaultPlaceholderTimeZone initWithName: aTimeZoneName data: data]; return AUTORELEASE(zone); } @@ -1276,8 +1329,8 @@ */ - (NSString*) abbreviationForDate: (NSDate*)aDate { - NSTimeZoneDetail *detail; - NSString *abbr; + NSTimeZoneDetail *detail; + NSString *abbr; detail = [self timeZoneDetailForDate: aDate]; abbr = [detail timeZoneAbbreviation]; @@ -1285,6 +1338,9 @@ return abbr; } +/** + * Returns the Class for this object + */ - (Class) classForCoder { return NSTimeZoneClass; @@ -1303,6 +1359,9 @@ return nil; } +/** + * Returns the name of this object. + */ - (NSString*) description { return [self name]; @@ -1320,7 +1379,7 @@ - (id) initWithCoder: (NSCoder*)aDecoder { - NSString *name; + NSString *name; name = [aDecoder decodeObject]; self = [self initWithName: name data: nil]; @@ -1363,8 +1422,8 @@ */ - (BOOL) isDaylightSavingTimeForDate: (NSDate*)aDate { - NSTimeZoneDetail *detail; - BOOL isDST; + NSTimeZoneDetail *detail; + BOOL isDST; detail = [self timeZoneDetailForDate: aDate]; isDST = [detail isDaylightSavingTimeZone]; @@ -1381,6 +1440,9 @@ return [self isEqualToTimeZone: other]; } +/* + * Returns TRUE if the time zones are equal. + */ - (BOOL) isEqualToTimeZone: (NSTimeZone*)aTimeZone { if (aTimeZone == self) @@ -1425,8 +1487,8 @@ */ - (int) secondsFromGMTForDate: (NSDate*)aDate { - NSTimeZoneDetail *detail; - int offset; + NSTimeZoneDetail *detail; + int offset; detail = [self timeZoneDetailForDate: aDate]; offset = [detail timeZoneSecondsFromGMT]; @@ -1434,16 +1496,25 @@ return offset; } +/* + * DEPRICATED: see NSTimeZoneDetail + */ - (NSArray*) timeZoneDetailArray { return [self subclassResponsibility: _cmd]; } +/* + * DEPRICATED: see NSTimeZoneDetail + */ - (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date { return [self subclassResponsibility: _cmd]; } +/* + * Returns the name of this timezone. + */ - (NSString*) timeZoneName { return [self name]; @@ -1461,9 +1532,9 @@ - (NSString*) description { return [NSString stringWithFormat: @"%@(%@, %s%d)", [self name], - [self timeZoneAbbreviation], - ([self isDaylightSavingTimeZone]? "IS_DST, ": ""), - [self timeZoneSecondsFromGMT]]; + [self timeZoneAbbreviation], + ([self isDaylightSavingTimeZone]? "IS_DST, ": ""), + [self timeZoneSecondsFromGMT]]; } - (BOOL) isDaylightSavingTimeZone @@ -1489,7 +1560,7 @@ @implementation NSTimeZone (Private) /* - * When the system becomes multithreaded, we set a flag to say so + * When the system becomes multithreaded, we set a flag to say so */ + (void) _becomeThreaded: (NSNotification*)notification { @@ -1499,8 +1570,8 @@ } [[NSNotificationCenter defaultCenter] removeObserver: self - name: NSWillBecomeMultiThreadedNotification - object: nil]; + name: NSWillBecomeMultiThreadedNotification + object: nil]; } + (NSString*) getAbbreviationFile @@ -1515,7 +1586,7 @@ + (NSString*) getTimeZoneFile: (NSString *)name { - NSString *dir; + NSString *dir; dir= _time_zone_path (ZONES_DIR); return [dir stringByAppendingPathComponent: name]; @@ -1525,7 +1596,7 @@ -@implementation GSTimeZone +@implementation GSTimeZone /** * Perform a binary search of a transitions table to locate the index @@ -1536,15 +1607,15 @@ static TypeInfo* chop(NSTimeInterval since, GSTimeZone *zone) { - gss32 when = (gss32)since; - gss32 *trans = zone->trans; - unsigned hi = zone->n_trans; - unsigned lo = 0; - unsigned int i; + gss32 when = (gss32)since; + gss32 *trans = zone->trans; + unsigned hi = zone->n_trans; + unsigned lo = 0; + unsigned int i; if (hi == 0 || trans[0] > when) { - unsigned n_types = zone->n_types; + unsigned n_types = zone->n_types; /* * If the first transition is greater than our date, @@ -1552,40 +1623,40 @@ * or just use the first transition. */ for (i = 0; i < n_types; i++) - { - if (zone->types[i].isdst == 0) - { - return &zone->types[i]; - } - } + { + if (zone->types[i].isdst == 0) + { + return &zone->types[i]; + } + } return &zone->types[0]; } else { for (i = hi/2; hi != lo; i = (hi + lo)/2) - { - if (when < trans[i]) - { - hi = i; - } - else if (when > trans[i]) - { - lo = ++i; - } - else - { - break; - } - } + { + if (when < trans[i]) + { + hi = i; + } + else if (when > trans[i]) + { + lo = ++i; + } + else + { + break; + } + } /* * If we went off the top of the table or the closest transition * was later than our date, we step back to find the last * transition before our date. */ if (i > 0 && (i == zone->n_trans || trans[i] > when)) - { - i--; - } + { + i--; + } return &zone->types[zone->idxs[i]]; } } @@ -1593,19 +1664,19 @@ static NSTimeZoneDetail* newDetailInZoneForType(GSTimeZone *zone, TypeInfo *type) { - GSTimeZoneDetail *detail; + GSTimeZoneDetail *detail; detail = [GSTimeZoneDetail alloc]; detail = [detail initWithTimeZone: zone - withAbbrev: type->abbreviation - withOffset: type->offset - withDST: type->isdst]; + withAbbrev: type->abbreviation + withOffset: type->offset + withDST: type->isdst]; return detail; } - (NSString*) abbreviationForDate: (NSDate*)aDate { - TypeInfo *type = chop([aDate timeIntervalSince1970], self); + TypeInfo *type = chop([aDate timeIntervalSince1970], self); return type->abbreviation; } @@ -1621,12 +1692,12 @@ RELEASE(timeZoneData); if (types != 0) { - unsigned i; + unsigned i; for (i = 0; i < n_types; i++) - { - RELEASE(types[i].abbreviation); - } + { + RELEASE(types[i].abbreviation); + } NSZoneFree(NSDefaultMallocZone(), types); } [super dealloc]; @@ -1634,32 +1705,32 @@ - (id) initWithName: (NSString*)name data: (NSData*)data { - static NSString *fileException = @"GSTimeZoneFileException"; + static NSString *fileException = @"GSTimeZoneFileException"; timeZoneName = [name copy]; timeZoneData = [data copy]; NS_DURING { - const void *bytes = [timeZoneData bytes]; - unsigned length = [timeZoneData length]; - void *buf; - unsigned pos = 0; - unsigned i, charcnt; - unsigned char *abbr; - struct tzhead *header; + const void *bytes = [timeZoneData bytes]; + unsigned length = [timeZoneData length]; + void *buf; + unsigned pos = 0; + unsigned i, charcnt; + unsigned char *abbr; + struct tzhead *header; if (length < sizeof(struct tzhead)) - { - [NSException raise: fileException - format: @"File is too small"]; - } + { + [NSException raise: fileException + format: @"File is too small"]; + } header = (struct tzhead *)(bytes + pos); pos += sizeof(struct tzhead); if (memcmp(header->tzh_magic, TZ_MAGIC, strlen(TZ_MAGIC)) != 0) - { - [NSException raise: fileException - format: @"TZ_MAGIC is incorrect"]; - } + { + [NSException raise: fileException + format: @"TZ_MAGIC is incorrect"]; + } n_trans = GSSwapBigI32ToHost(*(gss32*)header->tzh_timecnt); n_types = GSSwapBigI32ToHost(*(gss32*)header->tzh_typecnt); charcnt = GSSwapBigI32ToHost(*(gss32*)header->tzh_charcnt); @@ -1667,27 +1738,27 @@ i = pos; i += sizeof(gss32)*n_trans; if (i > length) - { - [NSException raise: fileException - format: @"Transitions list is truncated"]; - } + { + [NSException raise: fileException + format: @"Transitions list is truncated"]; + } i += n_trans; if (i > length) - { - [NSException raise: fileException - format: @"Transition indexes are truncated"]; - } + { + [NSException raise: fileException + format: @"Transition indexes are truncated"]; + } i += sizeof(struct ttinfo)*n_types; if (i > length) - { - [NSException raise: fileException - format: @"Types list is truncated"]; - } + { + [NSException raise: fileException + format: @"Types list is truncated"]; + } if (i + charcnt > length) - { - [NSException raise: fileException - format: @"Abbreviations list is truncated"]; - } + { + [NSException raise: fileException + format: @"Abbreviations list is truncated"]; + } /* * Now calculate size we need to store the information @@ -1704,63 +1775,63 @@ /* Read in transitions. */ for (i = 0; i < n_trans; i++) - { - trans[i] = GSSwapBigI32ToHost(*(gss32*)(bytes + pos)); - pos += sizeof(gss32); - } + { + trans[i] = GSSwapBigI32ToHost(*(gss32*)(bytes + pos)); + pos += sizeof(gss32); + } for (i = 0; i < n_trans; i++) - { - idxs[i] = *(unsigned char*)(bytes + pos); - pos++; - } + { + idxs[i] = *(unsigned char*)(bytes + pos); + pos++; + } for (i = 0; i < n_types; i++) - { - struct ttinfo *ptr = (struct ttinfo*)(bytes + pos); + { + struct ttinfo *ptr = (struct ttinfo*)(bytes + pos); - types[i].isdst = (ptr->isdst != 0 ? YES : NO); - types[i].abbr_idx = ptr->abbr_idx; - types[i].offset = decode(ptr->offset); - pos += sizeof(struct ttinfo); - } + types[i].isdst = (ptr->isdst != 0 ? YES : NO); + types[i].abbr_idx = ptr->abbr_idx; + types[i].offset = decode(ptr->offset); + pos += sizeof(struct ttinfo); + } abbr = (char*)(bytes + pos); { - id abbrevs[charcnt]; + id abbrevs[charcnt]; - memset(abbrevs, '\0', sizeof(id)*charcnt); - for (i = 0; i < n_types; i++) - { - int loc = types[i].abbr_idx; - - if (abbrevs[loc] == nil) - { - abbrevs[loc] = [[NSString alloc] initWithCString: abbr + loc]; - } - else - { - RETAIN(abbrevs[loc]); - } - types[i].abbreviation = abbrevs[loc]; - } + memset(abbrevs, '\0', sizeof(id)*charcnt); + for (i = 0; i < n_types; i++) + { + int loc = types[i].abbr_idx; + + if (abbrevs[loc] == nil) + { + abbrevs[loc] = [[NSString alloc] initWithCString: abbr + loc]; + } + else + { + RETAIN(abbrevs[loc]); + } + types[i].abbreviation = abbrevs[loc]; + } } if (zone_mutex != nil) - { - [zone_mutex lock]; - } + { + [zone_mutex lock]; + } [zoneDictionary setObject: self forKey: timeZoneName]; if (zone_mutex != nil) - { - [zone_mutex unlock]; - } + { + [zone_mutex unlock]; + } } NS_HANDLER { DESTROY(self); NSLog(@"Unable to obtain time zone `%@'... %@", name, localException); if ([localException name] != fileException) - { - [localException raise]; - } + { + [localException raise]; + } } NS_ENDHANDLER return self; @@ -1768,7 +1839,7 @@ - (BOOL) isDaylightSavingTimeForDate: (NSDate*)aDate { - TypeInfo *type = chop([aDate timeIntervalSince1970], self); + TypeInfo *type = chop([aDate timeIntervalSince1970], self); return type->isdst; } @@ -1780,16 +1851,16 @@ - (int) secondsFromGMTForDate: (NSDate*)aDate { - TypeInfo *type = chop([aDate timeIntervalSince1970], self); + TypeInfo *type = chop([aDate timeIntervalSince1970], self); return type->offset; } - (NSArray*) timeZoneDetailArray { - NSTimeZoneDetail *details[n_types]; - unsigned i; - NSArray *array; + NSTimeZoneDetail *details[n_types]; + unsigned i; + NSArray *array; for (i = 0; i < n_types; i++) { @@ -1805,8 +1876,8 @@ - (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)aDate { - TypeInfo *type; - NSTimeZoneDetail *detail; + TypeInfo *type; + NSTimeZoneDetail *detail; type = chop([aDate timeIntervalSince1970], self); detail = newDetailInZoneForType(self, type);