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