1 // natTimeZone.cc -- Native side of TimeZone class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
17 #include <java/util/TimeZone.h>
18 #include <java/lang/Character.h>
19 #include <java/lang/Integer.h>
23 #if TIME_WITH_SYS_TIME
24 # include <sys/time.h>
28 # include <sys/time.h>
37 * This method returns a time zone string that is used by init_properties
38 * to set the default timezone property 'user.timezone'. That value is
39 * used by default as a key into the timezone table used by the
40 * java::util::TimeZone class.
43 getSystemTimeZone (void)
48 const char *tz1
, *tz2
;
51 current_time
= time(0);
53 mktime(tim
= localtime(¤t_time
));
54 #ifdef STRUCT_TM_HAS_GMTOFF
55 // tm_gmtoff is secs EAST of UTC.
56 tzoffset
= -(tim
->tm_gmtoff
) + tim
->tm_isdst
* 3600L;
57 #elif HAVE_UNDERSCORE_TIMEZONE
60 // timezone is secs WEST of UTC.
63 // FIXME: there must be another global if neither tm_gmtoff nor timezone
64 // is available, esp. if tzname is valid.
65 // Richard Earnshaw <rearnsha@arm.com> has suggested using difftime to
66 // calculate between gmtime and localtime (and accounting for possible
67 // daylight savings time) as an alternative.
74 #elif defined (HAVE_TZNAME)
76 tz2
= strcmp (tzname
[0], tzname
[1]) ? tzname
[1] : "";
78 // Some targets have no concept of timezones.
83 if ((tzoffset
% 3600) == 0)
84 tzoffset
= tzoffset
/ 3600;
86 tzid
= (char*) _Jv_Malloc (strlen(tz1
) + strlen(tz2
) + 6);
87 sprintf(tzid
, "%s%ld%s", tz1
, tzoffset
, tz2
);
88 jstring retval
= JvNewStringUTF (tzid
);
94 // Get the System Timezone as reported by the OS. It should be in
95 // the form PST8PDT so we'll need to parse it and check that it's valid.
96 // FIXME: Using the code from Classpath for generating the System
97 // Timezone IMO is suboptimal because it ignores whether the rules for
100 java::util::TimeZone::getDefaultTimeZoneId ()
102 jstring sysTimeZoneId
= getSystemTimeZone ();
104 using namespace java::lang
;
106 // Check if this is a valid timezone. Make sure the IDs match
107 // since getTimeZone returns GMT if no match is found.
108 TimeZone
*tz
= TimeZone::getTimeZone (sysTimeZoneId
);
109 if (tz
->getID ()->equals (sysTimeZoneId
))
110 return sysTimeZoneId
;
112 // Check if the base part of sysTimeZoneId is a valid timezone that
113 // matches with daylight usage and rawOffset. Make sure the IDs match
114 // since getTimeZone returns GMT if no match is found.
115 // First find start of GMT offset info and any Daylight zone name.
116 int startGMToffset
= 0;
117 int sysTimeZoneIdLength
= sysTimeZoneId
->length();
118 for (int i
= 0; i
< sysTimeZoneIdLength
&& startGMToffset
== 0; i
++)
120 if (Character::isDigit (sysTimeZoneId
->charAt (i
)))
124 int startDaylightZoneName
= 0;
125 jboolean usesDaylight
= false;
126 for (int i
= sysTimeZoneIdLength
- 1;
127 i
>= 0 && !Character::isDigit (sysTimeZoneId
->charAt (i
)); --i
)
129 startDaylightZoneName
= i
;
131 if (startDaylightZoneName
> 0)
135 = Integer::parseInt (startDaylightZoneName
== 0 ?
136 sysTimeZoneId
->substring (startGMToffset
) :
137 sysTimeZoneId
->substring (startGMToffset
,
138 startDaylightZoneName
));
140 // Offset could be in hours or seconds. Convert to millis.
142 GMToffset
*= 60 * 60;
145 jstring tzBasename
= sysTimeZoneId
->substring (0, startGMToffset
);
146 tz
= TimeZone::getTimeZone (tzBasename
);
147 if (tz
->getID ()->equals (tzBasename
) && tz
->getRawOffset () == GMToffset
)
149 jboolean tzUsesDaylight
= tz
->useDaylightTime ();
150 if (usesDaylight
&& tzUsesDaylight
|| !usesDaylight
&& !tzUsesDaylight
)
154 // If no match, see if a valid timezone has the same attributes as this
155 // and then use it instead.
156 jstringArray IDs
= TimeZone::getAvailableIDs (GMToffset
);
157 jstring
*elts
= elements (IDs
);
158 for (int i
= 0; i
< IDs
->length
; ++i
)
160 // FIXME: The daylight savings rules may not match the rules
161 // for the desired zone.
162 jboolean IDusesDaylight
=
163 TimeZone::getTimeZone (elts
[i
])->useDaylightTime ();
164 if (usesDaylight
&& IDusesDaylight
|| !usesDaylight
&& !IDusesDaylight
)
168 // If all else fails, return null.