This is NSTimeZone.m in view mode; [Download] [Up]
/* NSTimeZone.m Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro> Ovidiu Predescu <ovidiu@bx.logicnet.ro> This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #include <Foundation/common.h> #include <Foundation/NSDate.h> #include <Foundation/NSArray.h> #include <Foundation/NSDictionary.h> #include <Foundation/NSString.h> #include <Foundation/NSUtilities.h> #include <Foundation/NSAutoreleasePool.h> #include <Foundation/NSProcessInfo.h> #include <Foundation/NSUserDefaults.h> #include <Foundation/NSException.h> #include <Foundation/NSCoder.h> #include "NSConcreteTimeZone.h" /* * NSTimeZone cluster abstract class */ static NSString* timeZoneInfoFilesPath = nil; static NSMutableDictionary *abbreviationDictionary = nil; static NSArray* timeZoneArray = nil; static NSMutableDictionary* regionsByOffset = nil; static NSMutableDictionary* timeZonesByName = nil; static NSTimeZone* defaultTimeZone = nil; static NSTimeZone* localTimeZone = nil; @implementation NSTimeZone + (NSTimeZone*)_createTimeZoneWithName:(NSString*)name checkDuplicates:(BOOL)checkDuplicates { NSString* filename; NSTimeZone* concreteTimeZone; if (checkDuplicates) { if ([timeZonesByName objectForKey:name]) return nil; } filename = [[[timeZoneInfoFilesPath stringByAppendingPathComponent:@"TimeZoneInfo"] stringByAppendingPathComponent:name] stringByResolvingSymlinksInPath]; if (!filename || ![filename length]) { NSLog (@"Cannot find the time zone description file '%@' in " @"resource directory '%@'", name, timeZoneInfoFilesPath); return nil; } concreteTimeZone = [[[NSConcreteTimeZoneFile alloc] initFromFile:filename withName:name] autorelease]; [timeZonesByName setObject:concreteTimeZone forKey:name]; return concreteTimeZone; } + (void)initialize { static BOOL didInit = NO; NSArray* searchPaths; NSArray* timeZoneInfoPaths; NSString* timeZoneInfoPathString; id regionsDictionary; id regionsFile = nil; NSString* offset; NSEnumerator* enumerator; NSString* abbreviation; NSAutoreleasePool* pool; int i, count; if (didInit) return; didInit = YES; pool = [NSAutoreleasePool new]; timeZonesByName = [NSMutableDictionary new]; searchPaths = [NSMutableArray arrayWithObject:@RESOURCES_PATH]; timeZoneInfoPathString = [[[NSProcessInfo processInfo] environment] objectForKey:@"LIB_FOUNDATION_RESOURCES_PATH"]; if (timeZoneInfoPathString) { timeZoneInfoPaths = [timeZoneInfoPathString componentsSeparatedByString:@":"]; searchPaths = [timeZoneInfoPaths arrayByAddingObjectsFromArray:searchPaths]; } for (i = 0, count = [searchPaths count]; i < count; i++) { timeZoneInfoFilesPath = [searchPaths objectAtIndex:i]; regionsFile = [[[timeZoneInfoFilesPath stringByAppendingPathComponent:@"TimeZoneInfo"] stringByAppendingPathComponent:@"RegionsDictionary"] stringByResolvingSymlinksInPath]; if(regionsFile && [regionsFile length]) break; } if (!regionsFile || ![regionsFile length]) { NSLog (@"Cannot find the 'TimeZoneInfo/RegionsDictionary' resource " @"file for NSTimeZone"); return; } [timeZoneInfoFilesPath retain]; regionsDictionary = [[NSString stringWithContentsOfFile:regionsFile] propertyList]; regionsByOffset = [[regionsDictionary objectForKey:@"RegionsByOffset"] mutableCopy]; if (!regionsByOffset) { NSLog (@"No regions by offset in the '%@' resource file (under " @"key 'RegionsByOffset')", regionsFile); return; } timeZoneArray = [[[regionsDictionary objectForKey:@"RegionsByOffset"] allValues] retain]; enumerator = [regionsByOffset keyEnumerator]; while ((offset = [enumerator nextObject])) { NSMutableArray* longitudinalRegions = [[[regionsByOffset objectForKey:offset] mutableCopy] autorelease]; int j, count2; [regionsByOffset setObject:longitudinalRegions forKey:offset]; for (j = 0, count2 = [longitudinalRegions count]; j < count2; j++) { NSString* timeZoneName = [longitudinalRegions objectAtIndex:j]; NSTimeZone* timeZone; timeZone = [timeZonesByName objectForKey:timeZoneName]; if (!timeZone) timeZone = [self _createTimeZoneWithName:timeZoneName checkDuplicates:NO]; [longitudinalRegions replaceObjectAtIndex:j withObject:timeZone]; } } abbreviationDictionary = [[regionsDictionary objectForKey:@"Abbreviations"] mutableCopy]; if (!abbreviationDictionary) { NSLog (@"No abbreviation dictionary in the '%@' resource file (under " @"key 'Abbreviations')", regionsFile); return; } enumerator = [abbreviationDictionary keyEnumerator]; while ((abbreviation = [enumerator nextObject])) { NSString* timeZoneName = [abbreviationDictionary objectForKey:abbreviation]; NSTimeZone* timeZone = [timeZonesByName objectForKey:timeZoneName]; if (!timeZone) { NSLog (@"warning: time zone '%@' is not declared in the " @"'RegionsByOffset' dictionary in resource file '%@'", timeZoneName, regionsFile); timeZone = [self _createTimeZoneWithName:timeZoneName checkDuplicates:NO]; } if (timeZone) [abbreviationDictionary setObject:timeZone forKey:abbreviation]; } [pool release]; } + (void)setDefaultTimeZone:(NSTimeZone*)aTimeZone { NSUserDefaults* userDef = [NSUserDefaults standardUserDefaults]; [aTimeZone retain]; [defaultTimeZone release]; defaultTimeZone = aTimeZone; [aTimeZone retain]; [localTimeZone release]; localTimeZone = aTimeZone; [userDef setObject:[defaultTimeZone timeZoneName] forKey:@"TimeZoneName"]; [userDef synchronize]; } + (NSTimeZoneDetail*)defaultTimeZone { if (defaultTimeZone == nil) { NSUserDefaults* userDef = [NSUserDefaults standardUserDefaults]; NSString* zName; zName = [userDef stringForKey:@"TimeZoneName"]; defaultTimeZone = [[self timeZoneWithName:zName] retain]; if (defaultTimeZone == nil) defaultTimeZone = [[self timeZoneWithAbbreviation:zName] retain]; if (defaultTimeZone == nil) defaultTimeZone = [[self timeZoneWithAbbreviation:@"GMT"] retain]; } return defaultTimeZone; } + (NSTimeZone*)localTimeZone { if (localTimeZone == nil) { // TODO : subclass NS*TimeZone to have a special encoding class localTimeZone = [[self defaultTimeZone] retain]; } return localTimeZone; } + (NSDictionary*)abbreviationDictionary { return abbreviationDictionary; } + (NSArray*)timeZoneArray { return timeZoneArray; } + (NSTimeZone*)timeZoneWithName:(NSString*)name { NSTimeZone* timezone; if (!name) return nil; if (!(timezone = [timeZonesByName objectForKey:name])) timezone = [self _createTimeZoneWithName:name checkDuplicates:NO]; return timezone; } + (NSTimeZone*)timeZoneWithAbbreviation:(NSString*)abbreviation { return [abbreviationDictionary objectForKey:abbreviation]; } + (NSTimeZone*)timeZoneForSecondsFromGMT:(int)seconds { BOOL isNegative = (seconds < 0); int hours, minutes; NSString* offset; NSArray* timeZoneArray; NSArray* details; NSTimeZoneDetail* detail; NSTimeZone* timeZone; int i, j, count1, count2; hours = abs (seconds) / 3600; minutes = (abs (seconds) - hours * 3600) / 60; offset = [NSString stringWithFormat:@"%c%02d%02d", (isNegative ? '-' : '+'), hours, minutes]; timeZoneArray = [regionsByOffset objectForKey:offset]; /* If there is no matching zone create an instance of NSConcreteTimeZone with a single detail whose offset is `seconds'. */ if (!timeZoneArray) return [NSConcreteTimeZone timeZoneWithOffset:seconds]; /* Do a search to find a zone that has a detail with no daylight saving which has the offset equal with `seconds'. */ for (i = 0, count1 = [timeZoneArray count]; i < count1; i++) { timeZone = [timeZoneArray objectAtIndex:i]; details = [timeZone timeZoneDetailArray]; /* Find a time zone that has a detail which is not daylight saving and has the offset equal with `seconds'. If no such detail is found the search either continues or ends depending on the offset of detail. */ for (j = 0, count2 = [details count]; j < count2; j++) { detail = [details objectAtIndex:j]; if (![detail isDaylightSavingTimeZone] && [detail timeZoneSecondsFromGMT] == seconds) return timeZone; } } NSLog (@"warning: unexpected failure of +timeZoneForSecondsFromGMT: " @"method. All the timezones specified for offset %@ do not " @"contain a detail whose non daylight saving offset is equal to " @"%@!", offset, offset); /* Return something useful even if there was an error! */ return [NSConcreteTimeZone timeZoneWithOffset:seconds]; } - (NSString*)timeZoneName { [self subclassResponsibility:_cmd]; return nil; } - (NSArray*)timeZoneDetailArray { [self subclassResponsibility:_cmd]; return nil; } - (NSTimeZoneDetail*)timeZoneDetailForDate:(NSDate*)date { [self subclassResponsibility:_cmd]; return nil; } - (id)copyWithZone:(NSZone*)zone { [self subclassResponsibility:_cmd]; return nil; } - (NSString*)description { return [[self timeZoneName] description]; } - (Class)classForCoder { return [NSTimeZone class]; } - (void)encodeWithCoder:(NSCoder*)aCoder { [aCoder encodeObject:[self timeZoneName]]; } - (id)initWithCoder:(NSCoder*)aDecoder { NSString* timeZoneName = [aDecoder decodeObject]; return [NSTimeZone timeZoneWithName:timeZoneName]; } @end /* NSTimeZone */ /* * NSTimeZone detail (concrete non-mutable subclass of NSTimeZone) */ @implementation NSTimeZoneDetail - (int)timeZoneSecondsFromGMT { [self subclassResponsibility:_cmd]; return 0; } - (NSString*)timeZoneAbbreviation { [self subclassResponsibility:_cmd]; return nil; } - (BOOL)isDaylightSavingTimeZone { [self subclassResponsibility:_cmd]; return NO; } - (BOOL)isEqual:anObject { if (anObject == self) return YES; return ([super isEqual:anObject] // this checks to ensure that they're the same class && [[self timeZoneName] isEqual:[anObject timeZoneName]] && [[self timeZoneAbbreviation] isEqual:[anObject timeZoneAbbreviation]] && [self isDaylightSavingTimeZone] == [anObject isDaylightSavingTimeZone] && [self timeZoneSecondsFromGMT] == [anObject timeZoneSecondsFromGMT]); } - (unsigned int)hash { // This should be sufficient for hashing return [self timeZoneSecondsFromGMT]; } @end /* NSTimeZoneDetail */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.