2001-12-17 14:31:42 +00:00
/ * * Time zone management . - * - Mode : ObjC - * -
2002-09-30 16:55:28 +00:00
Copyright ( C ) 1997 -2002 Free Software Foundation , Inc .
2005-02-22 11:22:44 +00:00
1997-09-01 21:59:51 +00:00
Written by : Yoo C . Chung < wacko @ laplace . snu . ac . kr >
Date : June 1997
2005-02-22 11:22:44 +00:00
2004-02-29 21:17:40 +00:00
Rewrite large chunks by : Richard Frith - Macdonald < rfm @ gnu . org >
2002-09-30 16:55:28 +00:00
Date : September 2002
2005-02-22 11:22:44 +00:00
1997-09-01 21:59:51 +00:00
This file is part of the GNUstep Base Library .
2005-02-22 11:22:44 +00:00
1997-10-17 13:35:52 +00:00
This library is free software ; you can redistribute it and / or
2007-09-14 11:36:11 +00:00
modify it under the terms of the GNU Lesser General Public License
2008-06-08 10:38:33 +00:00
as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
2005-02-22 11:22:44 +00:00
1997-09-01 21:59:51 +00:00
This library is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
1997-10-17 13:35:52 +00:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Library General Public License for more details .
2005-02-22 11:22:44 +00:00
2007-09-14 11:36:11 +00:00
You should have received a copy of the GNU Lesser General Public
1997-09-01 21:59:51 +00:00
License along with this library ; if not , write to the Free Software
2006-10-20 10:56:27 +00:00
Foundation , Inc . , 51 Franklin Street , Fifth Floor ,
Boston , MA 02111 USA .
2001-12-18 16:54:15 +00:00
< title > NSTimeZone class reference < / title >
2006-05-24 08:27:39 +00:00
$ Date $ $ Revision $
2001-12-18 16:54:15 +00:00
* /
2005-02-22 11:22:44 +00:00
2004-10-11 03:08:54 +00:00
/ * Use the system time zones if available . In other cases , use an
implementation independent of the system , since POSIX functions for
time zones are woefully inadequate for implementing NSTimeZone .
Time zone names can be different from system to system , but usually
the user has already set up his timezone independant of GNUstep , so we
should respect that information .
1997-09-01 21:59:51 +00:00
We do not use a dictionary for storing time zones , since such a
dictionary would be VERY large ( ~ 500 K ) . And we would have to use a
complicated object determining whether we ' re using daylight savings
1997-11-03 14:30:13 +00:00
time and such for every entry in the dictionary . ( Though we will
eventually have to change the implementation to prevent the year
2038 problem . )
1997-09-01 21:59:51 +00:00
2004-02-29 21:17:40 +00:00
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
2010-06-01 19:30:28 +00:00
5 ) tzset ( ) & tznam [ ] for platforms which have it
6 ) TZDEFAULT defined in tzfile . h on platforms which have it
2004-10-11 03:08:54 +00:00
7 ) Windows registry , for Win32 systems
8 ) or the fallback time zone ( which is UTC )
2000-01-05 14:53:03 +00:00
with the ones listed first having precedence .
1997-09-01 21:59:51 +00:00
Any time zone must be a file name in ZONES_DIR .
2004-02-29 21:17:40 +00:00
Files & File System Heirarchy info :
=== === === === === === === === === === === = =
2005-02-22 11:22:44 +00:00
2004-02-29 21:17:40 +00:00
Default place for the NSTimeZone directory is _time _zone _path ( ) :
2007-03-19 20:03:00 +00:00
{ $ ( GNUSTEP_SYSTEM _LIBRARY ) / Libraries / gnustep - base / Versions / 1.14 / Resources / TIME_ZONE _DIR )
2005-02-22 11:22:44 +00:00
2004-02-29 21:17:40 +00:00
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
2007-03-19 20:03:00 +00:00
( dir ) . . / System / Library / Libraries / gnustep - base / Versions / 1.14 / Resources /. .
2004-02-29 21:17:40 +00:00
( dir ) NSTimeZone
( file ) localtime { text ; time zone eg Australia / Perth }
( dir ) zones
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 .
2005-02-22 11:22:44 +00:00
1997-09-01 21:59:51 +00:00
FIXME ? : use leap seconds ? * /
2010-02-19 08:12:46 +00:00
# import "common.h"
2010-02-14 10:48:10 +00:00
# define EXPOSE_NSTimeZone _IVARS 1
# import "GNUstepBase/GSLock.h"
1997-09-01 21:59:51 +00:00
# include < stdio . h >
# include < string . h >
2003-09-04 03:28:14 +00:00
# include < time . h >
2010-02-14 10:48:10 +00:00
# import "Foundation/NSArray.h"
# import "Foundation/NSCoder.h"
# import "Foundation/NSData.h"
# import "Foundation/NSDate.h"
# import "Foundation/NSDictionary.h"
# import "Foundation/NSException.h"
# import "Foundation/NSFileManager.h"
# import "Foundation/NSLock.h"
# import "Foundation/NSProcessInfo.h"
# import "Foundation/NSUserDefaults.h"
# import "Foundation/NSBundle.h"
# import "Foundation/NSMapTable.h"
# import "Foundation/NSThread.h"
# import "Foundation/NSNotification.h"
# import "Foundation/NSPortCoder.h"
# import "Foundation/NSTimeZone.h"
# import "Foundation/NSByteOrder.h"
# import "GNUstepBase/GSConfig.h"
# import "GNUstepBase/NSObject+GNUstepBase.h"
# import "GNUstepBase/NSString+GNUstepBase.h"
# import "GSPrivate.h"
1997-09-01 21:59:51 +00:00
2004-10-26 19:08:17 +00:00
# ifdef HAVE_TZHEAD
2004-10-11 03:08:54 +00:00
# include < tzfile . h >
# else
1997-09-01 21:59:51 +00:00
# define NOID
2004-10-11 03:08:54 +00:00
# include "nstzfile.h"
# endif
1997-09-01 21:59:51 +00:00
2008-06-06 13:57:06 +00:00
NSString * const NSSystemTimeZoneDidChangeNotification
= @ "NSSystemTimeZoneDidChangeNotification" ;
1997-09-01 21:59:51 +00:00
/ * Key for local time zone in user defaults . * /
1997-11-28 20:13:58 +00:00
# define LOCALDBKEY @ "Local Time Zone"
1995-08-23 16:13:42 +00:00
2004-02-29 21:17:40 +00:00
/ * Directory that contains the time zone data .
Expected in Resources directory for library bundle . * /
1999-04-23 02:54:45 +00:00
# define TIME_ZONE _DIR @ "NSTimeZones"
1995-08-23 16:13:42 +00:00
2004-12-21 23:20:32 +00:00
/ * Name of time zone abbreviation ( plist ) dictionary . * /
# define ABBREV_DICT @ "abbreviations"
/ * Name of time zone abbreviation map . It is a text file
1997-09-01 21:59:51 +00:00
with each line comprised of the abbreviation , a whitespace , and the
name . Neither the abbreviation nor the name can contain
whitespace , and each line must not be longer than 80 characters . * /
2004-12-21 23:20:32 +00:00
# define ABBREV_MAP @ "abbreviations"
1995-08-23 16:13:42 +00:00
1997-09-01 21:59:51 +00:00
/ * File holding regions grouped by latitude . It is a text file with
each line comprised of the latitude region , whitespace , and the
1997-11-03 14:30:13 +00:00
name . Neither the abbreviation nor the name can contain
1997-09-01 21:59:51 +00:00
whitespace , and each line must not be longer than 80 characters . * /
1997-10-18 19:49:50 +00:00
# define REGIONS_FILE @ "regions"
1995-08-23 16:13:42 +00:00
1997-10-17 13:35:52 +00:00
/ * Name of the file that contains the name of the local time zone . * /
1997-10-18 19:49:50 +00:00
# define LOCAL_TIME _FILE @ "localtime"
1997-10-17 13:35:52 +00:00
1997-09-01 21:59:51 +00:00
/ * Directory that contains the actual time zones . * /
1997-11-28 20:13:58 +00:00
# define ZONES_DIR @ "zones/"
1995-08-23 16:13:42 +00:00
2004-10-11 03:08:54 +00:00
/ * Many systems have this file * /
# define SYSTEM_TIME _FILE @ "/etc/localtime"
2006-04-12 19:41:44 +00:00
/ * If TZDIR told us where the zoneinfo files are , don ' t append anything else * /
# ifdef TZDIR
# define POSIX_TZONES @ ""
# else
2006-02-21 15:44:04 +00:00
# define POSIX_TZONES @ "posix/"
2006-04-12 19:41:44 +00:00
# endif
2006-02-21 15:44:04 +00:00
2004-10-11 03:08:54 +00:00
/ * Possible location of system time zone files * /
static NSString * tzdir = nil ;
1995-08-23 16:13:42 +00:00
2002-10-01 10:25:40 +00:00
@ class GSAbsTimeZone ;
@ class GSTimeZoneDetail ;
@ class GSAbsTimeZoneDetail ;
1995-08-23 16:13:42 +00:00
2004-02-29 21:17:40 +00:00
@ class GSPlaceholderTimeZone ;
2001-01-31 11:29:55 +00:00
/ *
* Information for abstract placeholder class .
* /
static GSPlaceholderTimeZone * defaultPlaceholderTimeZone ;
static NSMapTable * placeholderMap ;
1995-08-23 16:13:42 +00:00
2002-10-01 10:25:40 +00:00
/ *
* Temporary structure for holding time zone details .
* This is the format in the data object .
* /
1997-09-01 21:59:51 +00:00
struct ttinfo
1995-08-23 16:13:42 +00:00
{
2004-02-29 21:17:40 +00:00
char offset [ 4 ] ; // Seconds east of UTC
unsigned char isdst ; // Daylight savings time ?
2002-10-01 10:25:40 +00:00
unsigned char abbr_idx ; // Index into time zone abbreviations string
2004-07-01 23:24:35 +00:00
} __attribute __ ( ( packed ) ) ;
1995-08-23 16:13:42 +00:00
2002-10-01 10:25:40 +00:00
/ *
* And this is the structure used in the time zone instances .
* /
typedef struct {
2006-01-11 08:37:16 +00:00
int32_t offset ;
2002-10-01 10:25:40 +00:00
BOOL isdst ;
unsigned char abbr_idx ;
char pad [ 2 ] ;
NSString * abbreviation ;
} TypeInfo ;
2002-09-30 16:54:29 +00:00
@ interface GSTimeZone : NSTimeZone
{
@ public
NSString * timeZoneName ;
2006-02-21 15:44:04 +00:00
NSArray * abbreviations ;
2002-10-01 10:25:40 +00:00
NSData * timeZoneData ;
2002-09-30 16:54:29 +00:00
unsigned int n_trans ;
unsigned int n_types ;
2006-01-11 08:37:16 +00:00
int32_t * trans ;
2002-10-01 10:25:40 +00:00
TypeInfo * types ;
2002-09-30 16:54:29 +00:00
unsigned char * idxs ;
}
@ end
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2004-02-29 21:17:40 +00:00
@ interface GSWindowsTimeZone : NSTimeZone
{
@ public
NSString * timeZoneName ;
NSString * daylightZoneName ;
NSString * timeZoneNameAbbr ;
NSString * daylightZoneNameAbbr ;
LONG Bias ;
LONG StandardBias ;
LONG DaylightBias ;
SYSTEMTIME StandardDate ;
SYSTEMTIME DaylightDate ;
}
@ end
# endif
1995-08-23 16:13:42 +00:00
2001-01-30 20:47:05 +00:00
static NSTimeZone * defaultTimeZone = nil ;
static NSTimeZone * localTimeZone = nil ;
static NSTimeZone * systemTimeZone = nil ;
1995-08-23 16:13:42 +00:00
1997-09-01 21:59:51 +00:00
/ * Dictionary for time zones . Each time zone must have a unique
name . * /
static NSMutableDictionary * zoneDictionary ;
1995-08-23 16:13:42 +00:00
2004-12-21 23:20:32 +00:00
/ * one - to - one abbreviation to time zone name dictionary . * /
static NSMutableDictionary * abbreviationDictionary = nil ;
/ * one - to - many abbreviation to time zone name dictionary . * /
static NSMutableDictionary * abbreviationMap = nil ;
1995-08-23 16:13:42 +00:00
1997-09-01 21:59:51 +00:00
/ * Lock for creating time zones . * /
2001-01-30 20:47:05 +00:00
static NSRecursiveLock * zone_mutex = nil ;
1995-08-23 16:13:42 +00:00
2001-01-30 12:05:02 +00:00
static Class NSTimeZoneClass ;
2001-01-31 11:29:55 +00:00
static Class GSPlaceholderTimeZoneClass ;
1995-08-23 16:13:42 +00:00
1997-09-01 21:59:51 +00:00
/ * 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 . * /
static inline int
decode ( const void * ptr )
1995-08-23 16:13:42 +00:00
{
1997-09-01 21:59:51 +00:00
# if defined ( WORDS_BIGENDIAN ) && SIZEOF_INT = = 4
2001-04-10 03:27:01 +00:00
# if NEED_WORD _ALIGNMENT
int value ;
2009-02-23 20:42:32 +00:00
memcpy ( & value , ptr , sizeof ( NSInteger ) ) ;
2001-04-10 03:27:01 +00:00
return value ;
# else
2009-02-23 20:42:32 +00:00
return * ( const NSInteger * ) ptr ;
2001-04-10 03:27:01 +00:00
# endif
1997-09-01 21:59:51 +00:00
# else / * defined ( WORDS_BIGENDIAN ) && SIZEOF_INT = = 4 * /
const unsigned char * p = ptr ;
int result = * p & ( 1 < < ( CHAR_BIT - 1 ) ) ? ~ 0 : 0 ;
result = ( result < < 8 ) | * p + + ;
result = ( result < < 8 ) | * p + + ;
result = ( result < < 8 ) | * p + + ;
result = ( result < < 8 ) | * p + + ;
return result ;
# endif / * defined ( WORDS_BIGENDIAN ) && SIZEOF_INT = = 4 * /
}
1995-08-23 16:13:42 +00:00
2003-04-28 02:29:49 +00:00
/ * Return path to a TimeZone directory file * /
2004-12-21 23:20:32 +00:00
static NSString * _time _zone _path ( NSString * subpath , NSString * type )
2003-04-28 02:29:49 +00:00
{
NSBundle * gbundle ;
2004-12-21 23:20:32 +00:00
if ( type = = nil )
type = @ "" ;
2007-03-09 19:09:08 +00:00
gbundle = [ NSBundle bundleForClass : [ NSObject class ] ] ;
2005-02-22 11:22:44 +00:00
return [ gbundle pathForResource : subpath
2004-12-21 23:20:32 +00:00
ofType : type
2003-04-28 02:29:49 +00:00
inDirectory : TIME_ZONE _DIR ] ;
}
1995-08-23 16:13:42 +00:00
2001-01-31 11:29:55 +00:00
@ interface GSPlaceholderTimeZone : NSTimeZone
@ end
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
@ interface GSAbsTimeZone : NSTimeZone
1995-08-23 16:13:42 +00:00
{
2002-10-01 10:25:40 +00:00
@ public
NSString * name ;
id detail ;
int offset ; // Offset from UTC in seconds .
1995-08-23 16:13:42 +00:00
}
2009-02-23 20:42:32 +00:00
- ( id ) initWithOffset : ( NSInteger ) anOffset name : ( NSString * ) aName ;
1997-10-17 13:35:52 +00:00
@ end
2005-02-22 11:22:44 +00:00
2001-01-30 20:47:05 +00:00
@ interface NSLocalTimeZone : NSTimeZone
@ end
2002-10-01 10:25:40 +00:00
@ interface GSTimeZoneDetail : NSTimeZoneDetail
1995-08-23 16:13:42 +00:00
{
2002-09-30 16:54:29 +00:00
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 ?
1995-08-23 16:13:42 +00:00
}
1997-09-01 21:59:51 +00:00
1999-08-25 16:12:36 +00:00
- ( id ) initWithTimeZone : ( NSTimeZone * ) aZone
withAbbrev : ( NSString * ) anAbbrev
2009-02-23 20:42:32 +00:00
withOffset : ( NSInteger ) anOffset
1999-08-25 16:12:36 +00:00
withDST : ( BOOL ) isDST ;
1997-10-17 13:35:52 +00:00
@ end
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
@ interface GSAbsTimeZoneDetail : NSTimeZoneDetail
{
GSAbsTimeZone * zone ; // Time zone which created this object .
}
- ( id ) initWithTimeZone : ( GSAbsTimeZone * ) aZone ;
@ end
2005-02-22 11:22:44 +00:00
1997-11-03 14:30:13 +00:00
/ * Private methods for obtaining resource file names . * /
@ interface NSTimeZone ( Private )
2008-06-06 14:47:40 +00:00
+ ( NSString * ) _getTimeZoneFile : ( NSString * ) name ;
+ ( void ) _notified : ( NSNotification * ) n ;
1997-11-03 14:30:13 +00:00
@ end
2001-01-31 11:29:55 +00:00
@ implementation GSPlaceholderTimeZone
- ( id ) autorelease
{
NSWarnLog ( @ "-autorelease sent to uninitialised time zone" ) ;
return self ; // placeholders never get released .
}
- ( void ) dealloc
{
2006-06-04 06:42:10 +00:00
GSNOSUPERDEALLOC ; // placeholders never get deallocated .
2001-01-31 11:29:55 +00:00
}
2002-09-30 16:54:29 +00:00
- ( id ) initWithName : ( NSString * ) name data : ( NSData * ) data
2001-01-31 11:29:55 +00:00
{
NSTimeZone * zone ;
2002-10-01 10:25:40 +00:00
unsigned length = [ name length ] ;
2001-01-31 11:29:55 +00:00
2002-10-01 10:25:40 +00:00
if ( length = = 0 )
{
NSLog ( @ "Disallowed null time zone name" ) ;
return nil ;
}
if ( length = = 15 && [ name isEqual : @ "NSLocalTimeZone" ] )
2001-01-31 11:29:55 +00:00
{
2002-09-30 16:54:29 +00:00
zone = RETAIN ( localTimeZone ) ;
2002-09-30 17:14:51 +00:00
DESTROY ( self ) ;
return zone ;
2001-01-31 11:29:55 +00:00
}
2001-01-31 15:10:41 +00:00
/ *
2001-05-02 11:52:43 +00:00
* Return a cached time zone if possible .
2002-10-01 10:25:40 +00:00
* NB . if data of cached zone does not match new data . . . don ' t use cache
2001-01-31 15:10:41 +00:00
* /
if ( zone_mutex ! = nil )
{
[ zone_mutex lock ] ;
}
zone = [ zoneDictionary objectForKey : name ] ;
2002-10-01 10:31:51 +00:00
if ( data ! = nil && [ data isEqual : [ zone data ] ] = = NO )
2002-10-01 10:25:40 +00:00
{
zone = nil ;
}
2001-05-02 11:52:43 +00:00
IF_NO _GC ( RETAIN ( zone ) ) ;
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
}
2002-10-01 10:25:40 +00:00
2002-09-30 16:54:29 +00:00
if ( zone = = nil )
2001-01-31 15:10:41 +00:00
{
2002-10-01 10:25:40 +00:00
unichar c ;
2009-02-23 20:42:32 +00:00
int i ;
2002-10-01 10:25:40 +00:00
2006-02-27 09:35:19 +00:00
if ( ( length = = 3
&& ( [ name isEqualToString : @ "GMT" ] = = YES
|| [ name isEqualToString : @ "UTC" ] = = YES
|| [ name isEqualToString : @ "UCT" ] = = YES ) )
|| ( length = = 4
&& ( [ name isEqualToString : @ "GMT0" ] = = YES
|| [ name isEqualToString : @ "Zulu" ] = = YES ) )
|| ( length = = 9 && [ name isEqualToString : @ "Universal" ] = = YES ) )
{
// Synonyms for GMT
zone = [ [ GSAbsTimeZone alloc ] initWithOffset : 0 name : name ] ;
}
else if ( length = = 5 && [ name hasPrefix : @ "GMT" ] = = YES
&& ( ( c = [ name characterAtIndex : 3 ] ) = = ' + ' || c = = ' - ' )
&& ( ( c = [ name characterAtIndex : 4 ] ) >= ' 0 ' && c <= ' 9 ' ) )
{
// GMT -9 to GMT + 9
i = ( c - ' 0 ' ) * 60 * 60 ;
if ( [ name characterAtIndex : 3 ] = = ' - ' )
{
i = - i ;
}
zone = [ [ GSAbsTimeZone alloc ] initWithOffset : i name : name ] ;
}
else if ( length = = 6 && [ name hasPrefix : @ "GMT" ] = = YES
&& ( ( c = [ name characterAtIndex : 3 ] ) = = ' + ' || c = = ' - ' )
&& ( ( c = [ name characterAtIndex : 4 ] ) = = ' 0 ' || c = = ' 1 ' )
&& ( ( c = [ name characterAtIndex : 5 ] ) >= ' 0 ' && c <= ' 4 ' ) )
{
// GMT -14 to GMT -10 and GMT + 10 to GMT + 14
i = ( c - ' 0 ' ) * 60 * 60 ;
if ( [ name characterAtIndex : 4 ] = = ' 1 ' )
{
i + = 60 * 60 * 10 ;
}
if ( [ name characterAtIndex : 3 ] = = ' - ' )
{
i = - i ;
}
zone = [ [ GSAbsTimeZone alloc ] initWithOffset : i name : name ] ;
}
else if ( length = = 8 && [ name hasPrefix : @ "GMT" ] = = YES
2002-10-01 10:25:40 +00:00
&& ( ( c = [ name characterAtIndex : 3 ] ) = = ' + ' || c = = ' - ' ) )
2001-01-31 11:29:55 +00:00
{
2006-02-27 09:35:19 +00:00
// GMT + NNNN and GMT - NNNN
2002-10-01 10:25:40 +00:00
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 ' ) ;
2006-02-27 09:35:19 +00:00
i = i * 60 ;
if ( [ name characterAtIndex : 3 ] = = ' - ' )
{
i = - i ;
}
zone = [ [ GSAbsTimeZone alloc ] initWithOffset : i
name : nil ] ;
2002-10-01 10:25:40 +00:00
}
}
}
}
}
2001-01-31 11:29:55 +00:00
2002-10-01 10:25:40 +00:00
if ( zone = = nil && length > 19
2005-11-06 07:13:33 +00:00
&& [ name hasPrefix : @ "NSAbsoluteTimeZone: " ] = = YES )
2002-10-01 10:25:40 +00:00
{
i = [ [ name substringFromIndex : 19 ] intValue ] ;
2006-02-27 09:35:19 +00:00
zone = [ [ GSAbsTimeZone alloc ] initWithOffset : i name : nil ] ;
2001-01-31 15:10:41 +00:00
}
2002-10-01 10:25:40 +00:00
if ( zone = = nil )
2001-01-31 15:10:41 +00:00
{
2002-09-30 16:54:29 +00:00
if ( data = = nil )
2001-01-31 11:29:55 +00:00
{
2010-06-02 10:27:28 +00:00
NSString * fileName ;
BOOL isDir ;
2001-01-31 11:29:55 +00:00
2008-06-06 14:47:40 +00:00
fileName = [ NSTimeZoneClass _getTimeZoneFile : name ] ;
2005-10-09 11:32:10 +00:00
if ( fileName = = nil
2010-06-02 10:27:28 +00:00
|| ! [ [ NSFileManager defaultManager ] fileExistsAtPath : fileName
isDirectory : & isDir ] || YES = = isDir )
{
data = nil ;
}
else
{
data = [ NSData dataWithContentsOfFile : fileName ] ;
}
if ( nil = = data )
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2004-02-29 21:17:40 +00:00
{
2005-11-06 07:13:33 +00:00
zone = [ [ GSWindowsTimeZone alloc ] initWithName : name data : 0 ] ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2004-02-29 21:17:40 +00:00
return zone ;
}
# else
2002-09-30 16:54:29 +00:00
{
NSLog ( @ "Unknown time zone name `%@'." , name ) ;
return nil ;
}
2004-02-29 21:17:40 +00:00
# endif
2001-01-31 15:10:41 +00:00
}
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2005-11-06 07:13:33 +00:00
if ( ! data )
zone = [ [ GSWindowsTimeZone alloc ] initWithName : name data : data ] ;
else
2004-02-29 21:17:40 +00:00
# endif
2002-09-30 16:54:29 +00:00
zone = [ [ GSTimeZone alloc ] initWithName : name data : data ] ;
2001-01-31 11:29:55 +00:00
}
}
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2001-01-31 11:29:55 +00:00
return zone ;
}
- ( void ) release
{
return ; // placeholders never get released .
}
- ( id ) retain
{
return self ; // placeholders never get retained .
}
@ end
2002-09-30 16:54:29 +00:00
@ implementation NSLocalTimeZone
2005-02-22 11:22:44 +00:00
2002-09-30 16:54:29 +00:00
- ( NSString * ) abbreviation
1997-10-17 13:35:52 +00:00
{
2002-09-30 16:54:29 +00:00
return [ [ NSTimeZoneClass defaultTimeZone ] abbreviation ] ;
1997-10-17 13:35:52 +00:00
}
1997-11-03 14:30:13 +00:00
2002-09-30 16:54:29 +00:00
- ( NSString * ) abbreviationForDate : ( NSDate * ) aDate
1995-08-23 16:13:42 +00:00
{
2002-09-30 16:54:29 +00:00
return [ [ NSTimeZoneClass defaultTimeZone ] abbreviationForDate : aDate ] ;
1998-03-12 14:21:20 +00:00
}
2002-09-30 16:54:29 +00:00
- ( id ) autorelease
1998-03-12 14:21:20 +00:00
{
2001-01-30 12:05:02 +00:00
return self ;
1995-08-23 16:13:42 +00:00
}
2002-10-01 10:25:40 +00:00
- ( NSData * ) data
{
return [ [ NSTimeZoneClass defaultTimeZone ] data ] ;
}
2002-09-30 16:54:29 +00:00
- ( void ) encodeWithCoder : ( NSCoder * ) aCoder
1997-10-17 13:35:52 +00:00
{
2002-09-30 16:54:29 +00:00
[ aCoder encodeObject : @ "NSLocalTimeZone" ] ;
1997-10-17 13:35:52 +00:00
}
1997-11-03 14:30:13 +00:00
2002-09-30 16:54:29 +00:00
- ( id ) init
1995-08-23 16:13:42 +00:00
{
2002-09-30 16:54:29 +00:00
return self ;
1995-08-23 16:13:42 +00:00
}
2001-01-30 20:47:05 +00:00
2002-09-30 16:54:29 +00:00
- ( BOOL ) isDaylightSavingTime
2001-01-30 20:47:05 +00:00
{
2002-09-30 16:54:29 +00:00
return [ [ NSTimeZoneClass defaultTimeZone ] isDaylightSavingTime ] ;
2001-01-30 20:47:05 +00:00
}
2002-09-30 16:54:29 +00:00
- ( BOOL ) isDaylightSavingTimeForDate : ( NSDate * ) aDate
2001-01-30 20:47:05 +00:00
{
2002-09-30 16:54:29 +00:00
return [ [ NSTimeZoneClass defaultTimeZone ] isDaylightSavingTimeForDate : aDate ] ;
2001-01-30 20:47:05 +00:00
}
2001-01-31 11:29:55 +00:00
- ( NSString * ) name
2001-01-30 20:47:05 +00:00
{
2001-01-31 11:29:55 +00:00
return [ [ NSTimeZoneClass defaultTimeZone ] name ] ;
2001-01-30 20:47:05 +00:00
}
2001-01-31 11:29:55 +00:00
- ( void ) release
2001-01-30 20:47:05 +00:00
{
2001-01-31 11:29:55 +00:00
}
- ( id ) retain
{
return self ;
2001-01-30 20:47:05 +00:00
}
2009-02-23 20:42:32 +00:00
- ( NSInteger ) secondsFromGMT
2002-09-30 16:54:29 +00:00
{
return [ [ NSTimeZoneClass defaultTimeZone ] secondsFromGMT ] ;
}
2009-02-23 20:42:32 +00:00
- ( NSInteger ) secondsFromGMTForDate : ( NSDate * ) aDate
2002-09-30 16:54:29 +00:00
{
return [ [ NSTimeZoneClass defaultTimeZone ] secondsFromGMTForDate : aDate ] ;
}
2001-01-30 20:47:05 +00:00
- ( NSArray * ) timeZoneDetailArray
{
return [ [ NSTimeZoneClass defaultTimeZone ] timeZoneDetailArray ] ;
}
2005-02-22 11:22:44 +00:00
2001-01-30 20:47:05 +00:00
- ( NSTimeZoneDetail * ) timeZoneDetailForDate : ( NSDate * ) date
{
return [ [ NSTimeZoneClass defaultTimeZone ] timeZoneDetailForDate : date ] ;
}
2002-09-30 17:14:51 +00:00
- ( NSString * ) timeZoneName
{
return [ [ NSTimeZoneClass defaultTimeZone ] timeZoneName ] ;
}
2001-01-30 20:47:05 +00:00
@ end
2004-02-29 21:17:40 +00:00
2002-10-01 10:25:40 +00:00
@ implementation GSAbsTimeZone
1997-11-03 14:30:13 +00:00
2003-02-13 13:31:59 +00:00
static int uninitialisedOffset = 100000 ;
1999-08-25 16:12:36 +00:00
static NSMapTable * absolutes = 0 ;
+ ( void ) initialize
1997-09-01 21:59:51 +00:00
{
2002-10-01 10:25:40 +00:00
if ( self = = [ GSAbsTimeZone class ] )
1999-08-25 16:12:36 +00:00
{
absolutes = NSCreateMapTable ( NSIntMapKeyCallBacks ,
2002-09-30 16:54:29 +00:00
NSNonOwnedPointerMapValueCallBacks , 0 ) ;
1999-08-25 16:12:36 +00:00
}
}
2002-09-30 16:54:29 +00:00
- ( NSString * ) abbreviationForDate : ( NSDate * ) aDate
{
return name ;
}
2001-01-30 12:05:02 +00:00
- ( void ) dealloc
{
2003-02-13 13:31:59 +00:00
if ( offset ! = uninitialisedOffset )
{
if ( zone_mutex ! = nil )
[ zone_mutex lock ] ;
2006-01-11 09:32:13 +00:00
NSMapRemove ( absolutes , ( void * ) ( uintptr_t ) offset ) ;
2003-02-13 13:31:59 +00:00
if ( zone_mutex ! = nil )
[ zone_mutex unlock ] ;
}
2001-01-30 12:05:02 +00:00
RELEASE ( name ) ;
RELEASE ( detail ) ;
[ super dealloc ] ;
}
- ( void ) encodeWithCoder : ( NSCoder * ) aCoder
{
[ aCoder encodeObject : name ] ;
}
2009-02-23 20:42:32 +00:00
- ( id ) initWithOffset : ( NSInteger ) anOffset name : ( NSString * ) aName
1999-08-25 16:12:36 +00:00
{
2002-10-01 10:25:40 +00:00
GSAbsTimeZone * z ;
int extra ;
int sign = anOffset >= 0 ? 1 : -1 ;
2003-02-13 13:31:59 +00:00
/ *
* Set the uninitialised offset so that dealloc before full
* initialisation won ' t remove the timezeone for offset 0 from cache .
* /
offset = uninitialisedOffset ;
2002-10-01 10:25:40 +00:00
/ *
* Round the offset to the nearest minute , ( for MacOS - X compatibility )
* and ensure it is no more than 18 hours .
* /
anOffset * = sign ;
extra = anOffset % 60 ;
if ( extra < 30 )
{
anOffset - = extra ;
}
else
{
anOffset + = 60 - extra ;
}
if ( anOffset > 64800 )
{
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-10-01 10:25:40 +00:00
return nil ;
}
anOffset * = sign ;
1999-08-25 16:12:36 +00:00
2001-01-30 20:47:05 +00:00
if ( zone_mutex ! = nil )
2002-09-30 16:54:29 +00:00
{
[ zone_mutex lock ] ;
}
2006-01-11 09:32:13 +00:00
z = ( GSAbsTimeZone * ) NSMapGet ( absolutes , ( void * ) ( uintptr_t ) anOffset ) ;
2002-09-30 16:54:29 +00:00
if ( z ! = nil )
1999-08-25 16:12:36 +00:00
{
1999-09-28 19:35:09 +00:00
IF_NO _GC ( RETAIN ( z ) ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
1999-08-25 16:12:36 +00:00
}
else
{
2006-02-27 09:35:19 +00:00
if ( aName = = nil )
2002-10-01 10:25:40 +00:00
{
2006-02-27 09:35:19 +00:00
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 ] initWithUTF8String : buf ] ;
}
else
{
/ *
* Should never happen now we round to the minute
* for MacOS - X compatibnility .
* /
name = [ [ NSString alloc ] initWithFormat : @ "NSAbsoluteTimeZone:%d" ,
anOffset ] ;
}
2002-10-01 10:25:40 +00:00
}
else
{
2006-02-27 09:35:19 +00:00
name = [ aName copy ] ;
2002-10-01 10:25:40 +00:00
}
detail = [ [ GSAbsTimeZoneDetail alloc ] initWithTimeZone : self ] ;
2002-09-30 16:54:29 +00:00
offset = anOffset ;
z = self ;
2006-01-11 09:32:13 +00:00
NSMapInsert ( absolutes , ( void * ) ( uintptr_t ) anOffset , ( void * ) z ) ;
2002-09-30 16:54:29 +00:00
[ zoneDictionary setObject : self forKey : ( NSString * ) name ] ;
1999-08-25 16:12:36 +00:00
}
2001-01-30 20:47:05 +00:00
if ( zone_mutex ! = nil )
2002-09-30 16:54:29 +00:00
{
[ zone_mutex unlock ] ;
}
1999-08-25 16:12:36 +00:00
return z ;
1997-10-17 13:35:52 +00:00
}
1997-11-03 14:30:13 +00:00
2002-09-30 16:54:29 +00:00
- ( BOOL ) isDaylightSavingTimeZoneForDate : ( NSDate * ) aDate
{
return NO ;
}
2001-01-30 12:05:02 +00:00
- ( NSString * ) name
1995-08-23 16:13:42 +00:00
{
2001-01-30 12:05:02 +00:00
return name ;
1995-08-23 16:13:42 +00:00
}
1997-11-03 14:30:13 +00:00
2009-02-23 20:42:32 +00:00
- ( NSInteger ) secondsFromGMTForDate : ( NSDate * ) aDate
2002-09-30 16:54:29 +00:00
{
return offset ;
}
2005-03-07 11:19:34 +00:00
- ( NSArray * ) timeZoneDetailArray
1997-10-17 13:35:52 +00:00
{
2005-03-07 11:19:34 +00:00
return [ NSArray arrayWithObject : detail ] ;
1997-09-01 21:59:51 +00:00
}
2005-02-22 11:22:44 +00:00
1999-08-25 16:12:36 +00:00
- ( NSTimeZoneDetail * ) timeZoneDetailForDate : ( NSDate * ) date
1997-10-17 13:35:52 +00:00
{
return detail ;
1995-08-23 16:13:42 +00:00
}
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
- ( NSString * ) timeZoneName
{
return name ;
}
1997-09-01 21:59:51 +00:00
@ end
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
@ implementation GSTimeZoneDetail
2005-02-22 11:22:44 +00:00
1999-08-25 16:12:36 +00:00
- ( void ) dealloc
1997-10-17 13:35:52 +00:00
{
1999-05-27 09:52:49 +00:00
RELEASE ( timeZone ) ;
1997-09-01 21:59:51 +00:00
[ super dealloc ] ;
}
1997-11-03 14:30:13 +00:00
2000-06-30 11:59:59 +00:00
- ( id ) initWithCoder : ( NSCoder * ) aDecoder
1995-08-23 16:13:42 +00:00
{
1998-09-02 12:34:38 +00:00
[ aDecoder decodeValueOfObjCType : @ encode ( id ) at : & abbrev ] ;
1997-09-01 21:59:51 +00:00
[ aDecoder decodeValueOfObjCType : @ encode ( int ) at : & offset ] ;
[ aDecoder decodeValueOfObjCType : @ encode ( BOOL ) at : & is_dst ] ;
return self ;
1997-10-17 13:35:52 +00:00
}
2001-01-30 12:05:02 +00:00
- ( id ) initWithTimeZone : ( NSTimeZone * ) aZone
withAbbrev : ( NSString * ) anAbbrev
2009-02-23 20:42:32 +00:00
withOffset : ( NSInteger ) anOffset
2001-01-30 12:05:02 +00:00
withDST : ( BOOL ) isDST
{
timeZone = RETAIN ( aZone ) ;
2002-09-30 16:54:29 +00:00
abbrev = anAbbrev ; // NB . Depend on this being retained in aZone
2001-01-30 12:05:02 +00:00
offset = anOffset ;
is_dst = isDST ;
return self ;
}
2005-02-22 11:22:44 +00:00
2001-01-30 12:05:02 +00:00
- ( BOOL ) isDaylightSavingTimeZone
1997-10-24 16:58:20 +00:00
{
2001-01-30 12:05:02 +00:00
return is_dst ;
1997-10-24 16:58:20 +00:00
}
2005-02-22 11:22:44 +00:00
2001-01-30 12:05:02 +00:00
- ( NSString * ) name
1997-10-24 16:58:20 +00:00
{
2001-01-30 12:05:02 +00:00
return [ timeZone name ] ;
1997-10-24 16:58:20 +00:00
}
2005-02-22 11:22:44 +00:00
2001-01-30 12:05:02 +00:00
- ( NSString * ) timeZoneAbbreviation
{
return abbrev ;
}
2005-02-22 11:22:44 +00:00
1999-08-25 16:12:36 +00:00
- ( NSArray * ) timeZoneDetailArray
1997-10-24 16:58:20 +00:00
{
return [ timeZone timeZoneDetailArray ] ;
}
2001-01-30 12:05:02 +00:00
- ( NSTimeZoneDetail * ) timeZoneDetailForDate : ( NSDate * ) date
1997-10-17 13:35:52 +00:00
{
2001-01-30 12:05:02 +00:00
return [ timeZone timeZoneDetailForDate : date ] ;
1995-08-23 16:13:42 +00:00
}
2001-01-30 12:05:02 +00:00
2009-02-23 20:42:32 +00:00
- ( NSInteger ) timeZoneSecondsFromGMT
1995-08-23 16:13:42 +00:00
{
2001-01-30 12:05:02 +00:00
return offset ;
1995-08-23 16:13:42 +00:00
}
2001-01-30 12:05:02 +00:00
2009-02-23 20:42:32 +00:00
- ( NSInteger ) timeZoneSecondsFromGMTForDate : ( NSDate * ) aDate
1997-09-01 21:59:51 +00:00
{
return offset ;
1997-10-17 13:35:52 +00:00
}
2005-02-22 11:22:44 +00:00
1995-08-23 16:13:42 +00:00
@ end
2002-10-01 10:25:40 +00:00
@ implementation GSAbsTimeZoneDetail
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
- ( NSString * ) abbreviation
{
return zone -> name ;
}
- ( NSString * ) abbreviationForDate : ( NSDate * ) aDate
{
return zone -> name ;
}
- ( void ) dealloc
{
RELEASE ( zone ) ;
[ super dealloc ] ;
}
- ( id ) initWithTimeZone : ( GSAbsTimeZone * ) aZone
{
zone = RETAIN ( aZone ) ;
return self ;
}
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
- ( BOOL ) isDaylightSavingTimeZone
{
return NO ;
}
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
- ( BOOL ) isDaylightSavingTimeZoneForDate : ( NSDate * ) aDate
{
return NO ;
}
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
- ( NSString * ) name
{
return zone -> name ;
}
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
- ( NSString * ) timeZoneAbbreviation
{
return zone -> name ;
}
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
- ( NSArray * ) timeZoneDetailArray
{
return [ zone timeZoneDetailArray ] ;
}
- ( NSTimeZoneDetail * ) timeZoneDetailForDate : ( NSDate * ) date
{
return self ;
}
2009-02-23 20:42:32 +00:00
- ( NSInteger ) timeZoneSecondsFromGMT
2002-10-01 10:25:40 +00:00
{
return zone -> offset ;
}
2009-02-23 20:42:32 +00:00
- ( NSInteger ) timeZoneSecondsFromGMTForDate : ( NSDate * ) aDate
2002-10-01 10:25:40 +00:00
{
return zone -> offset ;
}
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
@ end
2002-08-20 10:22:05 +00:00
/ * *
* < p >
2004-10-11 03:08:54 +00:00
* The local time zone is obtained from , in order of preference : < br / >
2004-02-29 21:17:40 +00:00
* 1 ) the user defaults database : NSGlobalDomain "Local Time Zone" < br / >
* 2 ) the GNUSTEP_TZ environment variable < br / >
* 3 ) the file "localtime" in System / Library / Libraries / Resources / NSTimeZone < br / >
* 4 ) the TZ environment variable < br / >
2010-06-01 19:30:28 +00:00
* 5 ) tzset and tznam on platforms which have it < br / >
* 6 ) The system zone settings ( typically in / etc / localtime ) < br / >
2004-10-11 03:08:54 +00:00
* 7 ) Windows registry , on Win32 systems < br / >
* 8 ) or the fallback time zone ( which is UTC ) < br / >
2004-02-29 21:17:40 +00:00
* < / p >
* < p > If the GNUstep time zone datafiles become too out of date , one
2002-08-20 10:22:05 +00:00
* can download an updated database from < uref
* url = "ftp://elsie.nci.nih.gov/pub/" > ftp : // elsie . nci . nih . gov / pub / < / uref >
* and compile it as specified in the README file in the
* NSTimeZones directory .
2002-10-01 10:25:40 +00:00
* < / p >
* < p > Time zone names in NSDates should be GMT , MET etc . not
2002-08-20 10:22:05 +00:00
* Europe / Berlin , America / Washington etc .
2002-10-01 10:25:40 +00:00
* < / p >
2002-10-04 12:32:27 +00:00
* < p > The problem with this is that various time zones may use the
2002-08-20 10:22:05 +00:00
* same abbreviation ( e . g . Australia / Brisbane and
* America / New_York both use EST ) , and some time zones
* may have different rules for daylight saving time even if the
* abbreviation and offsets from UTC are the same .
2002-10-01 10:25:40 +00:00
* < / p >
* < p > The problems with depending on the OS for providing time zone
2004-10-11 03:08:54 +00:00
* info are that time zone names may vary
2002-08-20 10:22:05 +00:00
* wildly between OSes ( this could be a big problem when
* archiving is used between different systems ) .
* < / p >
2004-02-29 21:17:40 +00:00
* < p > Win32 : Time zone names read from the registry are different
* from other GNUstep installations . Be careful when moving data
* between platforms in this case .
* < / p >
2002-08-20 10:22:05 +00:00
* /
1997-09-01 21:59:51 +00:00
@ implementation NSTimeZone
1995-08-23 16:13:42 +00:00
2004-02-29 21:17:40 +00:00
/ * *
2004-12-21 23:20:32 +00:00
* Returns a dictionary containing time zone abbreviations and their
* corresponding time zone names . More than one time zone may be associated
* with a single abbreviation . In this case , the dictionary contains only
2005-02-22 11:22:44 +00:00
* one ( usually the most common ) time zone name for the abbreviation .
2004-02-29 21:17:40 +00:00
* /
2001-01-30 12:05:02 +00:00
+ ( NSDictionary * ) abbreviationDictionary
{
2004-12-21 23:20:32 +00:00
if ( abbreviationDictionary ! = nil )
2006-02-21 15:44:04 +00:00
{
return abbreviationDictionary ;
}
if ( zone_mutex ! = nil )
{
[ zone_mutex lock ] ;
}
if ( abbreviationDictionary = = nil )
{
CREATE_AUTORELEASE _POOL ( pool ) ;
NSString * path ;
path = _time _zone _path ( ABBREV_DICT , @ "plist" ) ;
if ( path ! = nil )
{
/ *
* Fast mechanism . . . load prebuilt data from file so we don ' t
* need to load in all time zones .
* /
abbreviationDictionary
= RETAIN ( [ [ NSString stringWithContentsOfFile : path ] propertyList ] ) ;
}
if ( abbreviationDictionary = = nil )
{
NSMutableDictionary * md ;
NSString * name ;
NSEnumerator * names ;
2004-12-21 23:20:32 +00:00
2006-02-21 15:44:04 +00:00
/ *
* Slow fallback . . . load all time zones and generate
* abbreviation dictionary from them .
* /
md = [ [ NSMutableDictionary alloc ] init ] ;
names = [ [ NSTimeZone knownTimeZoneNames ] objectEnumerator ] ;
while ( ( name = [ names nextObject ] ) ! = nil )
{
NSTimeZone * zone ;
if ( ( zone = [ NSTimeZone timeZoneWithName : name ] ) )
{
NSEnumerator * details ;
NSTimeZoneDetail * detail ;
details = [ [ zone timeZoneDetailArray ] objectEnumerator ] ;
while ( ( detail = [ details nextObject ] ) ! = nil )
{
2006-02-21 17:13:19 +00:00
[ md setObject : name
forKey : [ detail timeZoneAbbreviation ] ] ;
2006-02-21 15:44:04 +00:00
}
}
}
[ md makeImmutableCopyOnFail : NO ] ;
abbreviationDictionary = md ;
}
RELEASE ( pool ) ;
}
if ( zone_mutex ! = nil )
2004-12-21 23:20:32 +00:00
{
2006-02-21 15:44:04 +00:00
[ zone_mutex unlock ] ;
2004-12-21 23:20:32 +00:00
}
2006-02-21 15:44:04 +00:00
return abbreviationDictionary ;
2001-01-30 12:05:02 +00:00
}
2004-02-29 21:17:40 +00:00
/ * *
2004-12-21 23:20:32 +00:00
* Returns a dictionary that maps abbreviations to the array
* containing all the time zone names that use the abbreviation .
2004-02-29 21:17:40 +00:00
* /
2001-01-30 12:05:02 +00:00
+ ( NSDictionary * ) abbreviationMap
{
2004-02-29 21:17:40 +00:00
/ * 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 . * /
2004-12-21 23:20:32 +00:00
if ( abbreviationMap ! = nil )
2006-02-21 15:44:04 +00:00
{
return abbreviationMap ;
}
if ( zone_mutex ! = nil )
{
[ zone_mutex lock ] ;
}
if ( abbreviationMap = = nil )
{
CREATE_AUTORELEASE _POOL ( pool ) ;
NSMutableDictionary * md ;
NSMutableArray * ma ;
NSString * the_name ;
NSString * the_abbrev ;
FILE * file ;
char abbrev [ 80 ] ;
char name [ 80 ] ;
NSString * path ;
2001-01-30 12:05:02 +00:00
2006-02-21 15:44:04 +00:00
/ *
* Read dictionary from file . . . fast mechanism because we don ' t have
* to create all timezoneas and parse all their data files .
* /
md = [ NSMutableDictionary dictionaryWithCapacity : 100 ] ;
path = _time _zone _path ( ABBREV_MAP , nil ) ;
if ( path ! = nil )
{
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2006-02-21 15:44:04 +00:00
unichar mode [ 3 ] ;
mode [ 0 ] = ' r ' ;
mode [ 1 ] = ' b ' ;
mode [ 2 ] = ' \ 0 ' ;
file = _wfopen ( ( const unichar * ) [ path fileSystemRepresentation ] , mode ) ;
2001-01-30 12:05:02 +00:00
# else
2006-02-21 15:44:04 +00:00
file = fopen ( [ path fileSystemRepresentation ] , "r" ) ;
2001-01-30 12:05:02 +00:00
# endif
2006-02-21 15:44:04 +00:00
if ( file = = NULL )
{
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
}
[ NSException
raise : NSInternalInconsistencyException
format : @ "Failed to open time zone abbreviation map." ] ;
}
while ( fscanf ( file , "%79s %79s" , abbrev , name ) = = 2 )
{
the_name = [ [ NSString alloc ] initWithUTF8String : name ] ;
the_abbrev = [ [ NSString alloc ] initWithUTF8String : abbrev ] ;
ma = [ md objectForKey : the_abbrev ] ;
if ( ma = = nil )
{
ma = [ [ NSMutableArray alloc ] initWithCapacity : 1 ] ;
[ md setObject : ma forKey : the_abbrev ] ;
RELEASE ( ma ) ;
}
RELEASE ( the_abbrev ) ;
2006-02-21 17:13:19 +00:00
if ( [ ma containsObject : the_name ] = = NO )
{
[ ma addObject : the_name ] ;
}
2006-02-21 15:44:04 +00:00
RELEASE ( the_name ) ;
}
fclose ( file ) ;
}
else
{
NSString * name ;
2006-02-21 17:13:19 +00:00
NSEnumerator * names ;
2006-02-21 15:44:04 +00:00
/ *
* Slow fallback mechanism . . . go through all time names
* so we load all the time zone data and generate the info
* we need from it .
* /
2006-02-21 17:13:19 +00:00
names = [ [ NSTimeZone knownTimeZoneNames ] objectEnumerator ] ;
while ( ( name = [ names nextObject ] ) ! = nil )
2006-02-21 15:44:04 +00:00
{
2006-02-21 17:13:19 +00:00
NSTimeZone * zone ;
2001-01-30 12:05:02 +00:00
2006-02-21 17:13:19 +00:00
if ( ( zone = [ NSTimeZone timeZoneWithName : name ] ) ! = nil )
{
NSEnumerator * details ;
NSTimeZoneDetail * detail ;
details = [ [ zone timeZoneDetailArray ] objectEnumerator ] ;
while ( ( detail = [ details nextObject ] ) ! = nil )
2006-02-21 15:44:04 +00:00
{
2006-02-21 17:13:19 +00:00
the_abbrev = [ detail timeZoneAbbreviation ] ;
ma = [ md objectForKey : the_abbrev ] ;
if ( ma = = nil )
2006-02-21 15:44:04 +00:00
{
2006-02-21 17:13:19 +00:00
ma = [ [ NSMutableArray alloc ] initWithCapacity : 1 ] ;
[ md setObject : ma forKey : the_abbrev ] ;
RELEASE ( ma ) ;
}
if ( [ ma containsObject : name ] = = NO )
{
[ ma addObject : name ] ;
2006-02-21 15:44:04 +00:00
}
}
}
}
}
/ * Special case : Add the system time zone if
* it doesn ' t exist in the map * /
the_abbrev = [ systemTimeZone abbreviation ] ;
ma = [ md objectForKey : the_abbrev ] ;
if ( ma = = nil )
{
ma = [ NSMutableArray new ] ;
[ md setObject : ma forKey : the_abbrev ] ;
RELEASE ( ma ) ;
}
the_name = [ systemTimeZone timeZoneName ] ;
if ( [ ma containsObject : the_name ] = = NO )
2001-01-30 12:05:02 +00:00
{
2006-02-21 15:44:04 +00:00
[ ma addObject : the_name ] ;
2001-01-30 12:05:02 +00:00
}
2006-02-21 15:44:04 +00:00
[ md makeImmutableCopyOnFail : NO ] ;
abbreviationMap = RETAIN ( md ) ;
RELEASE ( pool ) ;
}
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
2001-01-30 12:05:02 +00:00
}
2004-10-11 03:08:54 +00:00
2004-12-21 23:20:32 +00:00
return abbreviationMap ;
2001-01-30 12:05:02 +00:00
}
2004-11-05 03:47:03 +00:00
/ * *
* Returns an array of all known time zone names .
* /
+ ( NSArray * ) knownTimeZoneNames
{
static NSArray * namesArray = nil ;
/ * We create the array only when we need it to reduce overhead . * /
if ( namesArray ! = nil )
2006-02-21 15:44:04 +00:00
{
return namesArray ;
}
2004-11-05 03:47:03 +00:00
2006-02-21 15:44:04 +00:00
if ( zone_mutex ! = nil )
2004-11-05 03:47:03 +00:00
{
2006-02-21 15:44:04 +00:00
[ zone_mutex lock ] ;
2004-11-05 03:47:03 +00:00
}
2006-02-21 15:44:04 +00:00
if ( namesArray = = nil )
{
unsigned i ;
NSMutableArray * ma ;
NSArray * regionsArray ;
ma = [ NSMutableArray new ] ;
regionsArray = [ self timeZoneArray ] ;
2004-11-05 03:47:03 +00:00
2006-02-21 15:44:04 +00:00
for ( i = 0 ; i < [ regionsArray count ] ; i + + )
{
NSArray * names = [ regionsArray objectAtIndex : i ] ;
[ ma addObjectsFromArray : names ] ;
}
[ ma makeImmutableCopyOnFail : NO ] ;
namesArray = ma ;
}
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
}
2004-11-05 03:47:03 +00:00
return namesArray ;
}
2001-01-31 11:29:55 +00:00
+ ( id ) allocWithZone : ( NSZone * ) z
{
if ( self = = NSTimeZoneClass )
{
/ *
* We return a placeholder object that can
* be converted to a real object when its initialisation method
* is called .
* /
if ( z = = NSDefaultMallocZone ( ) || z = = 0 )
{
/ *
* As a special case , we can return a placeholder for a time zone
2006-05-24 08:27:39 +00:00
* in the default zone extremely efficiently .
2001-01-31 11:29:55 +00:00
* /
return defaultPlaceholderTimeZone ;
}
else
{
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 ;
}
}
else
{
return NSAllocateObject ( self , 0 , z ) ;
}
}
2002-09-30 16:54:29 +00:00
/ * *
* Return the default time zone for this process .
* /
2001-01-30 20:47:05 +00:00
+ ( NSTimeZone * ) defaultTimeZone
2001-01-30 12:05:02 +00:00
{
2001-01-30 20:47:05 +00:00
NSTimeZone * zone ;
if ( zone_mutex ! = nil )
2002-09-30 16:54:29 +00:00
{
[ zone_mutex lock ] ;
}
2001-01-30 20:47:05 +00:00
if ( defaultTimeZone = = nil )
{
zone = [ self systemTimeZone ] ;
}
else
{
if ( zone_mutex ! = nil )
2002-09-30 16:54:29 +00:00
{
zone = AUTORELEASE ( RETAIN ( defaultTimeZone ) ) ;
}
2001-01-30 20:47:05 +00:00
else
2002-09-30 16:54:29 +00:00
{
zone = defaultTimeZone ;
}
2001-01-30 20:47:05 +00:00
}
if ( zone_mutex ! = nil )
2002-09-30 16:54:29 +00:00
{
[ zone_mutex unlock ] ;
}
2001-01-30 20:47:05 +00:00
return zone ;
2001-01-30 12:05:02 +00:00
}
1999-08-25 16:12:36 +00:00
+ ( void ) initialize
1997-10-17 13:35:52 +00:00
{
1997-09-01 21:59:51 +00:00
if ( self = = [ NSTimeZone class ] )
{
2001-01-30 12:05:02 +00:00
NSTimeZoneClass = self ;
2001-01-31 11:29:55 +00:00
GSPlaceholderTimeZoneClass = [ GSPlaceholderTimeZone class ] ;
1997-11-03 14:30:13 +00:00
zoneDictionary = [ [ NSMutableDictionary alloc ] init ] ;
1997-09-01 21:59:51 +00:00
2001-01-31 11:29:55 +00:00
/ *
* Set up infrastructure for placeholder timezones .
* /
defaultPlaceholderTimeZone = ( GSPlaceholderTimeZone * )
NSAllocateObject ( GSPlaceholderTimeZoneClass , 0 , NSDefaultMallocZone ( ) ) ;
placeholderMap = NSCreateMapTable ( NSNonOwnedPointerMapKeyCallBacks ,
NSNonRetainedObjectMapValueCallBacks , 0 ) ;
2001-01-30 20:47:05 +00:00
localTimeZone = [ [ NSLocalTimeZone alloc ] init ] ;
2004-02-08 09:42:38 +00:00
zone_mutex = [ GSLazyRecursiveLock new ] ;
2008-06-06 14:47:40 +00:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self
selector : @ selector ( _notified : )
name : NSUserDefaultsDidChangeNotification
object : nil ] ;
2001-01-30 20:47:05 +00:00
}
}
2002-09-30 16:54:29 +00:00
/ * *
* Return a proxy to the default time zone for this process .
* /
2001-01-30 20:47:05 +00:00
+ ( NSTimeZone * ) localTimeZone
{
return localTimeZone ;
}
2002-09-30 16:54:29 +00:00
/ * *
* Destroy the system time zone so that it will be recreated
* next time it is used .
* /
2001-01-30 20:47:05 +00:00
+ ( void ) resetSystemTimeZone
{
if ( zone_mutex ! = nil )
2002-09-30 16:54:29 +00:00
{
[ zone_mutex lock ] ;
}
2001-01-30 20:47:05 +00:00
DESTROY ( systemTimeZone ) ;
if ( zone_mutex ! = nil )
2002-09-30 16:54:29 +00:00
{
[ zone_mutex unlock ] ;
}
2008-06-06 13:57:06 +00:00
[ [ NSNotificationCenter defaultCenter ]
postNotificationName : NSSystemTimeZoneDidChangeNotification
object : nil ] ;
2001-01-30 20:47:05 +00:00
}
2002-09-30 16:54:29 +00:00
/ * *
* Set the default time zone to be used for this process .
* /
2001-01-30 20:47:05 +00:00
+ ( void ) setDefaultTimeZone : ( NSTimeZone * ) aTimeZone
{
2002-09-30 17:14:51 +00:00
if ( aTimeZone ! = defaultTimeZone )
2002-09-30 16:54:29 +00:00
{
2002-09-30 17:14:51 +00:00
/ *
* We can ' t make the localTimeZone the default since that would
* cause recursion . . .
* /
if ( aTimeZone = = localTimeZone )
{
aTimeZone = [ self systemTimeZone ] ;
}
if ( zone_mutex ! = nil )
{
[ zone_mutex lock ] ;
}
ASSIGN ( defaultTimeZone , aTimeZone ) ;
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
}
2002-09-30 16:54:29 +00:00
}
2001-01-30 20:47:05 +00:00
}
2002-09-30 16:54:29 +00:00
/ * *
* Returns the current system time zone for the process .
* /
2001-01-30 20:47:05 +00:00
+ ( NSTimeZone * ) systemTimeZone
{
NSTimeZone * zone = nil ;
if ( zone_mutex ! = nil )
2002-09-30 16:54:29 +00:00
{
[ zone_mutex lock ] ;
}
2001-01-30 20:47:05 +00:00
if ( systemTimeZone = = nil )
{
NSString * localZoneString = nil ;
2010-06-01 19:24:07 +00:00
NSString * localZoneSource = nil ;
2001-01-30 20:47:05 +00:00
/ *
* setup default value in case something goes wrong .
* /
systemTimeZone = RETAIN ( [ NSTimeZoneClass timeZoneForSecondsFromGMT : 0 ] ) ;
2004-02-29 21:17:40 +00:00
/ *
* Try to get timezone from user defaults database
* /
2010-06-02 09:35:26 +00:00
localZoneSource = [ NSString stringWithFormat :
@ "NSUserDefaults: '%@'" , LOCALDBKEY ] ;
1997-09-01 21:59:51 +00:00
localZoneString = [ [ NSUserDefaults standardUserDefaults ]
2000-01-05 14:53:03 +00:00
stringForKey : LOCALDBKEY ] ;
2005-02-22 11:22:44 +00:00
2004-02-29 21:17:40 +00:00
/ *
* Try to get timezone from GNUSTEP_TZ environment variable .
2005-02-22 11:22:44 +00:00
* /
1997-09-01 21:59:51 +00:00
if ( localZoneString = = nil )
2000-01-05 14:53:03 +00:00
{
2010-06-01 19:24:07 +00:00
localZoneSource = _ ( @ "environment variable: 'GNUSTEP_TZ'" ) ;
2000-01-05 14:53:03 +00:00
localZoneString = [ [ [ NSProcessInfo processInfo ]
environment ] objectForKey : @ "GNUSTEP_TZ" ] ;
}
2004-02-29 21:17:40 +00:00
/ *
* Try to get timezone from LOCAL_TIME _FILE .
* /
1997-10-17 13:35:52 +00:00
if ( localZoneString = = nil )
2000-01-05 14:53:03 +00:00
{
2004-12-21 23:20:32 +00:00
NSString * f = _time _zone _path ( LOCAL_TIME _FILE , nil ) ;
2010-06-01 19:24:07 +00:00
localZoneSource = [ NSString stringWithFormat : @ "file: '%@'" , f ] ;
2001-01-30 20:47:05 +00:00
if ( f ! = nil )
2000-01-05 14:53:03 +00:00
{
2001-01-30 20:47:05 +00:00
localZoneString = [ NSString stringWithContentsOfFile : f ] ;
localZoneString = [ localZoneString stringByTrimmingSpaces ] ;
2000-01-05 14:53:03 +00:00
}
}
2004-02-29 21:17:40 +00:00
/ *
2004-10-11 03:08:54 +00:00
* Try to get timezone from standard unix environment variable .
2004-02-29 21:17:40 +00:00
* /
2003-09-04 03:28:14 +00:00
if ( localZoneString = = nil )
{
2010-06-01 19:24:07 +00:00
localZoneSource = _ ( @ "environment variable: 'TZ'" ) ;
2004-10-11 03:08:54 +00:00
localZoneString = [ [ [ NSProcessInfo processInfo ]
environment ] objectForKey : @ "TZ" ] ;
2003-09-04 03:28:14 +00:00
}
2010-06-01 19:30:28 +00:00
# if HAVE_TZSET
/ *
* Try to get timezone from tzset and tzname
* /
if ( localZoneString = = nil )
{
localZoneSource = @ "function: 'tzset()/tzname'" ;
tzset ( ) ;
if ( tzname [ 0 ] ! = NULL && * tzname [ 0 ] ! = ' \ 0 ' )
localZoneString = [ NSString stringWithUTF8String : tzname [ 0 ] ] ;
}
# endif
2004-10-11 03:08:54 +00:00
if ( localZoneString = = nil )
{
/ * Get the zone name from the localtime file , assuming the file
is a symlink to the time zone . Getting the actual data ( which
is easier ) doesn ' t help , since we won ' t know the name itself . * /
2004-10-26 19:08:17 +00:00
# if defined ( HAVE_TZHEAD ) && defined ( TZDEFAULT )
2006-02-21 15:44:04 +00:00
tzdir = RETAIN ( [ NSString stringWithUTF8String : TZDIR ] ) ;
localZoneString = [ NSString stringWithUTF8String : TZDEFAULT ] ;
2010-06-01 19:30:28 +00:00
localZoneSource = [ NSString stringWithFormat :
@ "file (TZDEFAULT): '%@'" , localZoneString ] ;
2004-10-11 03:08:54 +00:00
localZoneString = [ localZoneString stringByResolvingSymlinksInPath ] ;
2003-09-04 03:28:14 +00:00
# else
2004-10-11 03:08:54 +00:00
NSFileManager * dflt = [ NSFileManager defaultManager ] ;
2005-11-06 07:13:33 +00:00
2004-10-11 03:08:54 +00:00
if ( [ dflt fileExistsAtPath : SYSTEM_TIME _FILE ] )
{
localZoneString = SYSTEM_TIME _FILE ;
2010-06-01 19:30:28 +00:00
localZoneSource = [ NSString stringWithFormat :
@ "file (SYSTEM_TIME_FILE): '%@'" , localZoneString ] ;
2005-11-06 07:13:33 +00:00
localZoneString
= [ localZoneString stringByResolvingSymlinksInPath ] ;
2004-10-11 03:08:54 +00:00
/ * Guess what tzdir is * /
tzdir = [ localZoneString stringByDeletingLastPathComponent ] ;
while ( [ tzdir length ] > 2
2005-11-06 07:13:33 +00:00
&& [ dflt fileExistsAtPath :
[ tzdir stringByAppendingPathComponent : @ "GMT" ] ] = = NO )
{
tzdir = [ tzdir stringByDeletingLastPathComponent ] ;
}
2009-01-12 12:48:46 +00:00
if ( [ tzdir length ] <= 2 )
2004-10-11 03:08:54 +00:00
{
localZoneString = tzdir = nil ;
}
2009-01-12 12:48:46 +00:00
# if ! GS_WITH _GC
else
{
[ tzdir retain ] ;
}
# endif
2004-10-11 03:08:54 +00:00
}
# endif
2005-02-22 11:22:44 +00:00
if ( localZoneString ! = nil && [ localZoneString hasPrefix : tzdir ] )
2004-10-11 03:08:54 +00:00
{
/ * This must be the time zone name * /
2005-11-06 07:13:33 +00:00
localZoneString = AUTORELEASE ( [ localZoneString mutableCopy ] ) ;
2010-02-14 10:48:10 +00:00
[ ( NSMutableString * ) localZoneString deleteCharactersInRange :
NSMakeRange ( 0 , [ tzdir length ] ) ] ;
while ( [ localZoneString hasPrefix : @ "/" ] )
2004-10-11 03:08:54 +00:00
{
2010-02-14 10:48:10 +00:00
[ ( NSMutableString * ) localZoneString deleteCharactersInRange :
NSMakeRange ( 0 , 1 ) ] ;
2004-10-11 03:08:54 +00:00
}
}
else
2005-11-06 07:13:33 +00:00
{
localZoneString = nil ;
}
2004-10-11 03:08:54 +00:00
}
2004-02-29 21:17:40 +00:00
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2004-02-29 21:17:40 +00:00
/ *
2007-02-14 11:38:52 +00:00
* Try to get timezone from windows system call .
2004-02-29 21:17:40 +00:00
* /
{
2007-02-14 11:38:52 +00:00
TIME_ZONE _INFORMATION tz ;
DWORD DST = GetTimeZoneInformation ( & tz ) ;
2010-06-01 19:24:07 +00:00
localZoneSource = @ "function: 'GetTimeZoneInformation()'" ;
2007-02-14 11:38:52 +00:00
if ( DST = = TIME_ZONE _ID _DAYLIGHT )
{
localZoneString = [ NSString stringWithCharacters : tz . DaylightName
length : wcslen ( tz . DaylightName ) ] ;
}
else
{
localZoneString = [ NSString stringWithCharacters : tz . StandardName
length : wcslen ( tz . StandardName ) ] ;
}
2004-02-29 21:17:40 +00:00
}
2005-02-22 11:22:44 +00:00
# endif
1997-09-01 21:59:51 +00:00
if ( localZoneString ! = nil )
2000-01-05 14:53:03 +00:00
{
2004-10-11 03:08:54 +00:00
NSDebugLLog ( @ "NSTimeZone" , @ "Using zone %@" , localZoneString ) ;
2001-01-31 11:29:55 +00:00
zone = [ defaultPlaceholderTimeZone initWithName : localZoneString ] ;
2010-06-01 19:24:07 +00:00
if ( zone = = nil )
{
NSLog ( @ "Unable to create time zone for name: '%@' (source '%@')." ,
localZoneString , localZoneSource ) ;
2010-06-02 09:35:26 +00:00
if ( [ localZoneSource hasPrefix : @ "file" ]
|| [ localZoneSource hasPrefix : @ "function" ] )
{
NSLog ( @ "It seems that your operating system does not have a valid timzone names configured ... please correct that or override by setting the '%@' user default to a timezone name (such as 'Europe/London' or 'America/Chicago')" , LOCALDBKEY ) ;
}
2010-06-01 19:24:07 +00:00
}
2000-01-05 14:53:03 +00:00
}
1997-09-01 21:59:51 +00:00
else
2000-01-05 14:53:03 +00:00
{
NSLog ( @ "No local time zone specified." ) ;
}
/ *
* If local time zone fails to allocate , then allocate something
* that is sure to succeed ( unless we run out of memory , of
* course ) .
* /
2001-01-30 20:47:05 +00:00
if ( zone = = nil )
1997-10-24 16:58:20 +00:00
{
1997-11-03 14:30:13 +00:00
NSLog ( @ "Using time zone with absolute offset 0." ) ;
2001-01-30 20:47:05 +00:00
zone = systemTimeZone ;
1997-10-24 16:58:20 +00:00
}
2001-01-30 20:47:05 +00:00
ASSIGN ( systemTimeZone , zone ) ;
1997-09-01 21:59:51 +00:00
}
2001-01-30 20:47:05 +00:00
if ( zone_mutex ! = nil )
{
zone = AUTORELEASE ( RETAIN ( systemTimeZone ) ) ;
[ zone_mutex unlock ] ;
}
else
{
zone = systemTimeZone ;
}
return zone ;
1995-08-23 16:13:42 +00:00
}
2004-02-29 21:17:40 +00:00
/ * *
* Returns an array of all the known regions . < br / >
* There are 24 elements , of course , one for each time zone .
* Each element contains an array of NSStrings which are
* the region names .
* /
2001-01-30 12:05:02 +00:00
+ ( NSArray * ) timeZoneArray
1995-08-23 16:13:42 +00:00
{
2001-01-30 12:05:02 +00:00
static NSArray * regionsArray = nil ;
2004-02-29 21:17:40 +00:00
/ * We create the array only when we need it to reduce overhead . * /
2001-01-30 12:05:02 +00:00
if ( regionsArray ! = nil )
2006-02-21 15:44:04 +00:00
{
return regionsArray ;
}
if ( zone_mutex ! = nil )
{
[ zone_mutex lock ] ;
}
if ( regionsArray = = nil )
{
CREATE_AUTORELEASE _POOL ( pool ) ;
int index , i ;
char name [ 80 ] ;
FILE * fp ;
NSMutableArray * temp_array [ 24 ] ;
NSString * path ;
for ( i = 0 ; i < 24 ; i + + )
{
temp_array [ i ] = [ NSMutableArray array ] ;
}
2001-01-30 12:05:02 +00:00
2006-02-21 15:44:04 +00:00
path = _time _zone _path ( REGIONS_FILE , nil ) ;
if ( path ! = nil )
{
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2006-02-21 15:44:04 +00:00
unichar mode [ 3 ] ;
mode [ 0 ] = ' r ' ;
mode [ 1 ] = ' b ' ;
mode [ 2 ] = ' \ 0 ' ;
fp = _wfopen ( ( const unichar * ) [ path fileSystemRepresentation ] , mode ) ;
2001-01-30 12:05:02 +00:00
# else
2006-02-21 15:44:04 +00:00
fp = fopen ( [ path fileSystemRepresentation ] , "r" ) ;
2001-01-30 12:05:02 +00:00
# endif
2006-02-21 15:44:04 +00:00
if ( fp = = NULL )
{
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
}
[ NSException
raise : NSInternalInconsistencyException
format : @ "Failed to open time zone regions array file." ] ;
}
while ( fscanf ( fp , "%d %s" , & index , name ) = = 2 )
{
[ temp_array [ index ]
addObject : [ NSString stringWithUTF8String : name ] ] ;
}
fclose ( fp ) ;
}
else
{
2008-06-06 14:47:40 +00:00
NSString * zonedir = [ NSTimeZone _getTimeZoneFile : @ "WET" ] ;
2006-02-21 15:44:04 +00:00
2006-02-21 17:13:19 +00:00
if ( tzdir ! = nil )
2006-02-21 15:44:04 +00:00
{
2006-02-21 17:13:19 +00:00
NSFileManager * mgr = [ NSFileManager defaultManager ] ;
2006-02-21 15:44:04 +00:00
NSDirectoryEnumerator * enumerator ;
NSString * name ;
2006-02-21 17:13:19 +00:00
zonedir = [ zonedir stringByDeletingLastPathComponent ] ;
2006-02-21 15:44:04 +00:00
enumerator = [ mgr enumeratorAtPath : zonedir ] ;
while ( ( name = [ enumerator nextObject ] ) ! = nil )
{
NSTimeZone * zone = nil ;
BOOL isDir ;
2006-02-21 17:13:19 +00:00
path = [ zonedir stringByAppendingPathComponent : name ] ;
2006-02-21 15:44:04 +00:00
if ( [ mgr fileExistsAtPath : path isDirectory : & isDir ]
2007-06-15 22:00:58 +00:00
&& isDir = = NO
&& [ [ path pathExtension ] isEqual : @ "tab" ] = = NO )
2006-02-21 15:44:04 +00:00
{
zone = [ zoneDictionary objectForKey : name ] ;
if ( zone = = nil )
{
NSData * data ;
data = [ NSData dataWithContentsOfFile : path ] ;
2007-06-15 22:00:58 +00:00
/ * We should really make sure this is a real
zone file and not something extra that happens
to be in this directory , but initWithName : data :
will do this anyway and log a message if not . * /
2006-02-21 15:44:04 +00:00
zone = [ [ self alloc ] initWithName : name data : data ] ;
2009-01-12 12:48:46 +00:00
IF_NO _GC ( [ zone autorelease ] ; )
2006-02-21 15:44:04 +00:00
}
if ( zone ! = nil )
{
int offset ;
NSArray * details ;
NSTimeZoneDetail * detail ;
NSEnumerator * e ;
details = [ zone timeZoneDetailArray ] ;
e = [ details objectEnumerator ] ;
while ( ( detail = [ e nextObject ] ) ! = nil )
{
if ( [ detail isDaylightSavingTime ] = = NO )
{
break ; // Found a standard time
}
}
if ( detail = = nil && [ details count ] > 0 )
{
// If no standard time
detail = [ details objectAtIndex : 0 ] ;
}
offset = [ detail secondsFromGMT ] ;
if ( offset < 0 )
{
offset = - offset ;
offset % = ( 60 * 60 * 24 ) ;
offset = - offset ;
offset + = ( 60 * 60 * 24 ) ;
}
else
{
offset % = ( 60 * 60 * 24 ) ;
}
offset / = ( 60 * 60 ) ;
[ temp_array [ offset ] addObject : name ] ;
}
}
}
}
}
regionsArray = [ [ NSArray alloc ] initWithObjects : temp_array count : 24 ] ;
RELEASE ( pool ) ;
}
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
}
2001-01-30 12:05:02 +00:00
return regionsArray ;
1995-08-23 16:13:42 +00:00
}
2002-10-01 10:25:40 +00:00
/ * *
* Return a timezone for the specified offset from GMT . < br / >
* The timezone returned does < em > not < / em > use daylight savings time .
* The actual timezone returned has an offset rounded to the nearest
* minute . < br / >
* Time zones with an offset of more than + / - 18 hours are disallowed ,
* and nil is returned .
* /
2009-02-23 20:42:32 +00:00
+ ( NSTimeZone * ) timeZoneForSecondsFromGMT : ( NSInteger ) seconds
1995-08-23 16:13:42 +00:00
{
2002-09-30 16:54:29 +00:00
NSTimeZone * zone ;
2006-02-27 09:35:19 +00:00
zone = [ [ GSAbsTimeZone alloc ] initWithOffset : seconds name : nil ] ;
2002-09-30 16:54:29 +00:00
return AUTORELEASE ( zone ) ;
1995-08-23 16:13:42 +00:00
}
2002-09-30 16:54:29 +00:00
/ * *
2005-11-06 13:53:40 +00:00
* Returns a timezone for the specified abbreviation . The same abbreviations
2004-02-29 21:17:40 +00:00
* are used in different regions so this isn ' t particularly useful . < br / >
* Calls NSTimeZone - abbreviation dictionary an so uses a lot of memory .
2002-09-30 16:54:29 +00:00
* /
2001-01-30 20:47:05 +00:00
+ ( NSTimeZone * ) timeZoneWithAbbreviation : ( NSString * ) abbreviation
1995-08-23 16:13:42 +00:00
{
2001-01-30 20:47:05 +00:00
NSTimeZone * zone ;
2006-02-21 17:13:19 +00:00
NSString * name ;
1997-09-01 21:59:51 +00:00
2006-02-21 17:13:19 +00:00
name = [ [ self abbreviationDictionary ] objectForKey : abbreviation ] ;
if ( name = = nil )
{
zone = nil ;
}
else
{
zone = [ self timeZoneWithName : name data : nil ] ;
}
2001-01-30 20:47:05 +00:00
return zone ;
1995-08-23 16:13:42 +00:00
}
2002-09-30 16:54:29 +00:00
/ * *
* Returns a timezone for the specified name .
* /
1999-08-25 16:12:36 +00:00
+ ( NSTimeZone * ) timeZoneWithName : ( NSString * ) aTimeZoneName
1995-08-23 16:13:42 +00:00
{
2001-01-31 11:29:55 +00:00
NSTimeZone * zone ;
1999-08-25 16:12:36 +00:00
2002-09-30 17:14:51 +00:00
zone = [ defaultPlaceholderTimeZone initWithName : aTimeZoneName data : nil ] ;
2001-01-31 11:29:55 +00:00
return AUTORELEASE ( zone ) ;
1995-08-23 16:13:42 +00:00
}
2002-09-30 16:54:29 +00:00
/ * *
2004-02-29 21:17:40 +00:00
* Returns a timezone for aTimeZoneName , created from the supplied
* time zone data . Data must be in TZ format as per the Olson database .
2002-09-30 16:54:29 +00:00
* /
2004-03-28 11:13:36 +00:00
+ ( NSTimeZone * ) timeZoneWithName : ( NSString * ) name data : ( NSData * ) data
2001-01-30 20:47:05 +00:00
{
2002-09-30 17:14:51 +00:00
NSTimeZone * zone ;
2004-03-28 11:13:36 +00:00
zone = [ defaultPlaceholderTimeZone initWithName : name data : data ] ;
2002-09-30 17:14:51 +00:00
return AUTORELEASE ( zone ) ;
2001-01-30 20:47:05 +00:00
}
2001-01-30 12:05:02 +00:00
2002-09-30 16:54:29 +00:00
/ * *
* Returns the abbreviation for this timezone now .
* Invokes - abbreviationForDate :
* /
2001-01-30 12:05:02 +00:00
- ( NSString * ) abbreviation
1995-08-23 16:13:42 +00:00
{
2001-01-30 12:05:02 +00:00
return [ self abbreviationForDate : [ NSDate date ] ] ;
1995-08-23 16:13:42 +00:00
}
2002-09-30 16:54:29 +00:00
/ * *
* Returns the abbreviation for this timezone at aDate . This may differ
* depending on whether daylight savings time is in effect or not .
* /
- ( NSString * ) abbreviationForDate : ( NSDate * ) aDate
1995-08-23 16:13:42 +00:00
{
2001-01-30 12:05:02 +00:00
NSTimeZoneDetail * detail ;
2002-09-30 16:54:29 +00:00
NSString * abbr ;
detail = [ self timeZoneDetailForDate : aDate ] ;
abbr = [ detail timeZoneAbbreviation ] ;
2001-01-30 12:05:02 +00:00
2002-09-30 16:54:29 +00:00
return abbr ;
1995-08-23 16:13:42 +00:00
}
2004-02-29 21:17:40 +00:00
/ * *
* Returns the Class for this object
* /
2001-01-30 12:05:02 +00:00
- ( Class ) classForCoder
1995-08-23 16:13:42 +00:00
{
2001-01-30 12:05:02 +00:00
return NSTimeZoneClass ;
1995-08-23 16:13:42 +00:00
}
2001-01-30 12:05:02 +00:00
- ( id ) copyWithZone : ( NSZone * ) z
1995-08-23 16:13:42 +00:00
{
2001-01-30 12:05:02 +00:00
return RETAIN ( self ) ;
}
1997-09-01 21:59:51 +00:00
2002-10-01 10:25:40 +00:00
/ * *
* Returns the data with which the receiver was initialised .
* /
- ( NSData * ) data
{
return nil ;
}
2004-02-29 21:17:40 +00:00
/ * *
* Returns the name of this object .
* /
2001-01-30 12:05:02 +00:00
- ( NSString * ) description
{
return [ self name ] ;
}
1997-09-01 21:59:51 +00:00
2001-01-30 12:05:02 +00:00
- ( void ) encodeWithCoder : ( NSCoder * ) aCoder
{
2001-01-31 11:29:55 +00:00
[ aCoder encodeObject : [ self name ] ] ;
2001-01-30 12:05:02 +00:00
}
1997-09-01 21:59:51 +00:00
2002-09-30 16:54:29 +00:00
- ( id ) init
{
2002-09-30 17:14:51 +00:00
return [ self initWithName : @ "NSLocalTimeZone" data : nil ] ;
2002-09-30 16:54:29 +00:00
}
2001-01-30 12:05:02 +00:00
- ( id ) initWithCoder : ( NSCoder * ) aDecoder
{
NSString * name ;
2001-01-31 11:29:55 +00:00
name = [ aDecoder decodeObject ] ;
2002-09-30 17:14:51 +00:00
self = [ self initWithName : name data : nil ] ;
2001-01-30 12:05:02 +00:00
return self ;
}
1995-08-23 16:13:42 +00:00
2002-10-01 10:25:40 +00:00
/ * *
* Initialise a timezone with the supplied name . May return a cached
* timezone object rather than the newly created one .
* /
2001-01-30 20:47:05 +00:00
- ( id ) initWithName : ( NSString * ) name
{
2002-09-30 16:54:29 +00:00
return [ self initWithName : name data : nil ] ;
2001-01-30 20:47:05 +00:00
}
2002-10-01 10:25:40 +00:00
/ * *
* Initialises a time zone object using the supplied data object . < br / >
* This method is intended for internal use by the NSTimeZone
* class cluster .
* Don ' t use it . . . use - initWithName : instead .
* /
2001-01-30 20:47:05 +00:00
- ( id ) initWithName : ( NSString * ) name data : ( NSData * ) data
{
[ self notImplemented : _cmd ] ;
return nil ;
}
2002-09-30 16:54:29 +00:00
/ * *
* Returns a boolean indicating whether daylight savings time is in
* effect now . Invokes - isDaylightSavingTimeForDate :
* /
2001-01-30 12:05:02 +00:00
- ( BOOL ) isDaylightSavingTime
{
return [ self isDaylightSavingTimeForDate : [ NSDate date ] ] ;
1997-10-17 13:35:52 +00:00
}
1997-11-03 14:30:13 +00:00
2002-09-30 16:54:29 +00:00
/ * *
* Returns a boolean indicating whether daylight savings time is in
* effect for this time zone at aDate .
* /
2001-01-30 12:05:02 +00:00
- ( BOOL ) isDaylightSavingTimeForDate : ( NSDate * ) aDate
1997-10-17 13:35:52 +00:00
{
2001-01-30 12:05:02 +00:00
NSTimeZoneDetail * detail ;
2002-09-30 16:54:29 +00:00
BOOL isDST ;
2001-01-30 12:05:02 +00:00
detail = [ self timeZoneDetailForDate : aDate ] ;
2002-09-30 16:54:29 +00:00
isDST = [ detail isDaylightSavingTimeZone ] ;
return isDST ;
1997-10-17 13:35:52 +00:00
}
1997-11-03 14:30:13 +00:00
2001-01-30 12:05:02 +00:00
- ( BOOL ) isEqual : ( id ) other
1997-10-17 13:35:52 +00:00
{
2001-01-30 12:05:02 +00:00
if ( other = = self )
return YES ;
if ( [ other isKindOfClass : NSTimeZoneClass ] = = NO )
return NO ;
return [ self isEqualToTimeZone : other ] ;
}
1997-09-01 21:59:51 +00:00
2004-02-29 21:17:40 +00:00
/ * *
* Returns TRUE if the time zones have the same name .
* /
2001-01-30 12:05:02 +00:00
- ( BOOL ) isEqualToTimeZone : ( NSTimeZone * ) aTimeZone
{
if ( aTimeZone = = self )
return YES ;
2002-10-01 10:25:40 +00:00
if ( [ [ self name ] isEqual : [ aTimeZone name ] ] = = NO )
return NO ;
if ( ( [ self data ] = = nil && [ aTimeZone data ] = = nil )
|| [ [ self name ] isEqual : [ aTimeZone name ] ] = = YES )
2001-01-30 12:05:02 +00:00
return YES ;
return NO ;
}
1997-09-01 21:59:51 +00:00
2004-02-29 21:17:40 +00:00
/ * *
* Returns the name of the timezone
* /
2001-01-30 12:05:02 +00:00
- ( NSString * ) name
{
return [ self subclassResponsibility : _cmd ] ;
}
1997-09-01 21:59:51 +00:00
2001-01-31 05:58:59 +00:00
- ( id ) replacementObjectForPortCoder : ( NSPortCoder * ) aCoder
{
if ( [ aCoder isByref ] = = NO )
2002-10-01 10:25:40 +00:00
{
return self ;
}
2001-01-31 05:58:59 +00:00
return [ super replacementObjectForPortCoder : aCoder ] ;
}
2002-09-30 16:54:29 +00:00
/ * *
* Returns the number of seconds by which the receiver differs
* from Greenwich Mean Time at the current date and time . < br / >
* Invokes - secondsFromGMTForDate :
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) secondsFromGMT
2001-01-30 12:05:02 +00:00
{
return [ self secondsFromGMTForDate : [ NSDate date ] ] ;
}
1997-09-01 21:59:51 +00:00
2002-09-28 09:30:38 +00:00
/ * *
* Returns the number of seconds by which the receiver differs
2002-09-30 16:54:29 +00:00
* from Greenwich Mean Time at the date aDate . < br / >
2005-11-06 13:53:40 +00:00
* If the time zone uses daylight savings time , the returned value
2002-09-28 09:30:38 +00:00
* will vary at different times of year .
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) secondsFromGMTForDate : ( NSDate * ) aDate
2001-01-30 12:05:02 +00:00
{
NSTimeZoneDetail * detail ;
2002-09-30 16:54:29 +00:00
int offset ;
2001-01-30 12:05:02 +00:00
2002-09-30 16:54:29 +00:00
detail = [ self timeZoneDetailForDate : aDate ] ;
offset = [ detail timeZoneSecondsFromGMT ] ;
return offset ;
1997-10-17 13:35:52 +00:00
}
1997-11-03 14:30:13 +00:00
2004-02-29 21:17:40 +00:00
/ * *
2004-06-22 22:40:40 +00:00
* DEPRECATED : see NSTimeZoneDetail
2004-02-29 21:17:40 +00:00
* /
1999-08-25 16:12:36 +00:00
- ( NSArray * ) timeZoneDetailArray
1997-10-17 13:35:52 +00:00
{
1997-09-01 21:59:51 +00:00
return [ self subclassResponsibility : _cmd ] ;
1997-10-17 13:35:52 +00:00
}
1997-11-03 14:30:13 +00:00
2004-02-29 21:17:40 +00:00
/ * *
2004-06-22 22:40:40 +00:00
* DEPRECATED : see NSTimeZoneDetail
2004-02-29 21:17:40 +00:00
* /
2001-01-30 12:05:02 +00:00
- ( NSTimeZoneDetail * ) timeZoneDetailForDate : ( NSDate * ) date
{
return [ self subclassResponsibility : _cmd ] ;
}
2004-02-29 21:17:40 +00:00
/ * *
* Returns the name of this timezone .
* /
2001-01-30 12:05:02 +00:00
- ( NSString * ) timeZoneName
{
return [ self name ] ;
}
2008-06-06 13:57:06 +00:00
- ( NSTimeInterval ) daylightSavingTimeOffsetForDate : ( NSDate * ) aDate
{
return 0.0 ; // FIXME
}
- ( NSDate * ) nextDaylightSavingTimeTransitionAfterDate : ( NSDate * ) aDate
{
return nil ; // FIXME ;
}
- ( NSTimeInterval ) daylightSavingTimeOffset
{
return 0.0 ; // FIXME
}
- ( NSDate * ) nextDaylightSavingTimeTransition
{
return nil ; // FIXME ;
}
- ( NSString * ) localizedName : ( NSTimeZoneNameStyle ) style
locale : ( NSLocale * ) locale
{
return nil ; // FIXME ;
}
1997-10-17 13:35:52 +00:00
@ end
2005-02-22 11:22:44 +00:00
2002-10-01 10:25:40 +00:00
/ * *
2006-02-22 09:30:55 +00:00
* This class serves no useful purpose in GNUstep other than to provide
* a backup mechanism for handling abbreviations where the precomputed
* data files cannot be found . It is provided primarily for backward
* compatibility with the OpenStep spec . It is missing entirely from MacOS - X .
2002-10-01 10:25:40 +00:00
* /
1997-09-01 21:59:51 +00:00
@ implementation NSTimeZoneDetail
1995-08-23 16:13:42 +00:00
1999-08-25 16:12:36 +00:00
- ( NSString * ) description
1997-11-03 14:30:13 +00:00
{
2002-09-30 16:54:29 +00:00
return [ NSString stringWithFormat : @ "%@(%@, %s%d)" , [ self name ] ,
[ self timeZoneAbbreviation ] ,
( [ self isDaylightSavingTimeZone ] ? "IS_DST, " : "" ) ,
[ self timeZoneSecondsFromGMT ] ] ;
1997-11-03 14:30:13 +00:00
}
2004-02-29 21:17:40 +00:00
/ * *
2004-06-22 22:40:40 +00:00
* DEPRECATED : Class is no longer used .
2004-02-29 21:17:40 +00:00
* /
1999-08-25 16:12:36 +00:00
- ( BOOL ) isDaylightSavingTimeZone
1997-10-17 13:35:52 +00:00
{
1997-09-01 21:59:51 +00:00
[ self subclassResponsibility : _cmd ] ;
return NO ;
1997-10-17 13:35:52 +00:00
}
2005-02-22 11:22:44 +00:00
2004-02-29 21:17:40 +00:00
/ * *
2004-06-22 22:40:40 +00:00
* DEPRECATED : Class is no longer used .
2004-02-29 21:17:40 +00:00
* /
1999-08-25 16:12:36 +00:00
- ( NSString * ) timeZoneAbbreviation
1997-10-17 13:35:52 +00:00
{
1997-09-01 21:59:51 +00:00
return [ self subclassResponsibility : _cmd ] ;
1997-10-17 13:35:52 +00:00
}
2005-02-22 11:22:44 +00:00
2004-02-29 21:17:40 +00:00
/ * *
2004-06-22 22:40:40 +00:00
* DEPRECATED : Class is no longer used .
2004-02-29 21:17:40 +00:00
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) timeZoneSecondsFromGMT
1997-10-17 13:35:52 +00:00
{
1997-09-01 21:59:51 +00:00
[ self subclassResponsibility : _cmd ] ;
return 0 ;
1997-10-17 13:35:52 +00:00
}
@ end
1997-11-03 14:30:13 +00:00
1997-10-18 19:49:50 +00:00
@ implementation NSTimeZone ( Private )
1997-10-17 13:35:52 +00:00
2006-02-21 17:13:19 +00:00
/ * *
* Common locations for timezone info on unix systems .
* /
static NSString * zoneDirs [ ] = {
2006-04-12 19:41:44 +00:00
# ifdef TZDIR
2006-04-17 14:00:05 +00:00
@ TZDIR ,
2006-04-12 19:41:44 +00:00
# endif
2006-02-21 17:13:19 +00:00
@ "/usr/share/zoneinfo" ,
@ "/usr/lib/zoneinfo" ,
@ "/usr/local/share/zoneinfo" ,
@ "/usr/local/lib/zoneinfo" ,
@ "/etc/zoneinfo" ,
@ "/usr/local/etc/zoneinfo"
} ;
2004-02-29 21:17:40 +00:00
/ * *
* Returns the path to the named zone info file .
* /
2008-06-06 14:47:40 +00:00
+ ( NSString * ) _getTimeZoneFile : ( NSString * ) name
1997-10-18 19:49:50 +00:00
{
2006-02-21 17:13:19 +00:00
static BOOL beenHere = NO ;
2004-10-11 03:08:54 +00:00
NSString * dir = nil ;
2002-09-30 16:54:29 +00:00
2006-02-21 17:13:19 +00:00
if ( beenHere = = NO && tzdir = = nil )
{
if ( zone_mutex ! = nil )
{
[ zone_mutex lock ] ;
}
if ( beenHere = = NO && tzdir = = nil )
{
NSFileManager * mgr = [ NSFileManager defaultManager ] ;
NSString * zonedir = nil ;
unsigned i ;
for ( i = 0 ; i < sizeof ( zoneDirs ) / sizeof ( zoneDirs [ 0 ] ) ; i + + )
{
BOOL isDir ;
zonedir
= [ zoneDirs [ i ] stringByAppendingPathComponent : POSIX_TZONES ] ;
if ( [ mgr fileExistsAtPath : zonedir isDirectory : & isDir ] && isDir )
{
tzdir = RETAIN ( zonedir ) ;
break ; // use first one
}
}
beenHere = YES ;
}
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
}
}
2005-02-22 11:22:44 +00:00
/ * Use the system zone info if possible , otherwise , use our installed
2004-10-11 03:08:54 +00:00
info . * /
if ( tzdir && [ [ NSFileManager defaultManager ] fileExistsAtPath :
2006-02-21 17:13:19 +00:00
[ tzdir stringByAppendingPathComponent : name ] ] = = YES )
{
dir = tzdir ;
}
2004-10-11 03:08:54 +00:00
if ( dir = = nil )
2006-02-21 17:13:19 +00:00
{
dir = _time _zone _path ( ZONES_DIR , nil ) ;
}
2003-04-28 02:29:49 +00:00
return [ dir stringByAppendingPathComponent : name ] ;
1997-10-18 19:49:50 +00:00
}
1997-10-17 13:35:52 +00:00
2008-06-06 14:47:40 +00:00
+ ( void ) _notified : ( NSNotification * ) n
{
NSString * name ;
/ * If the name of the system time zone has changed . . .
* get a new system time zone .
* /
name = [ [ NSUserDefaults standardUserDefaults ] stringForKey : LOCALDBKEY ] ;
if ( [ name length ] > 0 && [ name isEqual : [ [ self systemTimeZone ] name ] ] = = NO )
{
[ self resetSystemTimeZone ] ;
[ self systemTimeZone ] ;
}
}
1997-10-18 19:49:50 +00:00
@ end
2002-09-30 16:54:29 +00:00
2004-02-29 21:17:40 +00:00
2010-03-19 12:10:11 +00:00
# if defined ( __MINGW __ )
2004-02-29 21:17:40 +00:00
/ * Timezone information data as stored in the registry * /
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 ;
}
}
/ * IMPORT from NSCalendar date * /
void
2009-02-23 20:42:32 +00:00
GSBreakTime ( NSTimeInterval when , NSInteger * year , NSInteger * month , NSInteger * day ,
NSInteger * hour , NSInteger * minute , NSInteger * second , NSInteger * mil ) ;
2006-03-10 10:46:37 +00:00
2004-02-29 21:17:40 +00:00
@ implementation GSWindowsTimeZone
- ( NSString * ) abbreviationForDate : ( NSDate * ) aDate
{
2005-11-06 07:13:33 +00:00
if ( [ self isDaylightSavingTimeForDate : aDate ] )
2004-02-29 21:17:40 +00:00
return daylightZoneNameAbbr ;
return timeZoneNameAbbr ;
}
- ( NSData * ) data
{
2005-11-06 07:13:33 +00:00
return 0 ;
2004-02-29 21:17:40 +00:00
}
- ( void ) dealloc
{
RELEASE ( timeZoneName ) ;
RELEASE ( daylightZoneName ) ;
RELEASE ( timeZoneNameAbbr ) ;
RELEASE ( daylightZoneNameAbbr ) ;
[ super dealloc ] ;
}
- ( id ) initWithName : ( NSString * ) name data : ( NSData * ) data
{
2007-11-06 10:21:46 +00:00
HKEY regDirKey ;
2008-01-18 13:33:26 +00:00
BOOL isNT = NO , regFound = NO ;
2007-11-06 10:21:46 +00:00
2008-01-18 13:33:26 +00:00
/ * Open the key in the local machine hive where
* the time zone data is stored . * /
2007-11-06 10:21:46 +00:00
if ( ERROR_SUCCESS = = RegOpenKeyExW ( HKEY_LOCAL _MACHINE ,
2008-01-18 13:33:26 +00:00
L "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones" ,
0 ,
KEY_READ ,
& regDirKey ) )
{
isNT = YES ;
regFound = YES ;
}
2004-02-29 21:17:40 +00:00
else
{
2008-01-18 13:33:26 +00:00
if ( ERROR_SUCCESS = = RegOpenKeyExW ( HKEY_LOCAL _MACHINE ,
L "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones" ,
0 ,
KEY_READ ,
& regDirKey ) )
{
regFound = YES ;
}
2004-02-29 21:17:40 +00:00
}
2004-05-21 15:39:02 +00:00
if ( regFound )
2008-01-18 13:33:26 +00:00
{
/ * Iterate over all subKeys in the registry to find the right one .
Unfortunately name is a localized value . The keys in the registry are
unlocalized names . * /
wchar_t achKey [ 255 ] ; // buffer for subkey name
DWORD cbName ; // size of name string
wchar_t achClass [ MAX_PATH ] = L "" ; // buffer for class name
DWORD cchClassName = MAX_PATH ; // size of class string
DWORD cSubKeys = 0 ; // number of subkeys
DWORD cbMaxSubKey ; // longest subkey size
DWORD cchMaxClass ; // longest class string
DWORD cValues ; // number of values for key
DWORD cchMaxValue ; // longest value name
DWORD cbMaxValueData ; // longest value data
DWORD cbSecurityDescriptor ; // size of security descriptor
FILETIME ftLastWriteTime ; // last write time
DWORD i , retCode ;
BOOL tzFound = NO ;
2007-11-06 10:21:46 +00:00
2008-01-18 13:33:26 +00:00
/ * Get the class name and the value count . * /
retCode = RegQueryInfoKeyW (
regDirKey , // key handle
achClass , // buffer for class name
& cchClassName , // size of class string
NULL , // reserved
& cSubKeys , // number of subkeys
& cbMaxSubKey , // longest subkey size
& cchMaxClass , // longest class string
& cValues , // number of values for this key
& cchMaxValue , // longest value name
& cbMaxValueData , // longest value data
& cbSecurityDescriptor , // security descriptor
& ftLastWriteTime ) ; // last write time
if ( cSubKeys && ( retCode = = ERROR_SUCCESS ) )
2007-11-06 10:21:46 +00:00
{
2008-01-18 16:04:41 +00:00
unsigned wLen = [ name length ] ;
2008-01-18 13:33:26 +00:00
wchar_t * wName = malloc ( ( wLen + 1 ) * sizeof ( wchar_t ) ) ;
if ( wName )
{
[ name getCharacters : wName ] ;
wName [ wLen ] = 0 ;
for ( i = 0 ; i < cSubKeys && ! tzFound ; i + + )
{
cbName = 255 ;
retCode = RegEnumKeyExW ( regDirKey , i , achKey , & cbName ,
NULL , NULL , NULL , & ftLastWriteTime ) ;
if ( retCode = = ERROR_SUCCESS )
{
wchar_t keyBuffer [ 16384 ] ;
HKEY regKey ;
if ( isNT )
wcscpy ( keyBuffer , L "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\" ) ;
else
wcscpy ( keyBuffer , L "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones\\" ) ;
wcscat ( keyBuffer , achKey ) ;
if ( ERROR_SUCCESS = = RegOpenKeyExW ( HKEY_LOCAL _MACHINE ,
keyBuffer , 0 , KEY_READ , & regKey ) )
{
wchar_t buf [ 256 ] ;
wchar_t standardName [ 256 ] ;
wchar_t daylightName [ 256 ] ;
DWORD bufsize ;
DWORD type ;
/ * check standardname * /
standardName [ 0 ] = L ' \ 0 ' ;
bufsize = sizeof ( buf ) ;
if ( ERROR_SUCCESS = = RegQueryValueExW ( regKey ,
L "Std" , 0 , & type , ( BYTE * ) buf , & bufsize ) )
{
wcscpy ( standardName , buf ) ;
if ( wcscmp ( standardName , wName ) = = 0 )
tzFound = YES ;
}
/ * check daylightname * /
daylightName [ 0 ] = L ' \ 0 ' ;
bufsize = sizeof ( buf ) ;
if ( ERROR_SUCCESS = = RegQueryValueExW ( regKey ,
L "Dlt" , 0 , & type , ( BYTE * ) buf , & bufsize ) )
{
wcscpy ( daylightName , buf ) ;
if ( wcscmp ( daylightName , wName ) = = 0 )
tzFound = YES ;
}
if ( tzFound )
{
/ * Read in the time zone data * /
bufsize = sizeof ( buf ) ;
if ( ERROR_SUCCESS = = RegQueryValueExW ( regKey ,
L "TZI" , 0 , & type , ( BYTE * ) buf , & bufsize ) )
{
TZI * tzi = ( void * ) buf ;
Bias = tzi -> Bias ;
StandardBias = tzi -> StandardBias ;
DaylightBias = tzi -> DaylightBias ;
StandardDate = tzi -> StandardDate ;
DaylightDate = tzi -> DaylightDate ;
}
/ * Set the standard name for the time zone . * /
if ( wcslen ( standardName ) )
{
int a , b ;
ASSIGN ( timeZoneName ,
[ NSString stringWithCharacters : standardName
length : wcslen ( standardName ) ] ) ;
/ * Abbr generated here is IMHO
* a bit suspicous but I kept it * /
for ( a = 0 , b = 0 ; standardName [ a ] ; a + + )
{
if ( iswupper ( standardName [ a ] ) )
standardName [ b + + ] = standardName [ a ] ;
}
standardName [ b ] = L ' \ 0 ' ;
ASSIGN ( timeZoneNameAbbr ,
[ NSString stringWithCharacters : standardName
length : wcslen ( standardName ) ] ) ;
}
/ * Set the daylight savings name
* for the time zone . * /
if ( wcslen ( daylightName ) )
{
int a , b ;
ASSIGN ( daylightZoneName ,
[ NSString stringWithCharacters : daylightName
length : wcslen ( daylightName ) ] ) ;
/ * Abbr generated here is IMHO
* a bit suspicous but I kept it * /
for ( a = 0 , b = 0 ; daylightName [ a ] ; a + + )
{
if ( iswupper ( daylightName [ a ] ) )
daylightName [ b + + ] = daylightName [ a ] ;
}
daylightName [ b ] = L ' \ 0 ' ;
ASSIGN ( daylightZoneNameAbbr ,
[ NSString stringWithCharacters : daylightName
length : wcslen ( daylightName ) ] ) ;
}
}
RegCloseKey ( regKey ) ;
}
}
}
free ( wName ) ;
}
}
2005-11-06 07:13:33 +00:00
RegCloseKey ( regDirKey ) ;
2008-01-18 13:33:26 +00:00
}
2007-11-06 10:21:46 +00:00
2004-02-29 21:17:40 +00:00
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 ;
2002-09-30 16:54:29 +00:00
2004-02-29 21:17:40 +00:00
when = [ aDate timeIntervalSinceReferenceDate ] - Bias * 60 ;
GSBreakTime ( when , & year , & month , & day , & hour , & minute , & second , & mil ) ;
2007-02-14 11:38:52 +00:00
// Check north globe
if ( StandardDate . wMonth >= DaylightDate . wMonth )
{
// 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 ;
}
}
else
{
/ * check south globe
* Before April or after October is DST
* /
if ( month < StandardDate . wMonth || month > DaylightDate . wMonth )
{
return YES ;
}
// After April and before October is Std
if ( month > StandardDate . wMonth && month < DaylightDate . wMonth )
{
return NO ;
}
2008-01-18 13:33:26 +00:00
}
2007-02-14 11:38:52 +00:00
2009-02-23 20:42:32 +00:00
dow = ( ( NSInteger ) ( ( when / 86400.0 ) + GREGORIAN_REFERENCE ) ) % 7 ;
2004-02-29 21:17:40 +00:00
if ( dow < 0 )
dow + = 7 ;
2005-02-22 11:22:44 +00:00
2004-02-29 21:17:40 +00:00
if ( month = = DaylightDate . wMonth / * April * / )
{
daylightdate = day - dow + DaylightDate . wDayOfWeek ;
maxdate = lastDayOfGregorianMonth ( DaylightDate . wMonth , year ) -7 ;
while ( daylightdate > 7 )
2008-01-18 13:33:26 +00:00
daylightdate - = 7 ;
2004-02-29 21:17:40 +00:00
if ( daylightdate < 1 )
daylightdate + = 7 ;
2008-01-18 13:33:26 +00:00
count = DaylightDate . wDay ;
while ( count > 1 && daylightdate < maxdate )
2004-02-29 21:17:40 +00:00
{
2008-01-18 13:33:26 +00:00
daylightdate + = 7 ;
2004-02-29 21:17:40 +00:00
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 ;
2007-02-14 11:38:52 +00:00
}
2004-02-29 21:17:40 +00:00
if ( month = = StandardDate . wMonth / * October * / )
{
daylightdate = day - dow + StandardDate . wDayOfWeek ;
maxdate = lastDayOfGregorianMonth ( StandardDate . wMonth , year ) -7 ;
while ( daylightdate > 7 )
2008-01-18 13:33:26 +00:00
daylightdate - = 7 ;
2004-02-29 21:17:40 +00:00
if ( daylightdate < 1 )
daylightdate + = 7 ;
2008-01-18 13:33:26 +00:00
count = StandardDate . wDay ;
while ( count > 1 && daylightdate < maxdate )
2004-02-29 21:17:40 +00:00
{
2008-01-18 13:33:26 +00:00
daylightdate + = 7 ;
2004-02-29 21:17:40 +00:00
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
{
2007-02-14 11:38:52 +00:00
TIME_ZONE _INFORMATION tz ;
DWORD DST = GetTimeZoneInformation ( & tz ) ;
if ( DST = = TIME_ZONE _ID _DAYLIGHT )
{
return daylightZoneName ;
}
else
{
return timeZoneName ;
}
2004-02-29 21:17:40 +00:00
}
2009-02-23 20:42:32 +00:00
- ( NSInteger ) secondsFromGMTForDate : ( NSDate * ) aDate
2004-02-29 21:17:40 +00:00
{
2005-11-06 07:13:33 +00:00
if ( [ self isDaylightSavingTimeForDate : aDate ] )
2004-02-29 21:17:40 +00:00
return - Bias * 60 - DaylightBias * 60 ;
return - Bias * 60 - StandardBias * 60 ;
}
- ( NSArray * ) timeZoneDetailArray
{
2005-03-07 11:19:34 +00:00
return [ NSArray arrayWithObjects :
2005-11-06 07:13:33 +00:00
[ [ [ 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 ] ;
2004-02-29 21:17:40 +00:00
}
- ( NSTimeZoneDetail * ) timeZoneDetailForDate : ( NSDate * ) aDate
{
GSTimeZoneDetail * detail ;
int offset ;
2005-11-06 07:13:33 +00:00
BOOL isDST = [ self isDaylightSavingTimeForDate : aDate ] ;
2004-02-29 21:17:40 +00:00
NSString * abbr ;
if ( isDST )
{
offset = - Bias * 60 - DaylightBias * 60 ;
abbr = daylightZoneNameAbbr ;
2005-02-22 11:22:44 +00:00
}
2004-02-29 21:17:40 +00:00
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
{
2007-02-14 11:38:52 +00:00
return [ self name ] ;
2004-02-29 21:17:40 +00:00
}
@ end
2010-03-19 12:10:11 +00:00
# endif // __MINGW __
2004-02-29 21:17:40 +00:00
2002-09-30 16:54:29 +00:00
@ implementation GSTimeZone
/ * *
* Perform a binary search of a transitions table to locate the index
* of the transition to use for a particular time interval since 1970. < br / >
* We locate the index of the highest transition before the date , or zero
* if there is no transition before it .
* /
2002-10-01 10:25:40 +00:00
static TypeInfo *
2002-09-30 16:54:29 +00:00
chop ( NSTimeInterval since , GSTimeZone * zone )
{
2006-01-11 08:37:16 +00:00
int32_t when = ( int32_t ) since ;
int32_t * trans = zone -> trans ;
2002-09-30 16:54:29 +00:00
unsigned hi = zone -> n_trans ;
unsigned lo = 0 ;
2003-01-03 20:14:47 +00:00
unsigned int i ;
2002-09-30 16:54:29 +00:00
if ( hi = = 0 || trans [ 0 ] > when )
{
unsigned n_types = zone -> n_types ;
/ *
2002-10-01 10:25:40 +00:00
* If the first transition is greater than our date ,
2002-09-30 16:54:29 +00:00
* we locate the first non - DST transition and use that offset ,
* or just use the first transition .
* /
for ( i = 0 ; i < n_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 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 .
* /
2003-01-03 20:14:47 +00:00
if ( i > 0 && ( i = = zone -> n_trans || trans [ i ] > when ) )
2002-09-30 16:54:29 +00:00
{
i - - ;
}
return & zone -> types [ zone -> idxs [ i ] ] ;
}
}
static NSTimeZoneDetail *
2002-10-01 10:25:40 +00:00
newDetailInZoneForType ( GSTimeZone * zone , TypeInfo * type )
2002-09-30 16:54:29 +00:00
{
2002-10-01 10:25:40 +00:00
GSTimeZoneDetail * detail ;
2002-09-30 16:54:29 +00:00
2002-10-01 10:25:40 +00:00
detail = [ GSTimeZoneDetail alloc ] ;
2002-09-30 16:54:29 +00:00
detail = [ detail initWithTimeZone : zone
2002-10-01 10:25:40 +00:00
withAbbrev : type -> abbreviation
withOffset : type -> offset
withDST : type -> isdst ] ;
2002-09-30 16:54:29 +00:00
return detail ;
}
- ( NSString * ) abbreviationForDate : ( NSDate * ) aDate
{
2002-10-01 10:25:40 +00:00
TypeInfo * type = chop ( [ aDate timeIntervalSince1970 ] , self ) ;
2002-09-30 16:54:29 +00:00
2002-10-01 10:25:40 +00:00
return type -> abbreviation ;
}
- ( NSData * ) data
{
return timeZoneData ;
2002-09-30 16:54:29 +00:00
}
- ( void ) dealloc
{
RELEASE ( timeZoneName ) ;
2002-10-01 10:25:40 +00:00
RELEASE ( timeZoneData ) ;
2006-02-21 15:44:04 +00:00
RELEASE ( abbreviations ) ;
2002-10-01 10:25:40 +00:00
if ( types ! = 0 )
2002-09-30 16:54:29 +00:00
{
2002-10-01 10:25:40 +00:00
NSZoneFree ( NSDefaultMallocZone ( ) , types ) ;
2002-09-30 16:54:29 +00:00
}
[ super dealloc ] ;
}
- ( id ) initWithName : ( NSString * ) name data : ( NSData * ) data
{
static NSString * fileException = @ "GSTimeZoneFileException" ;
timeZoneName = [ name copy ] ;
2002-10-01 10:25:40 +00:00
timeZoneData = [ data copy ] ;
2002-09-30 16:54:29 +00:00
NS_DURING
{
2002-10-01 10:25:40 +00:00
const void * bytes = [ timeZoneData bytes ] ;
unsigned length = [ timeZoneData length ] ;
void * buf ;
2002-09-30 16:54:29 +00:00
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" ] ;
}
header = ( struct tzhead * ) ( bytes + pos ) ;
pos + = sizeof ( struct tzhead ) ;
2004-10-11 03:08:54 +00:00
# ifdef TZ_MAGIC
2002-09-30 16:54:29 +00:00
if ( memcmp ( header -> tzh_magic , TZ_MAGIC , strlen ( TZ_MAGIC ) ) ! = 0 )
{
[ NSException raise : fileException
format : @ "TZ_MAGIC is incorrect" ] ;
}
2004-10-11 03:08:54 +00:00
# endif
2006-01-11 08:37:16 +00:00
n_trans = GSSwapBigI32ToHost (*(int32_t*) header -> tzh_timecnt ) ;
n_types = GSSwapBigI32ToHost (*(int32_t*) header -> tzh_typecnt ) ;
charcnt = GSSwapBigI32ToHost (*(int32_t*) header -> tzh_charcnt ) ;
2002-10-01 10:25:40 +00:00
i = pos ;
2006-01-11 08:37:16 +00:00
i + = sizeof ( int32_t ) * n_trans ;
2002-10-01 10:25:40 +00:00
if ( i > length )
2002-09-30 16:54:29 +00:00
{
[ NSException raise : fileException
format : @ "Transitions list is truncated" ] ;
}
2002-10-01 10:25:40 +00:00
i + = n_trans ;
if ( i > length )
2002-09-30 16:54:29 +00:00
{
2002-10-01 10:25:40 +00:00
[ NSException raise : fileException
format : @ "Transition indexes are truncated" ] ;
2002-09-30 16:54:29 +00:00
}
2002-10-01 10:25:40 +00:00
i + = sizeof ( struct ttinfo ) * n_types ;
if ( i > length )
2002-09-30 16:54:29 +00:00
{
[ NSException raise : fileException
format : @ "Types list is truncated" ] ;
}
2002-10-01 10:25:40 +00:00
if ( i + charcnt > length )
2002-09-30 16:54:29 +00:00
{
[ NSException raise : fileException
format : @ "Abbreviations list is truncated" ] ;
}
/ *
2002-10-01 10:25:40 +00:00
* Now calculate size we need to store the information
* for efficient access . . . not the same saze as the data
* we received .
2002-09-30 16:54:29 +00:00
* /
2006-01-11 08:37:16 +00:00
i = n_trans * ( sizeof ( int32_t ) + 1 ) + n_types * sizeof ( TypeInfo ) ;
2002-10-01 10:25:40 +00:00
buf = NSZoneMalloc ( NSDefaultMallocZone ( ) , i ) ;
types = ( TypeInfo * ) buf ;
buf + = ( n_types * sizeof ( TypeInfo ) ) ;
2006-01-11 08:37:16 +00:00
trans = ( int32_t * ) buf ;
buf + = ( n_trans * sizeof ( int32_t ) ) ;
2002-10-01 10:25:40 +00:00
idxs = ( unsigned char * ) buf ;
/ * Read in transitions . * /
for ( i = 0 ; i < n_trans ; i + + )
{
2006-01-11 08:37:16 +00:00
trans [ i ] = GSSwapBigI32ToHost (*(int32_t*) ( bytes + pos ) ) ;
pos + = sizeof ( int32_t ) ;
2002-10-01 10:25:40 +00:00
}
for ( i = 0 ; i < n_trans ; i + + )
{
idxs [ i ] = * ( unsigned char * ) ( bytes + pos ) ;
pos + + ;
}
2002-09-30 16:54:29 +00:00
for ( i = 0 ; i < n_types ; i + + )
{
2002-10-01 10:25:40 +00:00
struct ttinfo * ptr = ( struct ttinfo * ) ( bytes + pos ) ;
2002-09-30 16:54:29 +00:00
2002-10-01 10:25:40 +00:00
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 ) ;
2002-09-30 16:54:29 +00:00
}
2005-07-08 11:48:37 +00:00
abbr = ( unsigned char * ) ( bytes + pos ) ;
2002-10-01 10:25:40 +00:00
{
2006-02-21 15:44:04 +00:00
id abbrevs [ charcnt ] ;
unsigned count = 0 ;
unsigned used = 0 ;
2002-10-01 10:25:40 +00:00
memset ( abbrevs , ' \ 0 ' , sizeof ( id ) * charcnt ) ;
for ( i = 0 ; i < n_types ; i + + )
{
int loc = types [ i ] . abbr_idx ;
if ( abbrevs [ loc ] = = nil )
{
2005-07-08 11:48:37 +00:00
abbrevs [ loc ]
2006-02-21 15:44:04 +00:00
= [ [ NSString alloc ] initWithUTF8String : ( char * ) abbr + loc ] ;
count + + ;
2002-10-01 10:25:40 +00:00
}
2006-02-21 15:44:04 +00:00
types [ i ] . abbreviation = abbrevs [ loc ] ;
}
/ *
* Now we have created all the abbreviations , we put them in an
* array for easy access later and easy deallocation if / when
* the receiver is deallocated .
* /
i = charcnt ;
while ( i - - > count )
{
if ( abbrevs [ i ] ! = nil )
2002-10-01 10:25:40 +00:00
{
2006-02-21 15:44:04 +00:00
while ( abbrevs [ used ] ! = nil )
{
used + + ;
}
abbrevs [ used ] = abbrevs [ i ] ;
abbrevs [ i ] = nil ;
if ( + + used >= count )
{
break ;
}
2002-10-01 10:25:40 +00:00
}
2006-02-21 15:44:04 +00:00
}
abbreviations = [ [ NSArray alloc ] initWithObjects : abbrevs count : count ] ;
while ( count - - > 0 )
{
RELEASE ( abbrevs [ count ] ) ;
2002-10-01 10:25:40 +00:00
}
}
2002-09-30 16:54:29 +00:00
if ( zone_mutex ! = nil )
{
[ zone_mutex lock ] ;
}
[ zoneDictionary setObject : self forKey : timeZoneName ] ;
if ( zone_mutex ! = nil )
{
[ zone_mutex unlock ] ;
}
}
NS_HANDLER
{
DESTROY ( self ) ;
NSLog ( @ "Unable to obtain time zone `%@'... %@" , name , localException ) ;
if ( [ localException name ] ! = fileException )
{
[ localException raise ] ;
}
}
NS_ENDHANDLER
return self ;
}
- ( BOOL ) isDaylightSavingTimeForDate : ( NSDate * ) aDate
{
2002-10-01 10:25:40 +00:00
TypeInfo * type = chop ( [ aDate timeIntervalSince1970 ] , self ) ;
2002-09-30 16:54:29 +00:00
2002-10-01 10:25:40 +00:00
return type -> isdst ;
2002-09-30 16:54:29 +00:00
}
- ( NSString * ) name
{
return timeZoneName ;
}
2009-02-23 20:42:32 +00:00
- ( NSInteger ) secondsFromGMTForDate : ( NSDate * ) aDate
2002-09-30 16:54:29 +00:00
{
2002-10-01 10:25:40 +00:00
TypeInfo * type = chop ( [ aDate timeIntervalSince1970 ] , self ) ;
2002-09-30 16:54:29 +00:00
2002-10-01 10:25:40 +00:00
return type -> offset ;
2002-09-30 16:54:29 +00:00
}
- ( NSArray * ) timeZoneDetailArray
{
NSTimeZoneDetail * details [ n_types ] ;
unsigned i ;
NSArray * array ;
for ( i = 0 ; i < n_types ; i + + )
{
details [ i ] = newDetailInZoneForType ( self , & types [ i ] ) ;
}
array = [ NSArray arrayWithObjects : details count : n_types ] ;
for ( i = 0 ; i < n_types ; i + + )
{
RELEASE ( details [ i ] ) ;
}
return array ;
}
- ( NSTimeZoneDetail * ) timeZoneDetailForDate : ( NSDate * ) aDate
{
2002-10-01 10:25:40 +00:00
TypeInfo * type ;
2002-09-30 16:54:29 +00:00
NSTimeZoneDetail * detail ;
type = chop ( [ aDate timeIntervalSince1970 ] , self ) ;
detail = newDetailInZoneForType ( self , type ) ;
return AUTORELEASE ( detail ) ;
}
- ( NSString * ) timeZoneName
{
return timeZoneName ;
}
@ end