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 * 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 * 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 * 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 ** 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 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 */ 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