--- gnustep-base-1.7.1/Source/NSTimeZone.m Fri Jun 6 20:24:41 2003 +++ gnustep-base-dev/Source/NSTimeZone.m Tue Aug 12 15:56:24 2003 @@ -155,6 +155,22 @@ } @end +#ifdef WIN32 address@hidden GSWindowsTimeZone : NSTimeZone +{ address@hidden + NSString *timeZoneName; + NSString *daylightZoneName; + NSString *timeZoneNameAbbr; + NSString *daylightZoneNameAbbr; + LONG Bias; + LONG StandardBias; + LONG DaylightBias; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +} address@hidden +#endif static NSTimeZone *defaultTimeZone = nil; static NSTimeZone *localTimeZone = nil; @@ -439,12 +455,25 @@ fileName = [NSTimeZoneClass getTimeZoneFile: name]; if (fileName == nil) +#ifdef WIN32 + { + zone = [[GSWindowsTimeZone alloc] initWithName:name data:0]; + RELEASE(self); + return zone; + } +#else { NSLog(@"Unknown time zone name `%@'.", name); return nil; } +#endif data = [NSData dataWithContentsOfFile: fileName]; } +#ifdef WIN32 + if (!data) + zone = [[GSWindowsTimeZone alloc] initWithName: name data: data]; + else +#endif zone = [[GSTimeZone alloc] initWithName: name data: data]; } } @@ -1131,6 +1160,24 @@ localZoneString = [[[NSProcessInfo processInfo] environment] objectForKey: @"TZ"]; } +#ifdef WIN32 +{ + HKEY regkey; + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", 0, KEY_READ, ®key)) { + char buf[100]; + DWORD bufsize=100; + DWORD type; + if (ERROR_SUCCESS==RegQueryValueEx(regkey, "StandardName", 0, &type, buf, &bufsize)) { + bufsize=strlen(buf); + while (bufsize && isspace(buf[bufsize-1])) { + bufsize--; + } + localZoneString = [NSString stringWithCString:buf length:bufsize]; + } + RegCloseKey(regkey); + } +} +#endif if (localZoneString != nil) { zone = [defaultPlaceholderTimeZone initWithName: localZoneString]; @@ -1510,7 +1557,240 @@ @end +#ifdef WIN32 +typedef struct TZI_format { + LONG Bias; + LONG StandardBias; + LONG DaylightBias; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +} TZI; +static inline unsigned int +lastDayOfGregorianMonth(int month, int year) +{ + switch (month) + { + case 2: + if ((((year % 4) == 0) && ((year % 100) != 0)) + || ((year % 400) == 0)) + return 29; + else + return 28; + case 4: + case 6: + case 9: + case 11: return 30; + default: return 31; + } +} +void +GSBreakTime(NSTimeInterval when, int *year, int *month, int *day, + int *hour, int *minute, int *second, int *mil); +int dayOfCommonEra(NSTimeInterval when); address@hidden GSWindowsTimeZone +- (NSString*) abbreviationForDate: (NSDate*)aDate +{ + if ([self isDaylightSavingTimeForDate:aDate]) + return daylightZoneNameAbbr; + return timeZoneNameAbbr; +} +- (NSData*) data +{ + return 0; +} +- (void) dealloc +{ + RELEASE(timeZoneName); + RELEASE(daylightZoneName); + RELEASE(timeZoneNameAbbr); + RELEASE(daylightZoneNameAbbr); + [super dealloc]; +} +- (id) initWithName: (NSString*)name data: (NSData*)data +{ + NSString *shortName; + HKEY regkey; + + if ([name hasSuffix:@" Standard Time"]) { + shortName = [name substringWithRange:NSMakeRange(0,[name length]-14)]; + } else { + shortName = name; + } + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, [[NSString stringWithFormat:@"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\%@", name] cString], 0, KEY_READ, ®key) || ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, [[NSString stringWithFormat:@"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones\\%@", shortName] cString], 0, KEY_READ, ®key)) { + char buf[200]; + DWORD bufsize=sizeof(buf); + DWORD type; + if (ERROR_SUCCESS==RegQueryValueEx(regkey, "TZI", 0, &type, buf, &bufsize)) { + TZI *tzi = (void*)buf; + Bias = tzi->Bias; + StandardBias = tzi->StandardBias; + DaylightBias = tzi->DaylightBias; + StandardDate = tzi->StandardDate; + DaylightDate = tzi->DaylightDate; + } + bufsize=sizeof(buf); + if (ERROR_SUCCESS==RegQueryValueEx(regkey, "Std", 0, &type, buf, &bufsize)) { + int a, b; + [timeZoneName release]; + timeZoneName = [[NSString stringWithCString:buf] retain]; + for(a=0,b=0;buf[a];a++) { + if (isupper(buf[a])) + buf[b++]=buf[a]; + } + buf[b]=0; + [timeZoneNameAbbr release]; + timeZoneNameAbbr = [[NSString stringWithCString:buf] retain]; + } + if (ERROR_SUCCESS==RegQueryValueEx(regkey, "Dlt", 0, &type, buf, &bufsize)) { + int a,b; + [daylightZoneName release]; + daylightZoneName = [[NSString stringWithCString:buf] retain]; + for(a=0,b=0;buf[a];a++) { + if (isupper(buf[a])) + buf[b++]=buf[a]; + } + buf[b]=0; + [daylightZoneNameAbbr release]; + daylightZoneNameAbbr = [[NSString stringWithCString:buf] retain]; + } + RegCloseKey(regkey); + } + return self; +} +- (BOOL) isDaylightSavingTimeForDate: (NSDate*)aDate +{ + int year, month, day, hour, minute, second, mil; + int dow; + int daylightdate, count, maxdate; + NSTimeInterval when; + + if (DaylightDate.wMonth == 0) + return NO; + + when = [aDate timeIntervalSinceReferenceDate] - Bias*60; + + GSBreakTime(when, &year, &month, &day, &hour, &minute, &second, &mil); + + // Before April or after October is Std + if (month < DaylightDate.wMonth || month > StandardDate.wMonth) + return NO; + // After April and before October is DST + if (month > DaylightDate.wMonth && month < StandardDate.wMonth) + return YES; + dow = dayOfCommonEra(when); + + dow = dow % 7; + if (dow < 0) + dow += 7; + + if (month == DaylightDate.wMonth /* April */) { + daylightdate = day - dow + DaylightDate.wDayOfWeek; + maxdate = lastDayOfGregorianMonth(DaylightDate.wMonth, year)-7; + while (daylightdate > 7) + daylightdate-=7; + if (daylightdate < 1) + daylightdate += 7; + count=DaylightDate.wDay; + while (count>1 && daylightdate < maxdate) { + daylightdate+=7; + count--; + } + if (day > daylightdate) + return YES; + if (day < daylightdate) + return NO; + if (hour > DaylightDate.wHour) + return YES; + if (hour < DaylightDate.wHour) + return NO; + if (minute > DaylightDate.wMinute) + return YES; + if (minute < DaylightDate.wMinute) + return NO; + if (second > DaylightDate.wSecond) + return YES; + if (second < DaylightDate.wSecond) + return NO; + if (mil >= DaylightDate.wMilliseconds) + return YES; + return NO; + } + if (month == StandardDate.wMonth /* October */) { + daylightdate = day - dow + StandardDate.wDayOfWeek; + maxdate = lastDayOfGregorianMonth(StandardDate.wMonth, year)-7; + while (daylightdate > 7) + daylightdate-=7; + if (daylightdate < 1) + daylightdate += 7; + count=StandardDate.wDay; + while (count>1 && daylightdate < maxdate) { + daylightdate+=7; + count--; + } + if (day > daylightdate) + return NO; + if (day < daylightdate) + return YES; + if (hour > StandardDate.wHour) + return NO; + if (hour < StandardDate.wHour) + return YES; + if (minute > StandardDate.wMinute) + return NO; + if (minute < StandardDate.wMinute) + return YES; + if (second > StandardDate.wSecond) + return NO; + if (second < StandardDate.wSecond) + return YES; + if (mil >= StandardDate.wMilliseconds) + return NO; + return YES; + } + return NO; // Never reached +} +- (NSString*) name +{ + return timeZoneName; +} +- (int) secondsFromGMTForDate: (NSDate*)aDate +{ + if ([self isDaylightSavingTimeForDate:aDate]) + return -Bias*60 - DaylightBias*60; + return -Bias*60 - StandardBias*60; +} +- (NSArray*) timeZoneDetailArray +{ + return [NSArray arrayWithObjects:[[[GSTimeZoneDetail alloc] initWithTimeZone:self withAbbrev:timeZoneNameAbbr withOffset:-Bias*60 - StandardBias*60 withDST:NO] autorelease], [[[GSTimeZoneDetail alloc] initWithTimeZone:self withAbbrev:daylightZoneNameAbbr withOffset:-Bias*60 - DaylightBias*60 withDST:YES] autorelease], 0]; +} +- (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)aDate +{ + GSTimeZoneDetail *detail; + int offset; + BOOL isDST = [self isDaylightSavingTimeForDate:aDate]; + NSString *abbr; + + if (isDST) { + offset = -Bias*60 - DaylightBias*60; + abbr = daylightZoneNameAbbr; + } else { + offset = -Bias*60 - StandardBias*60; + abbr = timeZoneNameAbbr; + } + detail = [GSTimeZoneDetail alloc]; + detail = [detail initWithTimeZone: self + withAbbrev: abbr + withOffset: offset + withDST: isDST]; + return detail; +} +- (NSString*) timeZoneName +{ + return timeZoneName; +} address@hidden +#endif @implementation GSTimeZone