2 * Unit test suite for time functions.
4 * Copyright 2004 Uwe Bonnes
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/test.h"
26 #include <stdlib.h> /*setenv*/
27 #include <stdio.h> /*printf*/
31 #define _MAX__TIME64_T (((__time64_t)0x00000007 << 32) | 0x93406FFF)
33 #define SECSPERDAY 86400
34 #define SECSPERHOUR 3600
36 #define MINSPERHOUR 60
37 #define HOURSPERDAY 24
39 static __time32_t (__cdecl *p_mkgmtime32)(struct tm*);
40 static struct tm* (__cdecl *p_gmtime32)(__time32_t*);
41 static struct tm* (__cdecl *p_gmtime)(time_t*);
42 static errno_t (__cdecl *p_gmtime32_s)(struct tm*, __time32_t*);
43 static errno_t (__cdecl *p_strtime_s)(char*,size_t);
44 static errno_t (__cdecl *p_strdate_s)(char*,size_t);
45 static errno_t (__cdecl *p_localtime32_s)(struct tm*, __time32_t*);
46 static errno_t (__cdecl *p_localtime64_s)(struct tm*, __time64_t*);
47 static int* (__cdecl *p__daylight)(void);
48 static int* (__cdecl *p___p__daylight)(void);
49 static long* (__cdecl *p___p__dstbias)(void);
50 static long* (__cdecl *p___p__timezone)(void);
51 static size_t (__cdecl *p_strftime)(char *, size_t, const char *, const struct tm *);
52 static size_t (__cdecl *p_wcsftime)(wchar_t *, size_t, const wchar_t *, const struct tm *);
53 static char* (__cdecl *p_asctime)(const struct tm *);
55 static void init(void)
57 HMODULE hmod = LoadLibrary("msvcrt.dll");
59 p_gmtime32 = (void*)GetProcAddress(hmod, "_gmtime32");
60 p_gmtime = (void*)GetProcAddress(hmod, "gmtime");
61 p_gmtime32_s = (void*)GetProcAddress(hmod, "_gmtime32_s");
62 p_mkgmtime32 = (void*)GetProcAddress(hmod, "_mkgmtime32");
63 p_strtime_s = (void*)GetProcAddress(hmod, "_strtime_s");
64 p_strdate_s = (void*)GetProcAddress(hmod, "_strdate_s");
65 p_localtime32_s = (void*)GetProcAddress(hmod, "_localtime32_s");
66 p_localtime64_s = (void*)GetProcAddress(hmod, "_localtime64_s");
67 p__daylight = (void*)GetProcAddress(hmod, "__daylight");
68 p___p__daylight = (void*)GetProcAddress(hmod, "__p__daylight");
69 p___p__dstbias = (void*)GetProcAddress(hmod, "__p__dstbias");
70 p___p__timezone = (void*)GetProcAddress(hmod, "__p__timezone");
71 p_strftime = (void*)GetProcAddress(hmod, "strftime");
72 p_wcsftime = (void*)GetProcAddress(hmod, "wcsftime");
73 p_asctime = (void*)GetProcAddress(hmod, "asctime");
76 static int get_test_year(time_t *start)
78 time_t now = time(NULL);
79 struct tm *tm = localtime(&now);
81 /* compute start of year in seconds */
82 *start = SECSPERDAY * ((tm->tm_year - 70) * 365 +
83 (tm->tm_year - 69) / 4 -
84 (tm->tm_year - 1) / 100 +
85 (tm->tm_year + 299) / 400);
89 static void test_ctime(void)
93 ret = ctime(&badtime);
94 ok(ret == NULL, "expected ctime to return NULL, got %s\n", ret);
96 static void test_gmtime(void)
98 __time32_t valid, gmt;
99 struct tm* gmt_tm, gmt_tm_s;
103 win_skip("Skipping _gmtime32 tests\n");
107 gmt_tm = p_gmtime32(NULL);
108 ok(gmt_tm == NULL, "gmt_tm != NULL\n");
111 gmt_tm = p_gmtime32(&gmt);
112 ok(gmt_tm == NULL, "gmt_tm != NULL\n");
115 gmt_tm = p_gmtime32(&gmt);
117 ok(0, "_gmtime32() failed\n");
121 ok(((gmt_tm->tm_year == 70) && (gmt_tm->tm_mon == 0) && (gmt_tm->tm_yday == 0) &&
122 (gmt_tm->tm_mday == 1) && (gmt_tm->tm_wday == 4) && (gmt_tm->tm_hour == 0) &&
123 (gmt_tm->tm_min == 0) && (gmt_tm->tm_sec == 0) && (gmt_tm->tm_isdst == 0)),
124 "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n",
125 gmt_tm->tm_year, gmt_tm->tm_mon, gmt_tm->tm_yday, gmt_tm->tm_mday, gmt_tm->tm_wday,
126 gmt_tm->tm_hour, gmt_tm->tm_min, gmt_tm->tm_sec, gmt_tm->tm_isdst);
129 win_skip("Skipping _mkgmtime32 tests\n");
133 gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
134 gmt = p_mkgmtime32(gmt_tm);
135 ok(gmt == valid, "gmt = %u\n", gmt);
136 ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
137 ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
139 gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
140 gmt_tm->tm_isdst = -1;
141 gmt = p_mkgmtime32(gmt_tm);
142 ok(gmt == valid, "gmt = %u\n", gmt);
143 ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
144 ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
146 gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
147 gmt_tm->tm_isdst = 1;
148 gmt = p_mkgmtime32(gmt_tm);
149 ok(gmt == valid, "gmt = %u\n", gmt);
150 ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
151 ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
153 gmt = valid = 173921;
154 gmt_tm = p_gmtime32(&gmt);
156 ok(0, "_gmtime32() failed\n");
160 gmt_tm->tm_isdst = -1;
161 gmt = p_mkgmtime32(gmt_tm);
162 ok(gmt == valid, "gmt = %u\n", gmt);
163 ok(gmt_tm->tm_wday == 6, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
164 ok(gmt_tm->tm_yday == 2, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
166 gmt_tm->tm_isdst = 1;
167 gmt = p_mkgmtime32(gmt_tm);
168 ok(gmt == valid, "gmt = %u\n", gmt);
171 win_skip("Skipping _gmtime32_s tests\n");
177 err = p_gmtime32_s(NULL, &gmt);
178 ok(err == EINVAL, "err = %d\n", err);
179 ok(errno == EINVAL, "errno = %d\n", errno);
183 err = p_gmtime32_s(&gmt_tm_s, &gmt);
184 ok(err == EINVAL, "err = %d\n", err);
185 ok(errno == EINVAL, "errno = %d\n", errno);
186 ok(gmt_tm_s.tm_year == -1, "tm_year = %d\n", gmt_tm_s.tm_year);
189 static void test_mktime(void)
191 TIME_ZONE_INFORMATION tzinfo;
192 DWORD res = GetTimeZoneInformation(&tzinfo);
193 struct tm my_tm, sav_tm;
194 time_t nulltime, local_time;
200 year = get_test_year( &ref );
203 ok (res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
204 WideCharToMultiByte( CP_ACP, 0, tzinfo.StandardName, -1, buffer, sizeof(buffer), NULL, NULL );
205 trace( "bias %d std %d dst %d zone %s\n",
206 tzinfo.Bias, tzinfo.StandardBias, tzinfo.DaylightBias, buffer );
207 /* Bias may be positive or negative, to use offset of one day */
208 my_tm = *localtime(&ref); /* retrieve current dst flag */
209 secs = SECSPERDAY - tzinfo.Bias * SECSPERMIN;
210 secs -= (my_tm.tm_isdst ? tzinfo.DaylightBias : tzinfo.StandardBias) * SECSPERMIN;
211 my_tm.tm_mday = 1 + secs/SECSPERDAY;
212 secs = secs % SECSPERDAY;
213 my_tm.tm_hour = secs / SECSPERHOUR;
214 secs = secs % SECSPERHOUR;
215 my_tm.tm_min = secs / SECSPERMIN;
216 secs = secs % SECSPERMIN;
219 my_tm.tm_year = year;
224 local_time = mktime(&my_tm);
225 ok(local_time == ref, "mktime returned %u, expected %u\n",
226 (DWORD)local_time, (DWORD)ref);
227 /* now test some unnormalized struct tm's */
231 local_time = mktime(&my_tm);
232 ok(local_time == ref, "Unnormalized mktime returned %u, expected %u\n",
233 (DWORD)local_time, (DWORD)ref);
234 ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
235 my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
236 my_tm.tm_sec == sav_tm.tm_sec,
237 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
238 my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
239 my_tm.tm_hour,my_tm.tm_sec,
240 sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
241 sav_tm.tm_hour,sav_tm.tm_sec);
245 local_time = mktime(&my_tm);
246 ok(local_time == ref, "Unnormalized mktime returned %u, expected %u\n",
247 (DWORD)local_time, (DWORD)ref);
248 ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
249 my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
250 my_tm.tm_sec == sav_tm.tm_sec,
251 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
252 my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
253 my_tm.tm_hour,my_tm.tm_sec,
254 sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
255 sav_tm.tm_hour,sav_tm.tm_sec);
259 local_time = mktime(&my_tm);
260 ok(local_time == ref, "Unnormalized mktime returned %u, expected %u\n",
261 (DWORD)local_time, (DWORD)ref);
262 ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
263 my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
264 my_tm.tm_sec == sav_tm.tm_sec,
265 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
266 my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
267 my_tm.tm_hour,my_tm.tm_sec,
268 sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
269 sav_tm.tm_hour,sav_tm.tm_sec);
273 local_time = mktime(&my_tm);
274 ok(local_time == ref, "Unnormalized mktime returned %u, expected %u\n",
275 (DWORD)local_time, (DWORD)ref);
276 ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
277 my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
278 my_tm.tm_sec == sav_tm.tm_sec,
279 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
280 my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
281 my_tm.tm_hour,my_tm.tm_sec,
282 sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
283 sav_tm.tm_hour,sav_tm.tm_sec);
284 /* now a bad time example */
287 local_time = mktime(&my_tm);
288 ok((local_time == -1), "(bad time) mktime returned %d, expected -1\n", (int)local_time);
291 /* TEST that we are independent from the TZ variable */
292 /*Argh, msvcrt doesn't have setenv() */
293 _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
295 nulltime = mktime(&my_tm);
296 ok(nulltime == ref,"mktime returned 0x%08x\n",(DWORD)nulltime);
300 static void test_localtime(void)
302 TIME_ZONE_INFORMATION tzinfo;
303 DWORD res = GetTimeZoneInformation(&tzinfo);
308 int year = get_test_year( &ref );
309 int is_leap = !(year % 4) && ((year % 100) || !((year + 300) % 400));
311 gmt = ref + SECSPERDAY + tzinfo.Bias * SECSPERMIN;
312 ok (res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
313 lt = localtime(&gmt);
314 gmt += (lt->tm_isdst ? tzinfo.DaylightBias : tzinfo.StandardBias) * SECSPERMIN;
315 lt = localtime(&gmt);
316 ok(((lt->tm_year == year) && (lt->tm_mon == 0) && (lt->tm_yday == 1) &&
317 (lt->tm_mday == 2) && (lt->tm_hour == 0) &&
318 (lt->tm_min == 0) && (lt->tm_sec == 0)),
319 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
320 lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour,
321 lt->tm_min, lt->tm_sec, lt->tm_isdst);
323 _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
325 lt = localtime(&gmt);
326 ok(((lt->tm_year == year) && (lt->tm_mon == 0) && (lt->tm_yday == 1) &&
327 (lt->tm_mday == 2) && (lt->tm_hour == 0) &&
328 (lt->tm_min == 0) && (lt->tm_sec == 0)),
329 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
330 lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour,
331 lt->tm_min, lt->tm_sec, lt->tm_isdst);
335 gmt = ref + 202 * SECSPERDAY + tzinfo.Bias * SECSPERMIN;
336 lt = localtime(&gmt);
337 gmt += (lt->tm_isdst ? tzinfo.DaylightBias : tzinfo.StandardBias) * SECSPERMIN;
338 lt = localtime(&gmt);
339 ok(((lt->tm_year == year) && (lt->tm_mon == 6) && (lt->tm_yday == 202) &&
340 (lt->tm_mday == 22 - is_leap) && (lt->tm_hour == 0) &&
341 (lt->tm_min == 0) && (lt->tm_sec == 0)),
342 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
343 lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour,
344 lt->tm_min, lt->tm_sec, lt->tm_isdst);
347 static void test_strdate(void)
349 char date[16], * result;
350 int month, day, year, count, len;
353 result = _strdate(date);
354 ok(result == date, "Wrong return value\n");
356 ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
357 count = sscanf(date, "%02d/%02d/%02d", &month, &day, &year);
358 ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
361 win_skip("Skipping _strdate_s tests\n");
366 err = p_strdate_s(NULL, 1);
367 ok(err == EINVAL, "err = %d\n", err);
368 ok(errno == EINVAL, "errno = %d\n", errno);
372 err = p_strdate_s(date, 8);
373 ok(err == ERANGE, "err = %d\n", err);
374 ok(errno == ERANGE, "errno = %d\n", errno);
375 ok(date[0] == '\0', "date[0] != '\\0'\n");
376 ok(date[1] == 'x', "date[1] != 'x'\n");
378 err = p_strdate_s(date, 9);
379 ok(err == 0, "err = %x\n", err);
382 static void test_strtime(void)
384 char time[16], * result;
385 int hour, minute, second, count, len;
388 result = _strtime(time);
389 ok(result == time, "Wrong return value\n");
391 ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
392 count = sscanf(time, "%02d:%02d:%02d", &hour, &minute, &second);
393 ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
396 win_skip("Skipping _strtime_s tests\n");
401 err = p_strtime_s(NULL, 0);
402 ok(err == EINVAL, "err = %d\n", err);
403 ok(errno == EINVAL, "errno = %d\n", errno);
405 err = p_strtime_s(NULL, 1);
406 ok(err == EINVAL, "err = %d\n", err);
407 ok(errno == EINVAL, "errno = %d\n", errno);
410 err = p_strtime_s(time, 8);
411 ok(err == ERANGE, "err = %d\n", err);
412 ok(errno == ERANGE, "errno = %d\n", errno);
413 ok(time[0] == '\0', "time[0] != '\\0'\n");
415 err = p_strtime_s(time, 9);
416 ok(err == 0, "err = %x\n", err);
419 static void test_wstrdate(void)
421 wchar_t date[16], * result;
422 int month, day, year, count, len;
423 wchar_t format[] = { '%','0','2','d','/','%','0','2','d','/','%','0','2','d',0 };
425 result = _wstrdate(date);
426 ok(result == date, "Wrong return value\n");
428 ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
429 count = swscanf(date, format, &month, &day, &year);
430 ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
433 static void test_wstrtime(void)
435 wchar_t time[16], * result;
436 int hour, minute, second, count, len;
437 wchar_t format[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',0 };
439 result = _wstrtime(time);
440 ok(result == time, "Wrong return value\n");
442 ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
443 count = swscanf(time, format, &hour, &minute, &second);
444 ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
447 static void test_localtime32_s(void)
453 if (!p_localtime32_s)
455 win_skip("Skipping _localtime32_s tests\n");
460 err = p_localtime32_s(NULL, NULL);
461 ok(err == EINVAL, "Expected _localtime32_s to return EINVAL, got %d\n", err);
462 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
466 err = p_localtime32_s(NULL, &time);
467 ok(err == EINVAL, "Expected _localtime32_s to return EINVAL, got %d\n", err);
468 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
470 memset(&tm, 0, sizeof(tm));
472 err = p_localtime32_s(&tm, NULL);
473 ok(err == EINVAL, "Expected _localtime32_s to return EINVAL, got %d\n", err);
474 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
475 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
476 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
477 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
478 "Expected tm structure members to be initialized to -1, got "
479 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
480 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
483 memset(&tm, 0, sizeof(tm));
486 err = p_localtime32_s(&tm, &time);
487 ok(err == EINVAL, "Expected _localtime32_s to return EINVAL, got %d\n", err);
488 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
489 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
490 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
491 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
492 "Expected tm structure members to be initialized to -1, got "
493 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
494 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
498 static void test_localtime64_s(void)
504 if (!p_localtime64_s)
506 win_skip("Skipping _localtime64_s tests\n");
511 err = p_localtime64_s(NULL, NULL);
512 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
513 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
517 err = p_localtime64_s(NULL, &time);
518 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
519 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
521 memset(&tm, 0, sizeof(tm));
523 err = p_localtime64_s(&tm, NULL);
524 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
525 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
526 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
527 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
528 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
529 "Expected tm structure members to be initialized to -1, got "
530 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
531 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
534 memset(&tm, 0, sizeof(tm));
537 err = p_localtime64_s(&tm, &time);
538 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
539 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
540 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
541 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
542 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
543 "Expected tm structure members to be initialized to -1, got "
544 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
545 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
548 memset(&tm, 0, sizeof(tm));
549 time = _MAX__TIME64_T + 1;
551 err = p_localtime64_s(&tm, &time);
552 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
553 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
554 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
555 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
556 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
557 "Expected tm structure members to be initialized to -1, got "
558 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
559 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
563 static void test_daylight(void)
569 win_skip("__daylight() not available\n");
573 if (!p___p__daylight)
575 win_skip("__p__daylight not available\n");
579 ret1 = p__daylight();
580 ret2 = p___p__daylight();
581 ok(ret1 && ret1 == ret2, "got %p\n", ret1);
584 static void test_strftime(void)
586 static const wchar_t cW[] = { '%','c',0 };
587 static const char expected[] = "01/01/70 00:00:00";
590 char buf[256], bufA[256];
594 if (!p_strftime || !p_wcsftime || !p_gmtime)
596 win_skip("strftime, wcsftime or gmtime is not available\n");
600 setlocale(LC_TIME, "C");
603 gmt_tm = p_gmtime(&gmt);
604 ok(gmt_tm != NULL, "gmtime failed\n");
607 retA = strftime(NULL, 0, "copy", gmt_tm);
608 ok(retA == 0, "expected 0, got %ld\n", retA);
609 ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
611 retA = strftime(bufA, 256, "copy", NULL);
612 ok(retA == 4, "expected 4, got %ld\n", retA);
613 ok(!strcmp(bufA, "copy"), "got %s\n", bufA);
615 retA = strftime(bufA, 256, "copy it", gmt_tm);
616 ok(retA == 7, "expected 7, got %ld\n", retA);
617 ok(!strcmp(bufA, "copy it"), "got %s\n", bufA);
620 retA = strftime(bufA, 2, "copy", gmt_tm);
621 ok(retA == 0, "expected 0, got %ld\n", retA);
622 ok(!strcmp(bufA, "") || broken(!strcmp(bufA, "copy it")), "got %s\n", bufA);
623 ok(errno==ERANGE || errno==0xdeadbeef, "errno = %d\n", errno);
626 retA = strftime(bufA, 256, "a%e", gmt_tm);
627 ok(retA==0 || broken(retA==1), "expected 0, got %ld\n", retA);
628 ok(!strcmp(bufA, "") || broken(!strcmp(bufA, "a")), "got %s\n", bufA);
629 ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
631 if(0) { /* crashes on Win2k */
633 retA = strftime(bufA, 256, "%c", NULL);
634 ok(retA == 0, "expected 0, got %ld\n", retA);
635 ok(!strcmp(bufA, ""), "got %s\n", bufA);
636 ok(errno == EINVAL, "errno = %d\n", errno);
639 retA = strftime(bufA, 256, "e%#%e", gmt_tm);
640 ok(retA == 3, "expected 3, got %ld\n", retA);
641 ok(!strcmp(bufA, "e%e"), "got %s\n", bufA);
643 retA = strftime(bufA, 256, "%c", gmt_tm);
644 ok(retA == 17, "expected 17, got %ld\n", retA);
645 ok(strcmp(bufA, expected) == 0, "expected %s, got %s\n", expected, bufA);
647 retW = wcsftime(bufW, 256, cW, gmt_tm);
648 ok(retW == 17, "expected 17, got %ld\n", retW);
649 ok(retA == retW, "expected %ld, got %ld\n", retA, retW);
651 retA = WideCharToMultiByte(CP_ACP, 0, bufW, retW, buf, 256, NULL, NULL);
653 ok(strcmp(bufA, buf) == 0, "expected %s, got %s\n", bufA, buf);
655 retA = strftime(bufA, 256, "%x", gmt_tm);
656 ok(retA == 8, "expected 8, got %ld\n", retA);
657 ok(!strcmp(bufA, "01/01/70"), "got %s\n", bufA);
659 retA = strftime(bufA, 256, "%X", gmt_tm);
660 ok(retA == 8, "expected 8, got %ld\n", retA);
661 ok(!strcmp(bufA, "00:00:00"), "got %s\n", bufA);
663 retA = strftime(bufA, 256, "%a", gmt_tm);
664 ok(retA == 3, "expected 3, got %ld\n", retA);
665 ok(!strcmp(bufA, "Thu"), "got %s\n", bufA);
667 retA = strftime(bufA, 256, "%A", gmt_tm);
668 ok(retA == 8, "expected 8, got %ld\n", retA);
669 ok(!strcmp(bufA, "Thursday"), "got %s\n", bufA);
671 retA = strftime(bufA, 256, "%b", gmt_tm);
672 ok(retA == 3, "expected 3, got %ld\n", retA);
673 ok(!strcmp(bufA, "Jan"), "got %s\n", bufA);
675 retA = strftime(bufA, 256, "%B", gmt_tm);
676 ok(retA == 7, "expected 7, got %ld\n", retA);
677 ok(!strcmp(bufA, "January"), "got %s\n", bufA);
679 retA = strftime(bufA, 256, "%d", gmt_tm);
680 ok(retA == 2, "expected 2, got %ld\n", retA);
681 ok(!strcmp(bufA, "01"), "got %s\n", bufA);
683 retA = strftime(bufA, 256, "%#d", gmt_tm);
684 ok(retA == 1, "expected 1, got %ld\n", retA);
685 ok(!strcmp(bufA, "1"), "got %s\n", bufA);
687 retA = strftime(bufA, 256, "%H", gmt_tm);
688 ok(retA == 2, "expected 2, got %ld\n", retA);
689 ok(!strcmp(bufA, "00"), "got %s\n", bufA);
691 retA = strftime(bufA, 256, "%I", gmt_tm);
692 ok(retA == 2, "expected 2, got %ld\n", retA);
693 ok(!strcmp(bufA, "12"), "got %s\n", bufA);
695 retA = strftime(bufA, 256, "%j", gmt_tm);
696 ok(retA == 3, "expected 3, got %ld\n", retA);
697 ok(!strcmp(bufA, "001"), "got %s\n", bufA);
699 retA = strftime(bufA, 256, "%m", gmt_tm);
700 ok(retA == 2, "expected 2, got %ld\n", retA);
701 ok(!strcmp(bufA, "01"), "got %s\n", bufA);
703 retA = strftime(bufA, 256, "%#M", gmt_tm);
704 ok(retA == 1, "expected 1, got %ld\n", retA);
705 ok(!strcmp(bufA, "0"), "got %s\n", bufA);
707 retA = strftime(bufA, 256, "%p", gmt_tm);
708 ok(retA == 2, "expected 2, got %ld\n", retA);
709 ok(!strcmp(bufA, "AM"), "got %s\n", bufA);
711 retA = strftime(bufA, 256, "%U", gmt_tm);
712 ok(retA == 2, "expected 2, got %ld\n", retA);
713 ok(!strcmp(bufA, "00"), "got %s\n", bufA);
715 retA = strftime(bufA, 256, "%W", gmt_tm);
716 ok(retA == 2, "expected 2, got %ld\n", retA);
717 ok(!strcmp(bufA, "00"), "got %s\n", bufA);
720 retA = strftime(bufA, 256, "%U", gmt_tm);
721 ok(retA == 2, "expected 2, got %ld\n", retA);
722 ok(!strcmp(bufA, "01"), "got %s\n", bufA);
724 retA = strftime(bufA, 256, "%W", gmt_tm);
725 ok(retA == 2, "expected 2, got %ld\n", retA);
726 ok(!strcmp(bufA, "00"), "got %s\n", bufA);
728 gmt_tm->tm_yday = 365;
729 retA = strftime(bufA, 256, "%U", gmt_tm);
730 ok(retA == 2, "expected 2, got %ld\n", retA);
731 ok(!strcmp(bufA, "53"), "got %s\n", bufA);
733 retA = strftime(bufA, 256, "%W", gmt_tm);
734 ok(retA == 2, "expected 2, got %ld\n", retA);
735 ok(!strcmp(bufA, "52"), "got %s\n", bufA);
738 gmt_tm->tm_mday = 30;
739 retA = strftime(bufA, 256, "%c", gmt_tm);
741 ok(retA == 17, "expected 17, got %ld\n", retA);
742 ok(!strcmp(bufA, "02/30/70 00:00:00"), "got %s\n", bufA);
746 static void test_asctime(void)
752 if(!p_asctime || !p_gmtime)
754 win_skip("asctime or gmtime is not available\n");
759 gmt_tm = p_gmtime(&gmt);
760 ret = p_asctime(gmt_tm);
761 ok(!strcmp(ret, "Thu Jan 01 00:00:00 1970\n"), "asctime retunred %s\n", ret);
764 gmt_tm = p_gmtime(&gmt);
765 ret = p_asctime(gmt_tm);
766 ok(!strcmp(ret, "Mon Nov 26 02:58:41 1979\n"), "asctime retunred %s\n", ret);
768 /* Week day is only checked if it's in 0..6 range */
770 ret = p_asctime(gmt_tm);
771 ok(!strcmp(ret, "Wed Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret);
775 ret = p_asctime(gmt_tm);
776 ok(!ret || broken(!ret[0]), "asctime returned %s\n", ret);
777 ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
779 /* Year day is ignored */
781 gmt_tm->tm_yday = 1300;
782 ret = p_asctime(gmt_tm);
783 ok(!strcmp(ret, "Wed Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret);
785 /* Dates that can't be displayed using 26 characters are broken */
786 gmt_tm->tm_mday = 28;
787 gmt_tm->tm_year = 8100;
788 ret = p_asctime(gmt_tm);
789 ok(!strcmp(ret, "Wed Nov 28 02:58:41 :000\n"), "asctime returned %s\n", ret);
791 gmt_tm->tm_year = 264100;
792 ret = p_asctime(gmt_tm);
793 ok(!strcmp(ret, "Wed Nov 28 02:58:41 :000\n"), "asctime returned %s\n", ret);
795 /* asctime works from year 1900 */
797 gmt_tm->tm_year = -1;
798 ret = p_asctime(gmt_tm);
799 ok(!ret || broken(!strcmp(ret, "Wed Nov 28 02:58:41 190/\n")), "asctime returned %s\n", ret);
800 ok(errno==EINVAL || broken(errno == 0xdeadbeef), "errno = %d\n", errno);
804 gmt_tm->tm_mday = 30;
805 gmt_tm->tm_year = 79;
806 ret = p_asctime(gmt_tm);
807 ok(!ret || broken(!strcmp(ret, "Wed Feb 30 02:58:41 1979\n")), "asctime returned %s\n", ret);
808 ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
811 static void test__tzset(void)
816 if(!p___p__daylight || !p___p__timezone || !p___p__dstbias) {
817 win_skip("__p__daylight, __p__timezone or __p__dstbias is not available\n");
821 _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
823 ret = *p___p__daylight();
824 ok(ret == 1, "*__p__daylight() = %d\n", ret);
825 ret = *p___p__timezone();
826 ok(ret == 28800, "*__p__timezone() = %d\n", ret);
827 ret = *p___p__dstbias();
828 ok(ret == -3600, "*__p__dstbias() = %d\n", ret);
830 _putenv("TZ=xxx+1yyy");
832 ret = *p___p__daylight();
833 ok(ret == 121, "*__p__daylight() = %d\n", ret);
834 ret = *p___p__timezone();
835 ok(ret == 3600, "*__p__timezone() = %d\n", ret);
836 ret = *p___p__dstbias();
837 ok(ret == -3600, "*__p__dstbias() = %d\n", ret);
839 *p___p__dstbias() = 0;
840 _putenv("TZ=xxx+1:3:5zzz");
842 ret = *p___p__daylight();
843 ok(ret == 122, "*__p__daylight() = %d\n", ret);
844 ret = *p___p__timezone();
845 ok(ret == 3785, "*__p__timezone() = %d\n", ret);
846 ret = *p___p__dstbias();
847 ok(ret == 0, "*__p__dstbias() = %d\n", ret);
866 test_localtime32_s();
867 test_localtime64_s();