xref: /reactos/sdk/lib/crt/time/timezone.c (revision c2c66aff)
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