1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * COPYRIGHT: LGPL, See LGPL.txt in the top level directory
3*c2c66affSColin Finck * PROJECT: ReactOS CRT library
4*c2c66affSColin Finck * FILE: lib/sdk/crt/time/timezone.c
5*c2c66affSColin Finck * PURPOSE: Implementation of time zone functions
6*c2c66affSColin Finck * PROGRAMERS: Timo Kreuzer
7*c2c66affSColin Finck */
8*c2c66affSColin Finck #include "precomp.h"
9*c2c66affSColin Finck
10*c2c66affSColin Finck char _tz_is_set = 0;
11*c2c66affSColin Finck
12*c2c66affSColin Finck /* buffers must hold 64 characters! */
13*c2c66affSColin Finck static char tz_name[64] = "PST";
14*c2c66affSColin Finck static char tz_dst_name[64] = "PDT";
15*c2c66affSColin Finck
16*c2c66affSColin Finck long dst_begin = 0;
17*c2c66affSColin Finck long dst_end = 0;
18*c2c66affSColin Finck
19*c2c66affSColin Finck /******************************************************************************
20*c2c66affSColin Finck * \var _tzname
21*c2c66affSColin Finck */
22*c2c66affSColin Finck char * _tzname[2] = {
23*c2c66affSColin Finck tz_name,
24*c2c66affSColin Finck tz_dst_name,
25*c2c66affSColin Finck };
26*c2c66affSColin Finck
27*c2c66affSColin Finck /******************************************************************************
28*c2c66affSColin Finck * \var _daylight
29*c2c66affSColin Finck */
30*c2c66affSColin Finck int _daylight = 0;
31*c2c66affSColin Finck
32*c2c66affSColin Finck /******************************************************************************
33*c2c66affSColin Finck * \name __p__daylight
34*c2c66affSColin Finck * \brief Returns a pointer to the _daylight variable;
35*c2c66affSColin Finck */
36*c2c66affSColin Finck void *
__p__daylight(void)37*c2c66affSColin Finck __p__daylight(void)
38*c2c66affSColin Finck {
39*c2c66affSColin Finck return &_daylight;
40*c2c66affSColin Finck }
41*c2c66affSColin Finck
42*c2c66affSColin Finck /******************************************************************************
43*c2c66affSColin Finck * \var _timezone
44*c2c66affSColin Finck * \brief
45*c2c66affSColin Finck */
46*c2c66affSColin Finck long _timezone = 28800;
47*c2c66affSColin Finck
48*c2c66affSColin Finck /******************************************************************************
49*c2c66affSColin Finck * \name __p__timezone
50*c2c66affSColin Finck * \brief Returns a pointer to the _timezone variable;
51*c2c66affSColin Finck */
52*c2c66affSColin Finck long *
__p__timezone(void)53*c2c66affSColin Finck __p__timezone(void)
54*c2c66affSColin Finck {
55*c2c66affSColin Finck return &_timezone;
56*c2c66affSColin Finck }
57*c2c66affSColin Finck
58*c2c66affSColin Finck /******************************************************************************
59*c2c66affSColin Finck * \var _dstbias
60*c2c66affSColin Finck * \brief
61*c2c66affSColin Finck */
62*c2c66affSColin Finck long _dstbias = 0;
63*c2c66affSColin Finck
64*c2c66affSColin Finck /******************************************************************************
65*c2c66affSColin Finck * \name __p__dstbias
66*c2c66affSColin Finck * \brief Returns a pointer to the _dstbias variable;
67*c2c66affSColin Finck */
68*c2c66affSColin Finck long *
__p__dstbias(void)69*c2c66affSColin Finck __p__dstbias(void)
70*c2c66affSColin Finck {
71*c2c66affSColin Finck return &_dstbias;
72*c2c66affSColin Finck }
73*c2c66affSColin Finck
74*c2c66affSColin Finck /******************************************************************************
75*c2c66affSColin Finck * \name __p__tzname
76*c2c66affSColin Finck * \brief Returns a pointer to the _tzname buffer;
77*c2c66affSColin Finck */
78*c2c66affSColin Finck char **
__p__tzname(void)79*c2c66affSColin Finck __p__tzname(void)
80*c2c66affSColin Finck {
81*c2c66affSColin Finck return _tzname;
82*c2c66affSColin Finck }
83*c2c66affSColin Finck
84*c2c66affSColin Finck /******************************************************************************
85*c2c66affSColin Finck * \name _tzset
86*c2c66affSColin Finck * \brief Initializes the variables _daylight, _timezone, and _tzname from the
87*c2c66affSColin Finck * "TZ" environment variable if available or else by calling
88*c2c66affSColin Finck * GetTimeZoneInformation.
89*c2c66affSColin Finck * \sa http://msdn.microsoft.com/en-us/library/90s5c885.aspx
90*c2c66affSColin Finck */
91*c2c66affSColin Finck void
_tzset(void)92*c2c66affSColin Finck _tzset(void)
93*c2c66affSColin Finck {
94*c2c66affSColin Finck const char * str;
95*c2c66affSColin Finck
96*c2c66affSColin Finck if (_tz_is_set)
97*c2c66affSColin Finck {
98*c2c66affSColin Finck return;
99*c2c66affSColin Finck }
100*c2c66affSColin Finck
101*c2c66affSColin Finck /* Try to read the timezone from environment */
102*c2c66affSColin Finck str = getenv("TZ");
103*c2c66affSColin Finck if (str && str[0] != 0)
104*c2c66affSColin Finck {
105*c2c66affSColin Finck long hour = 0, min = 0, sec = 0;
106*c2c66affSColin Finck size_t len = strnlen(str, 16);
107*c2c66affSColin Finck int sign = 1;
108*c2c66affSColin Finck
109*c2c66affSColin Finck dst_begin = 0;
110*c2c66affSColin Finck
111*c2c66affSColin Finck for (;;)
112*c2c66affSColin Finck {
113*c2c66affSColin Finck /* Copy timezone name */
114*c2c66affSColin Finck strncpy(tz_name, str, 3);
115*c2c66affSColin Finck str += 3;
116*c2c66affSColin Finck len -= 3;
117*c2c66affSColin Finck
118*c2c66affSColin Finck if (len < 1) break;
119*c2c66affSColin Finck
120*c2c66affSColin Finck if (*str == '+' || *str == '-')
121*c2c66affSColin Finck {
122*c2c66affSColin Finck sign = *str == '-' ? -1 : 1;
123*c2c66affSColin Finck str++;
124*c2c66affSColin Finck len--;
125*c2c66affSColin Finck }
126*c2c66affSColin Finck
127*c2c66affSColin Finck if (len < 1) break;
128*c2c66affSColin Finck
129*c2c66affSColin Finck hour = atol(str);
130*c2c66affSColin Finck
131*c2c66affSColin Finck while (*str != 0 && *str != ':') str++;
132*c2c66affSColin Finck if (*str == 0) break;
133*c2c66affSColin Finck
134*c2c66affSColin Finck min = atol(++str);
135*c2c66affSColin Finck
136*c2c66affSColin Finck while (*str != 0 && *str != ':') str++;
137*c2c66affSColin Finck if (*str == 0) break;
138*c2c66affSColin Finck
139*c2c66affSColin Finck sec = atol(++str);
140*c2c66affSColin Finck
141*c2c66affSColin Finck while (*str != 0 && *str <= '9') str++;
142*c2c66affSColin Finck if (*str == 0) break;
143*c2c66affSColin Finck
144*c2c66affSColin Finck /* Copy DST name */
145*c2c66affSColin Finck strncpy(tz_dst_name, str, 3);
146*c2c66affSColin Finck
147*c2c66affSColin Finck // FIXME: set dst_begin etc
148*c2c66affSColin Finck
149*c2c66affSColin Finck /* We are finished */
150*c2c66affSColin Finck break;
151*c2c66affSColin Finck }
152*c2c66affSColin Finck
153*c2c66affSColin Finck _timezone = sign * (((hour * 60) + min) * 60 + sec);
154*c2c66affSColin Finck
155*c2c66affSColin Finck }
156*c2c66affSColin Finck else
157*c2c66affSColin Finck {
158*c2c66affSColin Finck TIME_ZONE_INFORMATION tzi;
159*c2c66affSColin Finck DWORD ret;
160*c2c66affSColin Finck
161*c2c66affSColin Finck ret = GetTimeZoneInformation(&tzi);
162*c2c66affSColin Finck if (ret == TIME_ZONE_ID_INVALID)
163*c2c66affSColin Finck {
164*c2c66affSColin Finck return;
165*c2c66affSColin Finck }
166*c2c66affSColin Finck
167*c2c66affSColin Finck ret = WideCharToMultiByte(CP_ACP,
168*c2c66affSColin Finck 0,
169*c2c66affSColin Finck tzi.StandardName,
170*c2c66affSColin Finck -1,
171*c2c66affSColin Finck tz_name,
172*c2c66affSColin Finck sizeof(tz_name),
173*c2c66affSColin Finck NULL,
174*c2c66affSColin Finck NULL);
175*c2c66affSColin Finck
176*c2c66affSColin Finck ret = WideCharToMultiByte(CP_ACP,
177*c2c66affSColin Finck 0,
178*c2c66affSColin Finck tzi.DaylightName,
179*c2c66affSColin Finck -1,
180*c2c66affSColin Finck tz_dst_name,
181*c2c66affSColin Finck sizeof(tz_dst_name),
182*c2c66affSColin Finck NULL,
183*c2c66affSColin Finck NULL);
184*c2c66affSColin Finck
185*c2c66affSColin Finck _timezone = tzi.Bias * 60;
186*c2c66affSColin Finck
187*c2c66affSColin Finck if (tzi.DaylightDate.wMonth)
188*c2c66affSColin Finck {
189*c2c66affSColin Finck struct tm _tm;
190*c2c66affSColin Finck
191*c2c66affSColin Finck _daylight = 1;
192*c2c66affSColin Finck _dstbias = (tzi.DaylightBias - tzi.StandardBias) * 60;
193*c2c66affSColin Finck _tm.tm_year = 70;
194*c2c66affSColin Finck _tm.tm_mon = tzi.DaylightDate.wMonth - 1;
195*c2c66affSColin Finck _tm.tm_mday = tzi.DaylightDate.wDay;
196*c2c66affSColin Finck _tm.tm_hour = tzi.DaylightDate.wHour;
197*c2c66affSColin Finck _tm.tm_min = tzi.DaylightDate.wMinute;
198*c2c66affSColin Finck _tm.tm_sec = tzi.DaylightDate.wSecond;
199*c2c66affSColin Finck dst_begin = (long)_mkgmtime(&_tm);
200*c2c66affSColin Finck _tm.tm_mon = tzi.StandardDate.wMonth - 1;
201*c2c66affSColin Finck _tm.tm_mday = tzi.StandardDate.wDay;
202*c2c66affSColin Finck _tm.tm_hour = tzi.StandardDate.wHour;
203*c2c66affSColin Finck _tm.tm_min = tzi.StandardDate.wMinute;
204*c2c66affSColin Finck _tm.tm_sec = tzi.StandardDate.wSecond;
205*c2c66affSColin Finck dst_end = (long)_mkgmtime(&_tm);
206*c2c66affSColin Finck }
207*c2c66affSColin Finck else
208*c2c66affSColin Finck {
209*c2c66affSColin Finck _daylight = 0;
210*c2c66affSColin Finck _dstbias = 0;
211*c2c66affSColin Finck }
212*c2c66affSColin Finck
213*c2c66affSColin Finck }
214*c2c66affSColin Finck _tz_is_set = 1;
215*c2c66affSColin Finck }
216*c2c66affSColin Finck
217*c2c66affSColin Finck /*********************************************************************
218*c2c66affSColin Finck * _get_tzname (MSVCRT.@)
219*c2c66affSColin Finck */
_get_tzname(size_t * ret,char * buf,size_t bufsize,int index)220*c2c66affSColin Finck int CDECL _get_tzname(size_t *ret, char *buf, size_t bufsize, int index)
221*c2c66affSColin Finck {
222*c2c66affSColin Finck char *str_timezone;
223*c2c66affSColin Finck
224*c2c66affSColin Finck switch (index)
225*c2c66affSColin Finck {
226*c2c66affSColin Finck case 0:
227*c2c66affSColin Finck str_timezone = tz_name;
228*c2c66affSColin Finck break;
229*c2c66affSColin Finck
230*c2c66affSColin Finck case 1:
231*c2c66affSColin Finck str_timezone = tz_dst_name;
232*c2c66affSColin Finck break;
233*c2c66affSColin Finck
234*c2c66affSColin Finck default:
235*c2c66affSColin Finck *_errno() = EINVAL;
236*c2c66affSColin Finck return EINVAL;
237*c2c66affSColin Finck }
238*c2c66affSColin Finck
239*c2c66affSColin Finck if (!ret || (!buf && (bufsize > 0)) || (buf && !bufsize))
240*c2c66affSColin Finck {
241*c2c66affSColin Finck *_errno() = EINVAL;
242*c2c66affSColin Finck return EINVAL;
243*c2c66affSColin Finck }
244*c2c66affSColin Finck
245*c2c66affSColin Finck *ret = strlen(str_timezone) + 1;
246*c2c66affSColin Finck if(!buf && !bufsize)
247*c2c66affSColin Finck return 0;
248*c2c66affSColin Finck
249*c2c66affSColin Finck strncpy(buf, str_timezone, bufsize);
250*c2c66affSColin Finck return 0;
251*c2c66affSColin Finck }
252