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*/
30 #define SECSPERDAY 86400
31 #define SECSPERHOUR 3600
33 #define MINSPERHOUR 60
34 #define HOURSPERDAY 24
36 static __time32_t (__cdecl
*p_mkgmtime32
)(struct tm
*);
37 static struct tm
* (__cdecl
*p_gmtime32
)(__time32_t
*);
38 static errno_t (__cdecl
*p_strtime_s
)(char*,size_t);
40 static void init(void)
42 HMODULE hmod
= GetModuleHandleA("msvcrt.dll");
44 p_gmtime32
= (void*)GetProcAddress(hmod
, "_gmtime32");
45 p_mkgmtime32
= (void*)GetProcAddress(hmod
, "_mkgmtime32");
46 p_strtime_s
= (void*)GetProcAddress(hmod
, "_strtime_s");
49 static int get_test_year(time_t *start
)
51 time_t now
= time(NULL
);
52 struct tm
*tm
= localtime(&now
);
54 /* compute start of year in seconds */
55 *start
= SECSPERDAY
* ((tm
->tm_year
- 70) * 365 +
56 (tm
->tm_year
- 69) / 4 -
57 (tm
->tm_year
- 1) / 100 +
58 (tm
->tm_year
+ 299) / 400);
62 static void test_ctime(void)
66 ret
= ctime(&badtime
);
67 ok(ret
== NULL
, "expected ctime to return NULL, got %s\n", ret
);
69 static void test_gmtime(void)
71 __time32_t valid
, gmt
;
75 win_skip("Skipping _gmtime32 tests\n");
80 gmt_tm
= p_gmtime32(&gmt
);
82 ok(0, "_gmtime32() failed\n");
86 ok(((gmt_tm
->tm_year
== 70) && (gmt_tm
->tm_mon
== 0) && (gmt_tm
->tm_yday
== 0) &&
87 (gmt_tm
->tm_mday
== 1) && (gmt_tm
->tm_wday
== 4) && (gmt_tm
->tm_hour
== 0) &&
88 (gmt_tm
->tm_min
== 0) && (gmt_tm
->tm_sec
== 0) && (gmt_tm
->tm_isdst
== 0)),
89 "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n",
90 gmt_tm
->tm_year
, gmt_tm
->tm_mon
, gmt_tm
->tm_yday
, gmt_tm
->tm_mday
, gmt_tm
->tm_wday
,
91 gmt_tm
->tm_hour
, gmt_tm
->tm_min
, gmt_tm
->tm_sec
, gmt_tm
->tm_isdst
);
94 win_skip("Skipping _mkgmtime32 tests\n");
98 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
99 gmt
= p_mkgmtime32(gmt_tm
);
100 ok(gmt
== valid
, "gmt = %u\n", gmt
);
101 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
102 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
104 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
105 gmt_tm
->tm_isdst
= -1;
106 gmt
= p_mkgmtime32(gmt_tm
);
107 ok(gmt
== valid
, "gmt = %u\n", gmt
);
108 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
109 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
111 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
112 gmt_tm
->tm_isdst
= 1;
113 gmt
= p_mkgmtime32(gmt_tm
);
114 ok(gmt
== valid
, "gmt = %u\n", gmt
);
115 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
116 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
118 gmt
= valid
= 173921;
119 gmt_tm
= p_gmtime32(&gmt
);
121 ok(0, "_gmtime32() failed\n");
125 gmt_tm
->tm_isdst
= -1;
126 gmt
= p_mkgmtime32(gmt_tm
);
127 ok(gmt
== valid
, "gmt = %u\n", gmt
);
128 ok(gmt_tm
->tm_wday
== 6, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
129 ok(gmt_tm
->tm_yday
== 2, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
131 gmt_tm
->tm_isdst
= 1;
132 gmt
= p_mkgmtime32(gmt_tm
);
133 ok(gmt
== valid
, "gmt = %u\n", gmt
);
136 static void test_mktime(void)
138 TIME_ZONE_INFORMATION tzinfo
;
139 DWORD res
= GetTimeZoneInformation(&tzinfo
);
140 struct tm my_tm
, sav_tm
;
141 time_t nulltime
, local_time
;
147 year
= get_test_year( &ref
);
150 ok (res
!= TIME_ZONE_ID_INVALID
, "GetTimeZoneInformation failed\n");
151 WideCharToMultiByte( CP_ACP
, 0, tzinfo
.StandardName
, -1, buffer
, sizeof(buffer
), NULL
, NULL
);
152 trace( "bias %d std %d dst %d zone %s\n",
153 tzinfo
.Bias
, tzinfo
.StandardBias
, tzinfo
.DaylightBias
, buffer
);
154 /* Bias may be positive or negative, to use offset of one day */
155 my_tm
= *localtime(&ref
); /* retrieve current dst flag */
156 secs
= SECSPERDAY
- tzinfo
.Bias
* SECSPERMIN
;
157 secs
-= (my_tm
.tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
158 my_tm
.tm_mday
= 1 + secs
/SECSPERDAY
;
159 secs
= secs
% SECSPERDAY
;
160 my_tm
.tm_hour
= secs
/ SECSPERHOUR
;
161 secs
= secs
% SECSPERHOUR
;
162 my_tm
.tm_min
= secs
/ SECSPERMIN
;
163 secs
= secs
% SECSPERMIN
;
166 my_tm
.tm_year
= year
;
171 local_time
= mktime(&my_tm
);
172 ok(local_time
== ref
, "mktime returned %u, expected %u\n",
173 (DWORD
)local_time
, (DWORD
)ref
);
174 /* now test some unnormalized struct tm's */
178 local_time
= mktime(&my_tm
);
179 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
180 (DWORD
)local_time
, (DWORD
)ref
);
181 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
182 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
183 my_tm
.tm_sec
== sav_tm
.tm_sec
,
184 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
185 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
186 my_tm
.tm_hour
,my_tm
.tm_sec
,
187 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
188 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
192 local_time
= mktime(&my_tm
);
193 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
194 (DWORD
)local_time
, (DWORD
)ref
);
195 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
196 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
197 my_tm
.tm_sec
== sav_tm
.tm_sec
,
198 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
199 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
200 my_tm
.tm_hour
,my_tm
.tm_sec
,
201 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
202 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
206 local_time
= mktime(&my_tm
);
207 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
208 (DWORD
)local_time
, (DWORD
)ref
);
209 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
210 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
211 my_tm
.tm_sec
== sav_tm
.tm_sec
,
212 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
213 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
214 my_tm
.tm_hour
,my_tm
.tm_sec
,
215 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
216 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
220 local_time
= mktime(&my_tm
);
221 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
222 (DWORD
)local_time
, (DWORD
)ref
);
223 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
224 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
225 my_tm
.tm_sec
== sav_tm
.tm_sec
,
226 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
227 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
228 my_tm
.tm_hour
,my_tm
.tm_sec
,
229 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
230 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
231 /* now a bad time example */
234 local_time
= mktime(&my_tm
);
235 ok((local_time
== -1), "(bad time) mktime returned %d, expected -1\n", (int)local_time
);
238 /* TEST that we are independent from the TZ variable */
239 /*Argh, msvcrt doesn't have setenv() */
240 _snprintf(TZ_env
,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
242 nulltime
= mktime(&my_tm
);
243 ok(nulltime
== ref
,"mktime returned 0x%08x\n",(DWORD
)nulltime
);
247 static void test_localtime(void)
249 TIME_ZONE_INFORMATION tzinfo
;
250 DWORD res
= GetTimeZoneInformation(&tzinfo
);
255 int year
= get_test_year( &ref
);
256 int is_leap
= !(year
% 4) && ((year
% 100) || !((year
+ 300) % 400));
258 gmt
= ref
+ SECSPERDAY
+ tzinfo
.Bias
* SECSPERMIN
;
259 ok (res
!= TIME_ZONE_ID_INVALID
, "GetTimeZoneInformation failed\n");
260 lt
= localtime(&gmt
);
261 gmt
+= (lt
->tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
262 lt
= localtime(&gmt
);
263 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 0) && (lt
->tm_yday
== 1) &&
264 (lt
->tm_mday
== 2) && (lt
->tm_hour
== 0) &&
265 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
266 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
267 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
268 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
270 _snprintf(TZ_env
,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
272 lt
= localtime(&gmt
);
273 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 0) && (lt
->tm_yday
== 1) &&
274 (lt
->tm_mday
== 2) && (lt
->tm_hour
== 0) &&
275 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
276 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
277 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
278 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
282 gmt
= ref
+ 202 * SECSPERDAY
+ tzinfo
.Bias
* SECSPERMIN
;
283 lt
= localtime(&gmt
);
284 gmt
+= (lt
->tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
285 lt
= localtime(&gmt
);
286 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 6) && (lt
->tm_yday
== 202) &&
287 (lt
->tm_mday
== 22 - is_leap
) && (lt
->tm_hour
== 0) &&
288 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
289 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
290 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
291 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
294 static void test_strdate(void)
296 char date
[16], * result
;
297 int month
, day
, year
, count
, len
;
299 result
= _strdate(date
);
300 ok(result
== date
, "Wrong return value\n");
302 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
303 count
= sscanf(date
, "%02d/%02d/%02d", &month
, &day
, &year
);
304 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
307 static void test_strtime(void)
309 char time
[16], * result
;
310 int hour
, minute
, second
, count
, len
;
313 result
= _strtime(time
);
314 ok(result
== time
, "Wrong return value\n");
316 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
317 count
= sscanf(time
, "%02d:%02d:%02d", &hour
, &minute
, &second
);
318 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
321 win_skip("Skipping _strtime_s tests\n");
326 err
= p_strtime_s(NULL
, 0);
327 ok(err
== EINVAL
, "err = %d\n", err
);
328 ok(errno
== EINVAL
, "errno = %d\n", errno
);
330 err
= p_strtime_s(NULL
, 1);
331 ok(err
== EINVAL
, "err = %d\n", err
);
332 ok(errno
== EINVAL
, "errno = %d\n", errno
);
335 err
= p_strtime_s(time
, 8);
336 ok(err
== ERANGE
, "err = %d\n", err
);
337 ok(errno
== ERANGE
, "errno = %d\n", errno
);
338 ok(time
[0] == '\0', "time[0] != '\\0'\n");
340 err
= p_strtime_s(time
, 9);
341 ok(err
== 0, "err = %x\n", err
);
344 static void test_wstrdate(void)
346 wchar_t date
[16], * result
;
347 int month
, day
, year
, count
, len
;
348 wchar_t format
[] = { '%','0','2','d','/','%','0','2','d','/','%','0','2','d',0 };
350 result
= _wstrdate(date
);
351 ok(result
== date
, "Wrong return value\n");
353 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
354 count
= swscanf(date
, format
, &month
, &day
, &year
);
355 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
358 static void test_wstrtime(void)
360 wchar_t time
[16], * result
;
361 int hour
, minute
, second
, count
, len
;
362 wchar_t format
[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',0 };
364 result
= _wstrtime(time
);
365 ok(result
== time
, "Wrong return value\n");
367 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
368 count
= swscanf(time
, format
, &hour
, &minute
, &second
);
369 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);