win32u: Use the dummy surface for empty layered window surfaces.
[wine.git] / dlls / msvcrt / tests / time.c
blobaba911f30a470e0ce10f50da62959ff99203a983
1 /*
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"
22 #include "winbase.h"
23 #include "winnls.h"
24 #include "time.h"
26 #include <stdlib.h> /*setenv*/
27 #include <stdio.h> /*printf*/
28 #include <locale.h>
29 #include <errno.h>
31 #define _MAX__TIME64_T (((__time64_t)0x00000007 << 32) | 0x93406FFF)
33 #define SECSPERDAY 86400
34 #define SECSPERHOUR 3600
35 #define SECSPERMIN 60
36 #define MINSPERHOUR 60
37 #define HOURSPERDAY 24
39 typedef struct {
40 const char *short_wday[7];
41 const char *wday[7];
42 const char *short_mon[12];
43 const char *mon[12];
44 const char *am;
45 const char *pm;
46 const char *short_date;
47 const char *date;
48 const char *time;
49 LCID lcid;
50 int unk;
51 int refcount;
52 } __lc_time_data;
54 static __time32_t (__cdecl *p_mkgmtime32)(struct tm*);
55 static struct tm* (__cdecl *p_gmtime32)(__time32_t*);
56 static struct tm* (__cdecl *p_gmtime)(time_t*);
57 static errno_t (__cdecl *p_gmtime32_s)(struct tm*, __time32_t*);
58 static struct tm* (__cdecl *p_gmtime64)(__time64_t*);
59 static errno_t (__cdecl *p_gmtime64_s)(struct tm*, __time64_t*);
60 static errno_t (__cdecl *p_strtime_s)(char*,size_t);
61 static errno_t (__cdecl *p_strdate_s)(char*,size_t);
62 static errno_t (__cdecl *p_localtime32_s)(struct tm*, __time32_t*);
63 static errno_t (__cdecl *p_localtime64_s)(struct tm*, __time64_t*);
64 static int* (__cdecl *p__daylight)(void);
65 static int* (__cdecl *p___p__daylight)(void);
66 static long* (__cdecl *p___p__dstbias)(void);
67 static long* (__cdecl *p__dstbias)(void);
68 static long* (__cdecl *p___p__timezone)(void);
69 static size_t (__cdecl *p_strftime)(char *, size_t, const char *, const struct tm *);
70 static size_t (__cdecl *p__Strftime)(char*, size_t, const char*, const struct tm*, void*);
71 static size_t (__cdecl *p_wcsftime)(wchar_t *, size_t, const wchar_t *, const struct tm *);
72 static char* (__cdecl *p_asctime)(const struct tm *);
74 static void init(void)
76 HMODULE hmod = LoadLibraryA("msvcrt.dll");
78 p_gmtime32 = (void*)GetProcAddress(hmod, "_gmtime32");
79 p_gmtime = (void*)GetProcAddress(hmod, "gmtime");
80 p_gmtime32_s = (void*)GetProcAddress(hmod, "_gmtime32_s");
81 p_gmtime64 = (void*)GetProcAddress(hmod, "_gmtime64");
82 p_gmtime64_s = (void*)GetProcAddress(hmod, "_gmtime64_s");
83 p_mkgmtime32 = (void*)GetProcAddress(hmod, "_mkgmtime32");
84 p_strtime_s = (void*)GetProcAddress(hmod, "_strtime_s");
85 p_strdate_s = (void*)GetProcAddress(hmod, "_strdate_s");
86 p_localtime32_s = (void*)GetProcAddress(hmod, "_localtime32_s");
87 p_localtime64_s = (void*)GetProcAddress(hmod, "_localtime64_s");
88 p__daylight = (void*)GetProcAddress(hmod, "__daylight");
89 p___p__daylight = (void*)GetProcAddress(hmod, "__p__daylight");
90 p___p__dstbias = (void*)GetProcAddress(hmod, "__p__dstbias");
91 p__dstbias = (void*)GetProcAddress(hmod, "__dstbias");
92 p___p__timezone = (void*)GetProcAddress(hmod, "__p__timezone");
93 p_strftime = (void*)GetProcAddress(hmod, "strftime");
94 p__Strftime = (void*)GetProcAddress(hmod, "_Strftime");
95 p_wcsftime = (void*)GetProcAddress(hmod, "wcsftime");
96 p_asctime = (void*)GetProcAddress(hmod, "asctime");
99 static int get_test_year(time_t *start)
101 time_t now = time(NULL);
102 struct tm *tm = localtime(&now);
104 /* compute start of year in seconds */
105 *start = SECSPERDAY * ((tm->tm_year - 70) * 365 +
106 (tm->tm_year - 69) / 4 -
107 (tm->tm_year - 1) / 100 +
108 (tm->tm_year + 299) / 400);
109 return tm->tm_year;
112 static void test_ctime(void)
114 time_t badtime = -1;
115 char* ret;
116 ret = ctime(&badtime);
117 ok(ret == NULL, "expected ctime to return NULL, got %s\n", ret);
119 static void test_gmtime(void)
121 __time32_t valid, gmt;
122 struct tm* gmt_tm, gmt_tm_s;
123 errno_t err;
125 if(!p_gmtime32) {
126 win_skip("Skipping _gmtime32 tests\n");
127 return;
130 gmt_tm = p_gmtime32(NULL);
131 ok(gmt_tm == NULL, "gmt_tm != NULL\n");
133 gmt = -1;
134 gmt_tm = p_gmtime32(&gmt);
135 ok(gmt_tm==NULL || broken(gmt_tm->tm_year==70 && gmt_tm->tm_sec<0), "gmt_tm != NULL\n");
137 gmt = valid = 0;
138 gmt_tm = p_gmtime32(&gmt);
139 if(!gmt_tm) {
140 ok(0, "_gmtime32() failed\n");
141 return;
144 ok(((gmt_tm->tm_year == 70) && (gmt_tm->tm_mon == 0) && (gmt_tm->tm_yday == 0) &&
145 (gmt_tm->tm_mday == 1) && (gmt_tm->tm_wday == 4) && (gmt_tm->tm_hour == 0) &&
146 (gmt_tm->tm_min == 0) && (gmt_tm->tm_sec == 0) && (gmt_tm->tm_isdst == 0)),
147 "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n",
148 gmt_tm->tm_year, gmt_tm->tm_mon, gmt_tm->tm_yday, gmt_tm->tm_mday, gmt_tm->tm_wday,
149 gmt_tm->tm_hour, gmt_tm->tm_min, gmt_tm->tm_sec, gmt_tm->tm_isdst);
151 if(!p_mkgmtime32) {
152 win_skip("Skipping _mkgmtime32 tests\n");
153 return;
156 gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
157 gmt = p_mkgmtime32(gmt_tm);
158 ok(gmt == valid, "gmt = %lu\n", gmt);
159 ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
160 ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
162 gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
163 gmt_tm->tm_isdst = -1;
164 gmt = p_mkgmtime32(gmt_tm);
165 ok(gmt == valid, "gmt = %lu\n", gmt);
166 ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
167 ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
169 gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
170 gmt_tm->tm_isdst = 1;
171 gmt = p_mkgmtime32(gmt_tm);
172 ok(gmt == valid, "gmt = %lu\n", gmt);
173 ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
174 ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
176 gmt = valid = 173921;
177 gmt_tm = p_gmtime32(&gmt);
178 if(!gmt_tm) {
179 ok(0, "_gmtime32() failed\n");
180 return;
183 gmt_tm->tm_isdst = -1;
184 gmt = p_mkgmtime32(gmt_tm);
185 ok(gmt == valid, "gmt = %lu\n", gmt);
186 ok(gmt_tm->tm_wday == 6, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
187 ok(gmt_tm->tm_yday == 2, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
189 gmt_tm->tm_isdst = 1;
190 gmt = p_mkgmtime32(gmt_tm);
191 ok(gmt == valid, "gmt = %lu\n", gmt);
193 if(!p_gmtime32_s) {
194 win_skip("Skipping _gmtime32_s tests\n");
195 return;
198 errno = 0;
199 gmt = 0;
200 err = p_gmtime32_s(NULL, &gmt);
201 ok(err == EINVAL, "err = %d\n", err);
202 ok(errno == EINVAL, "errno = %d\n", errno);
204 errno = 0;
205 gmt = -1;
206 err = p_gmtime32_s(&gmt_tm_s, &gmt);
207 ok(gmt_tm_s.tm_year == -1 || broken(gmt_tm_s.tm_year == 70 && gmt_tm_s.tm_sec < 0),
208 "tm_year = %d, tm_sec = %d\n", gmt_tm_s.tm_year, gmt_tm_s.tm_sec);
209 if(gmt_tm_s.tm_year == -1) {
210 ok(err==EINVAL, "err = %d\n", err);
211 ok(errno==EINVAL, "errno = %d\n", errno);
215 static void test_gmtime64(void)
217 struct tm *ptm, tm;
218 __time64_t t;
219 int ret;
221 t = -1;
222 memset(&tm, 0xcc, sizeof(tm));
223 ptm = p_gmtime64(&t);
224 if (!ptm)
226 skip("Old gmtime64 limits, skipping tests.\n");
227 return;
229 ok(!!ptm, "got NULL.\n");
230 ret = p_gmtime64_s(&tm, &t);
231 ok(!ret, "got %d.\n", ret);
232 ok(tm.tm_year == 69 && tm.tm_hour == 23 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n",
233 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
235 t = -43200;
236 memset(&tm, 0xcc, sizeof(tm));
237 ptm = p_gmtime64(&t);
238 ok(!!ptm, "got NULL.\n");
239 ret = p_gmtime64_s(&tm, &t);
240 ok(!ret, "got %d.\n", ret);
241 ok(tm.tm_year == 69 && tm.tm_hour == 12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n",
242 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
243 ptm = p_gmtime32((__time32_t *)&t);
244 ok(!!ptm, "got NULL.\n");
245 memset(&tm, 0xcc, sizeof(tm));
246 ret = p_gmtime32_s(&tm, (__time32_t *)&t);
247 ok(!ret, "got %d.\n", ret);
248 todo_wine_if(tm.tm_year == 69 && tm.tm_hour == 12)
249 ok(tm.tm_year == 70 && tm.tm_hour == -12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n",
250 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
252 t = -43201;
253 ptm = p_gmtime64(&t);
254 ok(!ptm, "got non-NULL.\n");
255 memset(&tm, 0xcc, sizeof(tm));
256 ret = p_gmtime64_s(&tm, &t);
257 ok(ret == EINVAL, "got %d.\n", ret);
258 ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n",
259 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
260 ptm = p_gmtime32((__time32_t *)&t);
261 ok(!ptm, "got NULL.\n");
262 memset(&tm, 0xcc, sizeof(tm));
263 ret = p_gmtime32_s(&tm, (__time32_t *)&t);
264 ok(ret == EINVAL, "got %d.\n", ret);
265 ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n",
266 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
268 t = _MAX__TIME64_T + 46800;
269 memset(&tm, 0xcc, sizeof(tm));
270 ptm = p_gmtime64(&t);
271 ok(!!ptm, "got NULL.\n");
272 ret = p_gmtime64_s(&tm, &t);
273 ok(!ret, "got %d.\n", ret);
274 ok(tm.tm_year == 1101 && tm.tm_hour == 20 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n",
275 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
277 t = _MAX__TIME64_T + 46801;
278 ptm = p_gmtime64(&t);
279 ok(!ptm, "got non-NULL.\n");
280 memset(&tm, 0xcc, sizeof(tm));
281 ret = p_gmtime64_s(&tm, &t);
282 ok(ret == EINVAL, "got %d.\n", ret);
283 ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n",
284 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
287 static void test_mktime(void)
289 TIME_ZONE_INFORMATION tzinfo;
290 DWORD res = GetTimeZoneInformation(&tzinfo);
291 struct tm my_tm, sav_tm;
292 time_t nulltime, local_time;
293 char TZ_env[256];
294 char buffer[64];
295 int year;
296 time_t ref, secs;
298 year = get_test_year( &ref );
299 ref += SECSPERDAY;
301 ok (res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
302 WideCharToMultiByte( CP_ACP, 0, tzinfo.StandardName, -1, buffer, sizeof(buffer), NULL, NULL );
303 trace( "bias %ld std %ld dst %ld zone %s\n",
304 tzinfo.Bias, tzinfo.StandardBias, tzinfo.DaylightBias, buffer );
305 /* Bias may be positive or negative, to use offset of one day */
306 my_tm = *localtime(&ref); /* retrieve current dst flag */
307 secs = SECSPERDAY - tzinfo.Bias * SECSPERMIN;
308 secs -= (my_tm.tm_isdst ? tzinfo.DaylightBias : tzinfo.StandardBias) * SECSPERMIN;
309 my_tm.tm_mday = 1 + secs/SECSPERDAY;
310 secs = secs % SECSPERDAY;
311 my_tm.tm_hour = secs / SECSPERHOUR;
312 secs = secs % SECSPERHOUR;
313 my_tm.tm_min = secs / SECSPERMIN;
314 secs = secs % SECSPERMIN;
315 my_tm.tm_sec = secs;
317 my_tm.tm_year = year;
318 my_tm.tm_mon = 0;
320 sav_tm = my_tm;
322 local_time = mktime(&my_tm);
323 ok(local_time == ref, "mktime returned %lu, expected %lu\n",
324 (DWORD)local_time, (DWORD)ref);
325 /* now test some unnormalized struct tm's */
326 my_tm = sav_tm;
327 my_tm.tm_sec += 60;
328 my_tm.tm_min -= 1;
329 local_time = mktime(&my_tm);
330 ok(local_time == ref, "Unnormalized mktime returned %lu, expected %lu\n",
331 (DWORD)local_time, (DWORD)ref);
332 ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
333 my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
334 my_tm.tm_sec == sav_tm.tm_sec,
335 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
336 my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
337 my_tm.tm_hour,my_tm.tm_sec,
338 sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
339 sav_tm.tm_hour,sav_tm.tm_sec);
340 my_tm = sav_tm;
341 my_tm.tm_min -= 60;
342 my_tm.tm_hour += 1;
343 local_time = mktime(&my_tm);
344 ok(local_time == ref, "Unnormalized mktime returned %lu, expected %lu\n",
345 (DWORD)local_time, (DWORD)ref);
346 ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
347 my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
348 my_tm.tm_sec == sav_tm.tm_sec,
349 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
350 my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
351 my_tm.tm_hour,my_tm.tm_sec,
352 sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
353 sav_tm.tm_hour,sav_tm.tm_sec);
354 my_tm = sav_tm;
355 my_tm.tm_mon -= 12;
356 my_tm.tm_year += 1;
357 local_time = mktime(&my_tm);
358 ok(local_time == ref, "Unnormalized mktime returned %lu, expected %lu\n",
359 (DWORD)local_time, (DWORD)ref);
360 ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
361 my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
362 my_tm.tm_sec == sav_tm.tm_sec,
363 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
364 my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
365 my_tm.tm_hour,my_tm.tm_sec,
366 sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
367 sav_tm.tm_hour,sav_tm.tm_sec);
368 my_tm = sav_tm;
369 my_tm.tm_mon += 12;
370 my_tm.tm_year -= 1;
371 local_time = mktime(&my_tm);
372 ok(local_time == ref, "Unnormalized mktime returned %lu, expected %lu\n",
373 (DWORD)local_time, (DWORD)ref);
374 ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
375 my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
376 my_tm.tm_sec == sav_tm.tm_sec,
377 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
378 my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
379 my_tm.tm_hour,my_tm.tm_sec,
380 sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
381 sav_tm.tm_hour,sav_tm.tm_sec);
382 /* now a bad time example */
383 my_tm = sav_tm;
384 my_tm.tm_year = 69;
385 local_time = mktime(&my_tm);
386 ok((local_time == -1), "(bad time) mktime returned %d, expected -1\n", (int)local_time);
388 my_tm = sav_tm;
389 /* TEST that we are independent from the TZ variable */
390 /*Argh, msvcrt doesn't have setenv() */
391 _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
392 putenv("TZ=GMT");
393 nulltime = mktime(&my_tm);
394 ok(nulltime == ref,"mktime returned 0x%08lx\n",(DWORD)nulltime);
395 putenv(TZ_env);
398 static void test_localtime(void)
400 TIME_ZONE_INFORMATION tzinfo;
401 DWORD res = GetTimeZoneInformation(&tzinfo);
402 time_t gmt, ref;
404 char TZ_env[256];
405 struct tm* lt;
406 int year = get_test_year( &ref );
407 int is_leap = !(year % 4) && ((year % 100) || !((year + 300) % 400));
409 gmt = ref + SECSPERDAY + tzinfo.Bias * SECSPERMIN;
410 ok (res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
411 lt = localtime(&gmt);
412 gmt += (lt->tm_isdst ? tzinfo.DaylightBias : tzinfo.StandardBias) * SECSPERMIN;
413 lt = localtime(&gmt);
414 ok(((lt->tm_year == year) && (lt->tm_mon == 0) && (lt->tm_yday == 1) &&
415 (lt->tm_mday == 2) && (lt->tm_hour == 0) &&
416 (lt->tm_min == 0) && (lt->tm_sec == 0)),
417 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
418 lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour,
419 lt->tm_min, lt->tm_sec, lt->tm_isdst);
421 _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
422 putenv("TZ=GMT");
423 lt = localtime(&gmt);
424 ok(((lt->tm_year == year) && (lt->tm_mon == 0) && (lt->tm_yday == 1) &&
425 (lt->tm_mday == 2) && (lt->tm_hour == 0) &&
426 (lt->tm_min == 0) && (lt->tm_sec == 0)),
427 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
428 lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour,
429 lt->tm_min, lt->tm_sec, lt->tm_isdst);
430 putenv(TZ_env);
432 /* June 22 */
433 gmt = ref + 202 * SECSPERDAY + tzinfo.Bias * SECSPERMIN;
434 lt = localtime(&gmt);
435 gmt += (lt->tm_isdst ? tzinfo.DaylightBias : tzinfo.StandardBias) * SECSPERMIN;
436 lt = localtime(&gmt);
437 ok(((lt->tm_year == year) && (lt->tm_mon == 6) && (lt->tm_yday == 202) &&
438 (lt->tm_mday == 22 - is_leap) && (lt->tm_hour == 0) &&
439 (lt->tm_min == 0) && (lt->tm_sec == 0)),
440 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
441 lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour,
442 lt->tm_min, lt->tm_sec, lt->tm_isdst);
445 static void test_strdate(void)
447 char date[16], * result;
448 int month, day, year, count, len;
449 errno_t err;
451 result = _strdate(date);
452 ok(result == date, "Wrong return value\n");
453 len = strlen(date);
454 ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
455 count = sscanf(date, "%02d/%02d/%02d", &month, &day, &year);
456 ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
458 if(!p_strdate_s) {
459 win_skip("Skipping _strdate_s tests\n");
460 return;
463 errno = 0;
464 err = p_strdate_s(NULL, 1);
465 ok(err == EINVAL, "err = %d\n", err);
466 ok(errno == EINVAL, "errno = %d\n", errno);
468 date[0] = 'x';
469 date[1] = 'x';
470 err = p_strdate_s(date, 8);
471 ok(err == ERANGE, "err = %d\n", err);
472 ok(errno == ERANGE, "errno = %d\n", errno);
473 ok(date[0] == '\0', "date[0] != '\\0'\n");
474 ok(date[1] == 'x', "date[1] != 'x'\n");
476 err = p_strdate_s(date, 9);
477 ok(err == 0, "err = %x\n", err);
480 static void test_strtime(void)
482 char time[16], * result;
483 int hour, minute, second, count, len;
484 errno_t err;
486 result = _strtime(time);
487 ok(result == time, "Wrong return value\n");
488 len = strlen(time);
489 ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
490 count = sscanf(time, "%02d:%02d:%02d", &hour, &minute, &second);
491 ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
493 if(!p_strtime_s) {
494 win_skip("Skipping _strtime_s tests\n");
495 return;
498 errno = 0;
499 err = p_strtime_s(NULL, 0);
500 ok(err == EINVAL, "err = %d\n", err);
501 ok(errno == EINVAL, "errno = %d\n", errno);
503 err = p_strtime_s(NULL, 1);
504 ok(err == EINVAL, "err = %d\n", err);
505 ok(errno == EINVAL, "errno = %d\n", errno);
507 time[0] = 'x';
508 err = p_strtime_s(time, 8);
509 ok(err == ERANGE, "err = %d\n", err);
510 ok(errno == ERANGE, "errno = %d\n", errno);
511 ok(time[0] == '\0', "time[0] != '\\0'\n");
513 err = p_strtime_s(time, 9);
514 ok(err == 0, "err = %x\n", err);
517 static void test_wstrdate(void)
519 wchar_t date[16], * result;
520 int month, day, year, count, len;
522 result = _wstrdate(date);
523 ok(result == date, "Wrong return value\n");
524 len = wcslen(date);
525 ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
526 count = swscanf(date, L"%02d/%02d/%02d", &month, &day, &year);
527 ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
530 static void test_wstrtime(void)
532 wchar_t time[16], * result;
533 int hour, minute, second, count, len;
535 result = _wstrtime(time);
536 ok(result == time, "Wrong return value\n");
537 len = wcslen(time);
538 ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
539 count = swscanf(time, L"%02d:%02d:%02d", &hour, &minute, &second);
540 ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
543 static void test_localtime32_s(void)
545 struct tm tm;
546 __time32_t time;
547 errno_t err;
549 if (!p_localtime32_s)
551 win_skip("Skipping _localtime32_s tests\n");
552 return;
555 errno = EBADF;
556 err = p_localtime32_s(NULL, NULL);
557 ok(err == EINVAL, "Expected _localtime32_s to return EINVAL, got %d\n", err);
558 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
560 errno = EBADF;
561 time = 0x12345678;
562 err = p_localtime32_s(NULL, &time);
563 ok(err == EINVAL, "Expected _localtime32_s to return EINVAL, got %d\n", err);
564 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
566 memset(&tm, 0, sizeof(tm));
567 errno = EBADF;
568 err = p_localtime32_s(&tm, NULL);
569 ok(err == EINVAL, "Expected _localtime32_s to return EINVAL, got %d\n", err);
570 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
571 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
572 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
573 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
574 "Expected tm structure members to be initialized to -1, got "
575 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
576 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
577 tm.tm_isdst);
579 memset(&tm, 0, sizeof(tm));
580 time = -1;
581 errno = EBADF;
582 err = p_localtime32_s(&tm, &time);
583 ok(err == EINVAL, "Expected _localtime32_s to return EINVAL, got %d\n", err);
584 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
585 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
586 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
587 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
588 "Expected tm structure members to be initialized to -1, got "
589 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
590 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
591 tm.tm_isdst);
594 static void test_localtime64_s(void)
596 struct tm tm;
597 __time64_t time;
598 errno_t err;
600 if (!p_localtime64_s)
602 win_skip("Skipping _localtime64_s tests\n");
603 return;
606 errno = EBADF;
607 err = p_localtime64_s(NULL, NULL);
608 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
609 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
611 errno = EBADF;
612 time = 0xdeadbeef;
613 err = p_localtime64_s(NULL, &time);
614 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
615 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
617 memset(&tm, 0, sizeof(tm));
618 errno = EBADF;
619 err = p_localtime64_s(&tm, NULL);
620 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
621 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
622 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
623 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
624 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
625 "Expected tm structure members to be initialized to -1, got "
626 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
627 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
628 tm.tm_isdst);
630 memset(&tm, 0, sizeof(tm));
631 time = -1;
632 errno = EBADF;
633 err = p_localtime64_s(&tm, &time);
634 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
635 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
636 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
637 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
638 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
639 "Expected tm structure members to be initialized to -1, got "
640 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
641 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
642 tm.tm_isdst);
644 memset(&tm, 0, sizeof(tm));
645 time = _MAX__TIME64_T + 1;
646 errno = EBADF;
647 err = p_localtime64_s(&tm, &time);
648 ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
649 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
650 ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
651 tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
652 tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
653 "Expected tm structure members to be initialized to -1, got "
654 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
655 tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
656 tm.tm_isdst);
659 static void test_daylight(void)
661 int *ret1, *ret2;
663 if (!p__daylight)
665 win_skip("__daylight() not available\n");
666 return;
669 /* Examine the returned pointer from __p__environ(), if available. */
670 if (sizeof(void*) != sizeof(int))
671 ok( !p___p__daylight, "___p__daylight() should be 32-bit only\n");
672 else
674 ret1 = p__daylight();
675 ret2 = p___p__daylight();
676 ok(ret1 && ret1 == ret2, "got %p\n", ret1);
680 static void test_strftime(void)
682 const struct {
683 const char *format;
684 } tests_einval[] = {
685 {"%C"},
686 {"%D"},
687 {"%e"},
688 {"%F"},
689 {"%h"},
690 {"%n"},
691 {"%R"},
692 {"%t"},
693 {"%T"},
694 {"%u"},
697 const struct {
698 const char *format;
699 const char *ret;
700 struct tm tm;
701 BOOL todo;
702 } tests[] = {
703 {"e%#%e", "e%e", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
704 {"%c", "01/01/70 00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
705 {"%c", "02/30/70 00:00:00", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
706 {"%#c", "Thursday, January 01, 1970 00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
707 {"%#c", "Thursday, February 30, 1970 00:00:00", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
708 {"%x", "01/01/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
709 {"%x", "02/30/70", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
710 {"%#x", "Thursday, January 01, 1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
711 {"%#x", "Thursday, February 30, 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
712 {"%X", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
713 {"%X", "14:00:00", { 0, 0, 14, 1, 0, 70, 4, 0, 0 }},
714 {"%a", "Thu", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
715 {"%A", "Thursday", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
716 {"%b", "Jan", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
717 {"%B", "January", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
718 {"%d", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
719 {"%#d", "1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
720 {"%H", "00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
721 {"%I", "12", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
722 {"%j", "001", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
723 {"%m", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
724 {"%#M", "0", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
725 {"%p", "AM", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
726 {"%U", "00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
727 {"%W", "00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
728 {"%U", "01", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
729 {"%W", "00", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
730 {"%U", "53", { 0, 0, 0, 1, 0, 70, 0, 365, 0 }},
731 {"%W", "52", { 0, 0, 0, 1, 0, 70, 0, 365, 0 }},
734 const struct {
735 const char *format;
736 const char *ret;
737 const char *short_date;
738 const char *date;
739 const char *time;
740 struct tm tm;
741 BOOL todo;
742 } tests_td[] = {
743 { "%c", "x z", "x", "y", "z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
744 { "%#c", "y z", "x", "y", "z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
745 { "%X", "m1", 0, 0, "MMM", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
746 { "%X", "1", 0, 0, "h", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
747 { "%X", "01", 0, 0, "hh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
748 { "%X", "h01", 0, 0, "hhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
749 { "%X", "hh01", 0, 0, "hhhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
750 { "%X", "1", 0, 0, "H", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
751 { "%X", "01", 0, 0, "HH", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
752 { "%X", "H13", 0, 0, "HHH", { 0, 0, 13, 1, 0, 70, 0, 0, 0 }},
753 { "%X", "0", 0, 0, "m", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
754 { "%X", "00", 0, 0, "mm", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
755 { "%X", "0", 0, 0, "s", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
756 { "%X", "00", 0, 0, "ss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
757 { "%X", "s00", 0, 0, "sss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
758 { "%X", "t", 0, 0, "t", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
759 { "%X", "tam", 0, 0, "tt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
760 { "%X", "tam", 0, 0, "ttttttttt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
761 { "%X", "tam", 0, 0, "a", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
762 { "%X", "tam", 0, 0, "aaaaa", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
763 { "%X", "tam", 0, 0, "A", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
764 { "%X", "tam", 0, 0, "AAAAA", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
765 { "%x", "1", "d", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
766 { "%x", "01", "dd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
767 { "%x", "d1", "ddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
768 { "%x", "day1", "dddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
769 { "%x", "dday1", "ddddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
770 { "%x", "1", "M", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
771 { "%x", "01", "MM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
772 { "%x", "m1", "MMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
773 { "%x", "mon1", "MMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
774 { "%x", "Mmon1", "MMMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
775 { "%x", "y", "y", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
776 { "%x", "70", "yy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
777 { "%x", "y70", "yyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
778 { "%x", "1970", "yyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
779 { "%x", "y1970", "yyyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
780 { "%x", "ggggggggggg", "ggggggggggg", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
781 { "%#x", "1", 0, "d", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
782 { "%#x", "01", 0, "dd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
783 { "%#x", "d1", 0, "ddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
784 { "%#x", "day1", 0, "dddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
785 { "%#x", "dday1", 0, "ddddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
786 { "%#x", "1", 0, "M", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
787 { "%#x", "01", 0, "MM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
788 { "%#x", "m1", 0, "MMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
789 { "%#x", "mon1", 0, "MMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
790 { "%#x", "Mmon1", 0, "MMMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
791 { "%#x", "y", 0, "y", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
792 { "%#x", "70", 0, "yy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
793 { "%#x", "y70", 0, "yyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
794 { "%#x", "1970", 0, "yyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
795 { "%#x", "y1970", 0, "yyyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
798 __lc_time_data time_data = {
799 { "d1", "d2", "d3", "d4", "d5", "d6", "d7" },
800 { "day1", "day2", "day3", "day4", "day5", "day6", "day7" },
801 { "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9", "m10", "m11", "m12" },
802 { "mon1", "mon2", "mon3", "mon4", "mon5", "mon6", "mon7", "mon8", "mon9", "mon10", "mon11", "mon12" },
803 "tam", "tpm"
805 time_t gmt;
806 struct tm* gmt_tm;
807 char buf[256], bufA[256];
808 WCHAR bufW[256];
809 long retA, retW;
810 int i;
812 if (!p_strftime || !p_wcsftime || !p_gmtime)
814 win_skip("strftime, wcsftime or gmtime is not available\n");
815 return;
818 setlocale(LC_TIME, "C");
820 gmt = 0;
821 gmt_tm = p_gmtime(&gmt);
822 ok(gmt_tm != NULL, "gmtime failed\n");
824 for (i=0; i<ARRAY_SIZE(tests_einval); i++)
826 errno = 0xdeadbeef;
827 retA = p_strftime(bufA, 256, tests_einval[i].format, gmt_tm);
828 ok(retA == 0, "%d) ret = %ld\n", i, retA);
829 ok(errno==EINVAL || broken(errno==0xdeadbeef), "%d) errno = %d\n", i, errno);
832 errno = 0xdeadbeef;
833 retA = p_strftime(NULL, 0, "copy", gmt_tm);
834 ok(retA == 0, "expected 0, got %ld\n", retA);
835 ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
837 retA = p_strftime(bufA, 256, "copy", NULL);
838 ok(retA == 4, "expected 4, got %ld\n", retA);
839 ok(!strcmp(bufA, "copy"), "got %s\n", bufA);
841 retA = p_strftime(bufA, 256, "copy it", gmt_tm);
842 ok(retA == 7, "expected 7, got %ld\n", retA);
843 ok(!strcmp(bufA, "copy it"), "got %s\n", bufA);
845 errno = 0xdeadbeef;
846 retA = p_strftime(bufA, 2, "copy", gmt_tm);
847 ok(retA == 0, "expected 0, got %ld\n", retA);
848 ok(!strcmp(bufA, "") || broken(!strcmp(bufA, "copy it")), "got %s\n", bufA);
849 ok(errno==ERANGE || errno==0xdeadbeef, "errno = %d\n", errno);
851 errno = 0xdeadbeef;
852 retA = p_strftime(bufA, 256, "a%e", gmt_tm);
853 ok(retA==0 || broken(retA==1), "expected 0, got %ld\n", retA);
854 ok(!strcmp(bufA, "") || broken(!strcmp(bufA, "a")), "got %s\n", bufA);
855 ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
857 if(0) { /* crashes on Win2k */
858 errno = 0xdeadbeef;
859 retA = p_strftime(bufA, 256, "%c", NULL);
860 ok(retA == 0, "expected 0, got %ld\n", retA);
861 ok(!strcmp(bufA, ""), "got %s\n", bufA);
862 ok(errno == EINVAL, "errno = %d\n", errno);
865 for (i=0; i<ARRAY_SIZE(tests); i++)
867 retA = p_strftime(bufA, 256, tests[i].format, &tests[i].tm);
868 todo_wine_if(tests[i].todo) {
869 ok(retA == strlen(tests[i].ret), "%d) ret = %ld\n", i, retA);
870 ok(!strcmp(bufA, tests[i].ret), "%d) buf = \"%s\", expected \"%s\"\n",
871 i, bufA, tests[i].ret);
875 retA = p_strftime(bufA, 256, "%c", gmt_tm);
876 retW = p_wcsftime(bufW, 256, L"%c", gmt_tm);
877 ok(retW == 17, "expected 17, got %ld\n", retW);
878 ok(retA == retW, "expected %ld, got %ld\n", retA, retW);
879 buf[0] = 0;
880 retA = WideCharToMultiByte(CP_ACP, 0, bufW, retW, buf, 256, NULL, NULL);
881 buf[retA] = 0;
882 ok(strcmp(bufA, buf) == 0, "expected %s, got %s\n", bufA, buf);
884 if(!setlocale(LC_ALL, "Japanese_Japan.932")) {
885 win_skip("Japanese_Japan.932 locale not available\n");
886 return;
889 /* test with multibyte character */
890 retA = p_strftime(bufA, 256, "\x82%c", gmt_tm);
891 ok(retA == 3, "expected 3, got %ld\n", retA);
892 ok(!strcmp(bufA, "\x82%c"), "got %s\n", bufA);
894 setlocale(LC_ALL, "C");
895 if(!p__Strftime) {
896 win_skip("_Strftime is not available\n");
897 return;
900 /* TODO: find meaning of unk */
901 time_data.unk = 1;
902 for (i=0; i<ARRAY_SIZE(tests_td); i++)
904 time_data.short_date = tests_td[i].short_date;
905 time_data.date = tests_td[i].date;
906 time_data.time = tests_td[i].time;
907 retA = p__Strftime(buf, sizeof(buf), tests_td[i].format, &tests_td[i].tm, &time_data);
908 ok(retA == strlen(buf), "%d) ret = %ld\n", i, retA);
909 todo_wine_if(tests_td[i].todo) {
910 ok(!strcmp(buf, tests_td[i].ret), "%d) buf = \"%s\", expected \"%s\"\n",
911 i, buf, tests_td[i].ret);
916 static void test_asctime(void)
918 struct tm* gmt_tm;
919 time_t gmt;
920 char *ret;
922 if(!p_asctime || !p_gmtime)
924 win_skip("asctime or gmtime is not available\n");
925 return;
928 gmt = 0;
929 gmt_tm = p_gmtime(&gmt);
930 ret = p_asctime(gmt_tm);
931 ok(!strcmp(ret, "Thu Jan 01 00:00:00 1970\n"), "asctime returned %s\n", ret);
933 gmt = 312433121;
934 gmt_tm = p_gmtime(&gmt);
935 ret = p_asctime(gmt_tm);
936 ok(!strcmp(ret, "Mon Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret);
938 /* Week day is only checked if it's in 0..6 range */
939 gmt_tm->tm_wday = 3;
940 ret = p_asctime(gmt_tm);
941 ok(!strcmp(ret, "Wed Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret);
943 errno = 0xdeadbeef;
944 gmt_tm->tm_wday = 7;
945 ret = p_asctime(gmt_tm);
946 ok(!ret || broken(!ret[0]), "asctime returned %s\n", ret);
947 ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
949 /* Year day is ignored */
950 gmt_tm->tm_wday = 3;
951 gmt_tm->tm_yday = 1300;
952 ret = p_asctime(gmt_tm);
953 ok(!strcmp(ret, "Wed Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret);
955 /* Dates that can't be displayed using 26 characters are broken */
956 gmt_tm->tm_mday = 28;
957 gmt_tm->tm_year = 8100;
958 ret = p_asctime(gmt_tm);
959 ok(!strcmp(ret, "Wed Nov 28 02:58:41 :000\n"), "asctime returned %s\n", ret);
961 gmt_tm->tm_year = 264100;
962 ret = p_asctime(gmt_tm);
963 ok(!strcmp(ret, "Wed Nov 28 02:58:41 :000\n"), "asctime returned %s\n", ret);
965 /* asctime works from year 1900 */
966 errno = 0xdeadbeef;
967 gmt_tm->tm_year = -1;
968 ret = p_asctime(gmt_tm);
969 ok(!ret || broken(!strcmp(ret, "Wed Nov 28 02:58:41 190/\n")), "asctime returned %s\n", ret);
970 ok(errno==EINVAL || broken(errno == 0xdeadbeef), "errno = %d\n", errno);
972 errno = 0xdeadbeef;
973 gmt_tm->tm_mon = 1;
974 gmt_tm->tm_mday = 30;
975 gmt_tm->tm_year = 79;
976 ret = p_asctime(gmt_tm);
977 ok(!ret || broken(!strcmp(ret, "Wed Feb 30 02:58:41 1979\n")), "asctime returned %s\n", ret);
978 ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
981 static void test__tzset(void)
983 char TZ_env[256];
984 int ret;
986 if (sizeof(void*) != sizeof(int))
988 ok(!p___p__daylight, "___p__daylight() should be 32-bit only\n");
989 ok(!p___p__timezone, "___p__timezone() should be 32-bit only\n");
990 ok(!p___p__dstbias, "___p__dstbias() should be 32-bit only\n");
991 return;
994 if (p__dstbias) {
995 ret = *p__dstbias();
996 ok(ret == -3600, "*__dstbias() = %d\n", ret);
997 ret = *p___p__dstbias();
998 ok(ret == -3600, "*__p__dstbias() = %d\n", ret);
1000 else
1001 win_skip("__dstbias() is not available.\n");
1003 _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
1005 ret = *p___p__daylight();
1006 ok(ret == 1, "*__p__daylight() = %d\n", ret);
1007 ret = *p___p__timezone();
1008 ok(ret == 28800, "*__p__timezone() = %d\n", ret);
1009 ret = *p___p__dstbias();
1010 ok(ret == -3600, "*__p__dstbias() = %d\n", ret);
1012 _putenv("TZ=xxx+1yyy");
1013 _tzset();
1014 ret = *p___p__daylight();
1015 ok(ret == 121, "*__p__daylight() = %d\n", ret);
1016 ret = *p___p__timezone();
1017 ok(ret == 3600, "*__p__timezone() = %d\n", ret);
1018 ret = *p___p__dstbias();
1019 ok(ret == -3600, "*__p__dstbias() = %d\n", ret);
1021 *p___p__dstbias() = 0;
1022 _putenv("TZ=xxx+1:3:5zzz");
1023 _tzset();
1024 ret = *p___p__daylight();
1025 ok(ret == 122, "*__p__daylight() = %d\n", ret);
1026 ret = *p___p__timezone();
1027 ok(ret == 3785, "*__p__timezone() = %d\n", ret);
1028 ret = *p___p__dstbias();
1029 ok(ret == 0, "*__p__dstbias() = %d\n", ret);
1031 _putenv(TZ_env);
1034 START_TEST(time)
1036 init();
1038 test__tzset();
1039 test_strftime();
1040 test_ctime();
1041 test_gmtime();
1042 test_gmtime64();
1043 test_mktime();
1044 test_localtime();
1045 test_strdate();
1046 test_strtime();
1047 test_wstrdate();
1048 test_wstrtime();
1049 test_localtime32_s();
1050 test_localtime64_s();
1051 test_daylight();
1052 test_asctime();