ntdll: Translate signal to trap when trap code is 0 on ARM.
[wine.git] / dlls / msvcrt / time.c
blobe6493b09aff290c8bf5e287412ece330b5f668fd
1 /*
2 * msvcrt.dll date/time functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
8 * Copyright 2004 Hans Leidekker
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
27 #include <stdlib.h>
29 #include "msvcrt.h"
30 #include "mtdll.h"
31 #include "winbase.h"
32 #include "winnls.h"
33 #include "winternl.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
39 BOOL WINAPI GetDaylightFlag(void);
41 static const int MonthLengths[2][12] =
43 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
44 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
47 static inline BOOL IsLeapYear(int Year)
49 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
52 static inline void write_invalid_msvcrt_tm( struct MSVCRT_tm *tm )
54 tm->tm_sec = -1;
55 tm->tm_min = -1;
56 tm->tm_hour = -1;
57 tm->tm_mday = -1;
58 tm->tm_mon = -1;
59 tm->tm_year = -1;
60 tm->tm_wday = -1;
61 tm->tm_yday = -1;
62 tm->tm_isdst = -1;
65 /*********************************************************************
66 * _daylight (MSVCRT.@)
68 int MSVCRT___daylight = 1;
70 /*********************************************************************
71 * _timezone (MSVCRT.@)
73 MSVCRT_long MSVCRT___timezone = 28800;
75 /*********************************************************************
76 * _dstbias (MSVCRT.@)
78 int MSVCRT__dstbias = -3600;
80 /*********************************************************************
81 * _tzname (MSVCRT.@)
82 * NOTES
83 * Some apps (notably Mozilla) insist on writing to these, so the buffer
84 * must be large enough.
86 static char tzname_std[64] = "PST";
87 static char tzname_dst[64] = "PDT";
88 char *MSVCRT__tzname[2] = { tzname_std, tzname_dst };
90 static TIME_ZONE_INFORMATION tzi = {0};
91 /*********************************************************************
92 * _tzset (MSVCRT.@)
94 void CDECL MSVCRT__tzset(void)
96 char *tz = MSVCRT_getenv("TZ");
97 BOOL error;
99 _mlock(_TIME_LOCK);
100 if(tz && tz[0]) {
101 BOOL neg_zone = FALSE;
103 memset(&tzi, 0, sizeof(tzi));
105 /* Parse timezone information: tzn[+|-]hh[:mm[:ss]][dzn] */
106 lstrcpynA(MSVCRT__tzname[0], tz, 3);
107 tz += 3;
109 if(*tz == '-') {
110 neg_zone = TRUE;
111 tz++;
112 }else if(*tz == '+') {
113 tz++;
115 MSVCRT___timezone = strtol(tz, &tz, 10)*3600;
116 if(*tz == ':') {
117 MSVCRT___timezone += strtol(tz+1, &tz, 10)*60;
118 if(*tz == ':')
119 MSVCRT___timezone += strtol(tz+1, &tz, 10);
121 if(neg_zone)
122 MSVCRT___timezone = -MSVCRT___timezone;
124 MSVCRT___daylight = *tz;
125 lstrcpynA(MSVCRT__tzname[1], tz, 3);
126 }else if(GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_INVALID) {
127 MSVCRT___timezone = tzi.Bias*60;
128 if(tzi.StandardDate.wMonth)
129 MSVCRT___timezone += tzi.StandardBias*60;
131 if(tzi.DaylightDate.wMonth) {
132 MSVCRT___daylight = 1;
133 MSVCRT__dstbias = (tzi.DaylightBias-tzi.StandardBias)*60;
134 }else {
135 MSVCRT___daylight = 0;
136 MSVCRT__dstbias = 0;
139 if(!WideCharToMultiByte(CP_ACP, 0, tzi.StandardName, -1, MSVCRT__tzname[0],
140 sizeof(tzname_std), NULL, &error) || error)
141 *MSVCRT__tzname[0] = 0;
142 if(!WideCharToMultiByte(CP_ACP, 0, tzi.DaylightName, -1, MSVCRT__tzname[1],
143 sizeof(tzname_dst), NULL, &error) || error)
144 *MSVCRT__tzname[0] = 0;
146 _munlock(_TIME_LOCK);
149 static void _tzset_init(void)
151 static BOOL init = FALSE;
153 if(!init) {
154 _mlock(_TIME_LOCK);
155 if(!init) {
156 MSVCRT__tzset();
157 init = TRUE;
159 _munlock(_TIME_LOCK);
163 static BOOL is_dst(const SYSTEMTIME *st)
165 TIME_ZONE_INFORMATION tmp;
166 SYSTEMTIME out;
168 if(!MSVCRT___daylight)
169 return FALSE;
171 if(tzi.DaylightDate.wMonth) {
172 tmp = tzi;
173 }else if(st->wYear >= 2007) {
174 memset(&tmp, 0, sizeof(tmp));
175 tmp.StandardDate.wMonth = 11;
176 tmp.StandardDate.wDay = 1;
177 tmp.StandardDate.wHour = 2;
178 tmp.DaylightDate.wMonth = 3;
179 tmp.DaylightDate.wDay = 2;
180 tmp.DaylightDate.wHour = 2;
181 }else {
182 memset(&tmp, 0, sizeof(tmp));
183 tmp.StandardDate.wMonth = 10;
184 tmp.StandardDate.wDay = 5;
185 tmp.StandardDate.wHour = 2;
186 tmp.DaylightDate.wMonth = 4;
187 tmp.DaylightDate.wDay = 1;
188 tmp.DaylightDate.wHour = 2;
191 tmp.Bias = 0;
192 tmp.StandardBias = 0;
193 tmp.DaylightBias = MSVCRT__dstbias/60;
194 if(!SystemTimeToTzSpecificLocalTime(&tmp, st, &out))
195 return FALSE;
197 return memcmp(st, &out, sizeof(SYSTEMTIME));
200 #define SECSPERDAY 86400
201 /* 1601 to 1970 is 369 years plus 89 leap days */
202 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
203 #define TICKSPERSEC 10000000
204 #define TICKSPERMSEC 10000
205 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
207 static MSVCRT___time64_t mktime_helper(struct MSVCRT_tm *mstm, BOOL local)
209 SYSTEMTIME st;
210 FILETIME ft;
211 MSVCRT___time64_t ret = 0;
212 int i;
213 BOOL use_dst = FALSE;
215 ret = mstm->tm_year + mstm->tm_mon/12;
216 mstm->tm_mon %= 12;
217 if(mstm->tm_mon < 0) {
218 mstm->tm_mon += 12;
219 ret--;
222 if(ret<70 || ret>1100) {
223 *MSVCRT__errno() = MSVCRT_EINVAL;
224 return -1;
227 memset(&st, 0, sizeof(SYSTEMTIME));
228 st.wDay = 1;
229 st.wMonth = mstm->tm_mon+1;
230 st.wYear = ret+1900;
232 if(!SystemTimeToFileTime(&st, &ft)) {
233 *MSVCRT__errno() = MSVCRT_EINVAL;
234 return -1;
237 ret = ((MSVCRT___time64_t)ft.dwHighDateTime<<32)+ft.dwLowDateTime;
238 ret += (MSVCRT___time64_t)mstm->tm_sec*TICKSPERSEC;
239 ret += (MSVCRT___time64_t)mstm->tm_min*60*TICKSPERSEC;
240 ret += (MSVCRT___time64_t)mstm->tm_hour*60*60*TICKSPERSEC;
241 ret += (MSVCRT___time64_t)(mstm->tm_mday-1)*SECSPERDAY*TICKSPERSEC;
243 ft.dwLowDateTime = ret & 0xffffffff;
244 ft.dwHighDateTime = ret >> 32;
245 FileTimeToSystemTime(&ft, &st);
247 if(local) {
248 _tzset_init();
249 use_dst = is_dst(&st);
250 if((mstm->tm_isdst<=-1 && use_dst) || (mstm->tm_isdst>=1)) {
251 SYSTEMTIME tmp;
253 ret += (MSVCRT___time64_t)MSVCRT__dstbias*TICKSPERSEC;
255 ft.dwLowDateTime = ret & 0xffffffff;
256 ft.dwHighDateTime = ret >> 32;
257 FileTimeToSystemTime(&ft, &tmp);
259 if(!is_dst(&tmp)) {
260 st = tmp;
261 use_dst = FALSE;
262 }else {
263 use_dst = TRUE;
265 }else if(mstm->tm_isdst==0 && use_dst) {
266 ret -= (MSVCRT___time64_t)MSVCRT__dstbias*TICKSPERSEC;
267 ft.dwLowDateTime = ret & 0xffffffff;
268 ft.dwHighDateTime = ret >> 32;
269 FileTimeToSystemTime(&ft, &st);
270 ret += (MSVCRT___time64_t)MSVCRT__dstbias*TICKSPERSEC;
272 ret += (MSVCRT___time64_t)MSVCRT___timezone*TICKSPERSEC;
275 mstm->tm_sec = st.wSecond;
276 mstm->tm_min = st.wMinute;
277 mstm->tm_hour = st.wHour;
278 mstm->tm_mday = st.wDay;
279 mstm->tm_mon = st.wMonth-1;
280 mstm->tm_year = st.wYear-1900;
281 mstm->tm_wday = st.wDayOfWeek;
282 for(i=mstm->tm_yday=0; i<st.wMonth-1; i++)
283 mstm->tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
284 mstm->tm_yday += st.wDay-1;
285 mstm->tm_isdst = use_dst ? 1 : 0;
287 if(ret < TICKS_1601_TO_1970) {
288 *MSVCRT__errno() = MSVCRT_EINVAL;
289 return -1;
291 ret = (ret-TICKS_1601_TO_1970)/TICKSPERSEC;
292 return ret;
295 /**********************************************************************
296 * _mktime64 (MSVCRT.@)
298 MSVCRT___time64_t CDECL MSVCRT__mktime64(struct MSVCRT_tm *mstm)
300 return mktime_helper(mstm, TRUE);
303 /**********************************************************************
304 * _mktime32 (MSVCRT.@)
306 MSVCRT___time32_t CDECL MSVCRT__mktime32(struct MSVCRT_tm *mstm)
308 MSVCRT___time64_t ret = MSVCRT__mktime64( mstm );
309 return ret == (MSVCRT___time32_t)ret ? ret : -1;
312 /**********************************************************************
313 * mktime (MSVCRT.@)
315 #ifdef _WIN64
316 MSVCRT___time64_t CDECL MSVCRT_mktime(struct MSVCRT_tm *mstm)
318 return MSVCRT__mktime64( mstm );
320 #else
321 MSVCRT___time32_t CDECL MSVCRT_mktime(struct MSVCRT_tm *mstm)
323 return MSVCRT__mktime32( mstm );
325 #endif
327 /**********************************************************************
328 * _mkgmtime64 (MSVCRT.@)
330 * time->tm_isdst value is ignored
332 MSVCRT___time64_t CDECL MSVCRT__mkgmtime64(struct MSVCRT_tm *time)
334 return mktime_helper(time, FALSE);
337 /**********************************************************************
338 * _mkgmtime32 (MSVCRT.@)
340 MSVCRT___time32_t CDECL MSVCRT__mkgmtime32(struct MSVCRT_tm *time)
342 MSVCRT___time64_t ret = MSVCRT__mkgmtime64(time);
343 return ret == (MSVCRT___time32_t)ret ? ret : -1;
346 /**********************************************************************
347 * _mkgmtime (MSVCRT.@)
349 #ifdef _WIN64
350 MSVCRT___time64_t CDECL MSVCRT__mkgmtime(struct MSVCRT_tm *time)
352 return MSVCRT__mkgmtime64(time);
354 #else
355 MSVCRT___time32_t CDECL MSVCRT__mkgmtime(struct MSVCRT_tm *time)
357 return MSVCRT__mkgmtime32(time);
359 #endif
361 /*********************************************************************
362 * _localtime64_s (MSVCRT.@)
364 int CDECL _localtime64_s(struct MSVCRT_tm *res, const MSVCRT___time64_t *secs)
366 int i;
367 FILETIME ft;
368 SYSTEMTIME st;
369 ULONGLONG time;
371 if (!res || !secs || *secs < 0 || *secs > _MAX__TIME64_T)
373 if (res)
374 write_invalid_msvcrt_tm(res);
376 *MSVCRT__errno() = MSVCRT_EINVAL;
377 return MSVCRT_EINVAL;
380 _tzset_init();
381 time = (*secs - MSVCRT___timezone) * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
383 ft.dwHighDateTime = (UINT)(time >> 32);
384 ft.dwLowDateTime = (UINT)time;
385 FileTimeToSystemTime(&ft, &st);
387 res->tm_isdst = is_dst(&st) ? 1 : 0;
388 if(res->tm_isdst) {
389 time -= MSVCRT__dstbias * (ULONGLONG)TICKSPERSEC;
390 ft.dwHighDateTime = (UINT)(time >> 32);
391 ft.dwLowDateTime = (UINT)time;
392 FileTimeToSystemTime(&ft, &st);
395 res->tm_sec = st.wSecond;
396 res->tm_min = st.wMinute;
397 res->tm_hour = st.wHour;
398 res->tm_mday = st.wDay;
399 res->tm_year = st.wYear - 1900;
400 res->tm_mon = st.wMonth - 1;
401 res->tm_wday = st.wDayOfWeek;
402 for (i = res->tm_yday = 0; i < st.wMonth - 1; i++)
403 res->tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
404 res->tm_yday += st.wDay - 1;
406 return 0;
409 /*********************************************************************
410 * _localtime64 (MSVCRT.@)
412 struct MSVCRT_tm* CDECL MSVCRT__localtime64(const MSVCRT___time64_t* secs)
414 thread_data_t *data = msvcrt_get_thread_data();
416 if(!data->time_buffer)
417 data->time_buffer = MSVCRT_malloc(sizeof(struct MSVCRT_tm));
419 if(_localtime64_s(data->time_buffer, secs))
420 return NULL;
421 return data->time_buffer;
424 /*********************************************************************
425 * _localtime32 (MSVCRT.@)
427 struct MSVCRT_tm* CDECL MSVCRT__localtime32(const MSVCRT___time32_t* secs)
429 MSVCRT___time64_t secs64;
431 if(!secs)
432 return NULL;
434 secs64 = *secs;
435 return MSVCRT__localtime64( &secs64 );
438 /*********************************************************************
439 * _localtime32_s (MSVCRT.@)
441 int CDECL _localtime32_s(struct MSVCRT_tm *time, const MSVCRT___time32_t *secs)
443 MSVCRT___time64_t secs64;
445 if (!time || !secs || *secs < 0)
447 if (time)
448 write_invalid_msvcrt_tm(time);
450 *MSVCRT__errno() = MSVCRT_EINVAL;
451 return MSVCRT_EINVAL;
454 secs64 = *secs;
455 return _localtime64_s(time, &secs64);
458 /*********************************************************************
459 * localtime (MSVCRT.@)
461 #ifdef _WIN64
462 struct MSVCRT_tm* CDECL MSVCRT_localtime(const MSVCRT___time64_t* secs)
464 return MSVCRT__localtime64( secs );
466 #else
467 struct MSVCRT_tm* CDECL MSVCRT_localtime(const MSVCRT___time32_t* secs)
469 return MSVCRT__localtime32( secs );
471 #endif
473 /*********************************************************************
474 * _gmtime64 (MSVCRT.@)
476 int CDECL MSVCRT__gmtime64_s(struct MSVCRT_tm *res, const MSVCRT___time64_t *secs)
478 int i;
479 FILETIME ft;
480 SYSTEMTIME st;
481 ULONGLONG time;
483 if (!res || !secs || *secs < 0 || *secs > _MAX__TIME64_T) {
484 if (res) {
485 write_invalid_msvcrt_tm(res);
488 *MSVCRT__errno() = MSVCRT_EINVAL;
489 return MSVCRT_EINVAL;
492 time = *secs * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
494 ft.dwHighDateTime = (UINT)(time >> 32);
495 ft.dwLowDateTime = (UINT)time;
497 FileTimeToSystemTime(&ft, &st);
499 res->tm_sec = st.wSecond;
500 res->tm_min = st.wMinute;
501 res->tm_hour = st.wHour;
502 res->tm_mday = st.wDay;
503 res->tm_year = st.wYear - 1900;
504 res->tm_mon = st.wMonth - 1;
505 res->tm_wday = st.wDayOfWeek;
506 for (i = res->tm_yday = 0; i < st.wMonth - 1; i++) {
507 res->tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
510 res->tm_yday += st.wDay - 1;
511 res->tm_isdst = 0;
513 return 0;
516 /*********************************************************************
517 * _gmtime64 (MSVCRT.@)
519 struct MSVCRT_tm* CDECL MSVCRT__gmtime64(const MSVCRT___time64_t *secs)
521 thread_data_t * const data = msvcrt_get_thread_data();
523 if(!data->time_buffer)
524 data->time_buffer = MSVCRT_malloc(sizeof(struct MSVCRT_tm));
526 if(MSVCRT__gmtime64_s(data->time_buffer, secs))
527 return NULL;
528 return data->time_buffer;
531 /*********************************************************************
532 * _gmtime32_s (MSVCRT.@)
534 int CDECL MSVCRT__gmtime32_s(struct MSVCRT_tm *res, const MSVCRT___time32_t *secs)
536 MSVCRT___time64_t secs64;
538 if(secs) {
539 secs64 = *secs;
540 return MSVCRT__gmtime64_s(res, &secs64);
542 return MSVCRT__gmtime64_s(res, NULL);
545 /*********************************************************************
546 * _gmtime32 (MSVCRT.@)
548 struct MSVCRT_tm* CDECL MSVCRT__gmtime32(const MSVCRT___time32_t* secs)
550 MSVCRT___time64_t secs64;
552 if(!secs)
553 return NULL;
555 secs64 = *secs;
556 return MSVCRT__gmtime64( &secs64 );
559 /*********************************************************************
560 * gmtime (MSVCRT.@)
562 #ifdef _WIN64
563 struct MSVCRT_tm* CDECL MSVCRT_gmtime(const MSVCRT___time64_t* secs)
565 return MSVCRT__gmtime64( secs );
567 #else
568 struct MSVCRT_tm* CDECL MSVCRT_gmtime(const MSVCRT___time32_t* secs)
570 return MSVCRT__gmtime32( secs );
572 #endif
574 /**********************************************************************
575 * _strdate (MSVCRT.@)
577 char* CDECL MSVCRT__strdate(char* date)
579 static const char format[] = "MM'/'dd'/'yy";
581 GetDateFormatA(LOCALE_NEUTRAL, 0, NULL, format, date, 9);
583 return date;
586 /**********************************************************************
587 * _strdate_s (MSVCRT.@)
589 int CDECL _strdate_s(char* date, MSVCRT_size_t size)
591 if(date && size)
592 date[0] = '\0';
594 if(!date) {
595 *MSVCRT__errno() = MSVCRT_EINVAL;
596 return MSVCRT_EINVAL;
599 if(size < 9) {
600 *MSVCRT__errno() = MSVCRT_ERANGE;
601 return MSVCRT_ERANGE;
604 MSVCRT__strdate(date);
605 return 0;
608 /**********************************************************************
609 * _wstrdate (MSVCRT.@)
611 MSVCRT_wchar_t* CDECL MSVCRT__wstrdate(MSVCRT_wchar_t* date)
613 static const WCHAR format[] = { 'M','M','\'','/','\'','d','d','\'','/','\'','y','y',0 };
615 GetDateFormatW(LOCALE_NEUTRAL, 0, NULL, format, date, 9);
617 return date;
620 /**********************************************************************
621 * _wstrdate_s (MSVCRT.@)
623 int CDECL _wstrdate_s(MSVCRT_wchar_t* date, MSVCRT_size_t size)
625 if(date && size)
626 date[0] = '\0';
628 if(!date) {
629 *MSVCRT__errno() = MSVCRT_EINVAL;
630 return MSVCRT_EINVAL;
633 if(size < 9) {
634 *MSVCRT__errno() = MSVCRT_ERANGE;
635 return MSVCRT_ERANGE;
638 MSVCRT__wstrdate(date);
639 return 0;
642 /*********************************************************************
643 * _strtime (MSVCRT.@)
645 char* CDECL MSVCRT__strtime(char* time)
647 static const char format[] = "HH':'mm':'ss";
649 GetTimeFormatA(LOCALE_NEUTRAL, 0, NULL, format, time, 9);
651 return time;
654 /*********************************************************************
655 * _strtime_s (MSVCRT.@)
657 int CDECL _strtime_s(char* time, MSVCRT_size_t size)
659 if(time && size)
660 time[0] = '\0';
662 if(!time) {
663 *MSVCRT__errno() = MSVCRT_EINVAL;
664 return MSVCRT_EINVAL;
667 if(size < 9) {
668 *MSVCRT__errno() = MSVCRT_ERANGE;
669 return MSVCRT_ERANGE;
672 MSVCRT__strtime(time);
673 return 0;
676 /*********************************************************************
677 * _wstrtime (MSVCRT.@)
679 MSVCRT_wchar_t* CDECL MSVCRT__wstrtime(MSVCRT_wchar_t* time)
681 static const WCHAR format[] = { 'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0 };
683 GetTimeFormatW(LOCALE_NEUTRAL, 0, NULL, format, time, 9);
685 return time;
688 /*********************************************************************
689 * _wstrtime_s (MSVCRT.@)
691 int CDECL _wstrtime_s(MSVCRT_wchar_t* time, MSVCRT_size_t size)
693 if(time && size)
694 time[0] = '\0';
696 if(!time) {
697 *MSVCRT__errno() = MSVCRT_EINVAL;
698 return MSVCRT_EINVAL;
701 if(size < 9) {
702 *MSVCRT__errno() = MSVCRT_ERANGE;
703 return MSVCRT_ERANGE;
706 MSVCRT__wstrtime(time);
707 return 0;
710 /*********************************************************************
711 * clock (MSVCRT.@)
713 MSVCRT_clock_t CDECL MSVCRT_clock(void)
715 static LONGLONG start_time;
716 LARGE_INTEGER systime;
718 if(!start_time) {
719 KERNEL_USER_TIMES pti;
721 /* while Linux's clock returns user time, Windows' clock
722 * returns wall-clock time from process start. cache the
723 * process start time since it won't change and to avoid
724 * wineserver round-trip overhead */
725 if(NtQueryInformationProcess(GetCurrentProcess(), ProcessTimes, &pti, sizeof(pti), NULL))
726 return -1;
727 start_time = pti.CreateTime.QuadPart;
730 NtQuerySystemTime(&systime);
731 return (systime.QuadPart - start_time) * MSVCRT_CLOCKS_PER_SEC / TICKSPERSEC;
734 /*********************************************************************
735 * _difftime64 (MSVCRT.@)
737 double CDECL MSVCRT__difftime64(MSVCRT___time64_t time1, MSVCRT___time64_t time2)
739 return (double)(time1 - time2);
742 /*********************************************************************
743 * _difftime32 (MSVCRT.@)
745 double CDECL MSVCRT__difftime32(MSVCRT___time32_t time1, MSVCRT___time32_t time2)
747 return (double)(time1 - time2);
750 /*********************************************************************
751 * difftime (MSVCRT.@)
753 #ifdef _WIN64
754 double CDECL MSVCRT_difftime(MSVCRT___time64_t time1, MSVCRT___time64_t time2)
756 return MSVCRT__difftime64( time1, time2 );
758 #else
759 double CDECL MSVCRT_difftime(MSVCRT___time32_t time1, MSVCRT___time32_t time2)
761 return MSVCRT__difftime32( time1, time2 );
763 #endif
765 /*********************************************************************
766 * _ftime64 (MSVCRT.@)
768 void CDECL MSVCRT__ftime64(struct MSVCRT___timeb64 *buf)
770 FILETIME ft;
771 ULONGLONG time;
773 _tzset_init();
775 GetSystemTimeAsFileTime(&ft);
777 time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
779 buf->time = time / TICKSPERSEC - SECS_1601_TO_1970;
780 buf->millitm = (time % TICKSPERSEC) / TICKSPERMSEC;
781 buf->timezone = MSVCRT___timezone / 60;
782 buf->dstflag = GetDaylightFlag();
785 /*********************************************************************
786 * _ftime64_s (MSVCRT.@)
788 int CDECL MSVCRT__ftime64_s(struct MSVCRT___timeb64 *buf)
790 if (!MSVCRT_CHECK_PMT( buf != NULL )) return MSVCRT_EINVAL;
791 MSVCRT__ftime64(buf);
792 return 0;
795 /*********************************************************************
796 * _ftime32 (MSVCRT.@)
798 void CDECL MSVCRT__ftime32(struct MSVCRT___timeb32 *buf)
800 struct MSVCRT___timeb64 buf64;
802 MSVCRT__ftime64( &buf64 );
803 buf->time = buf64.time;
804 buf->millitm = buf64.millitm;
805 buf->timezone = buf64.timezone;
806 buf->dstflag = buf64.dstflag;
809 /*********************************************************************
810 * _ftime32_s (MSVCRT.@)
812 int CDECL MSVCRT__ftime32_s(struct MSVCRT___timeb32 *buf)
814 if (!MSVCRT_CHECK_PMT( buf != NULL )) return MSVCRT_EINVAL;
815 MSVCRT__ftime32(buf);
816 return 0;
819 /*********************************************************************
820 * _ftime (MSVCRT.@)
822 #ifdef _WIN64
823 void CDECL MSVCRT__ftime(struct MSVCRT___timeb64 *buf)
825 MSVCRT__ftime64( buf );
827 #else
828 void CDECL MSVCRT__ftime(struct MSVCRT___timeb32 *buf)
830 MSVCRT__ftime32( buf );
832 #endif
834 /*********************************************************************
835 * _time64 (MSVCRT.@)
837 MSVCRT___time64_t CDECL MSVCRT__time64(MSVCRT___time64_t *buf)
839 MSVCRT___time64_t curtime;
840 struct MSVCRT___timeb64 tb;
842 MSVCRT__ftime64(&tb);
844 curtime = tb.time;
845 return buf ? *buf = curtime : curtime;
848 /*********************************************************************
849 * _time32 (MSVCRT.@)
851 MSVCRT___time32_t CDECL MSVCRT__time32(MSVCRT___time32_t *buf)
853 MSVCRT___time32_t curtime;
854 struct MSVCRT___timeb64 tb;
856 MSVCRT__ftime64(&tb);
858 curtime = tb.time;
859 return buf ? *buf = curtime : curtime;
862 /*********************************************************************
863 * time (MSVCRT.@)
865 #ifdef _WIN64
866 MSVCRT___time64_t CDECL MSVCRT_time(MSVCRT___time64_t* buf)
868 return MSVCRT__time64( buf );
870 #else
871 MSVCRT___time32_t CDECL MSVCRT_time(MSVCRT___time32_t* buf)
873 return MSVCRT__time32( buf );
875 #endif
877 /*********************************************************************
878 * __p__daylight (MSVCRT.@)
880 int * CDECL MSVCRT___p__daylight(void)
882 return &MSVCRT___daylight;
885 /*********************************************************************
886 * __p__dstbias (MSVCRT.@)
888 int * CDECL MSVCRT___p__dstbias(void)
890 return &MSVCRT__dstbias;
893 #if _MSVCR_VER >= 80
894 /*********************************************************************
895 * _get_dstbias (MSVCR80.@)
897 int CDECL MSVCRT__get_dstbias(int *seconds)
899 if (!MSVCRT_CHECK_PMT(seconds != NULL)) return MSVCRT_EINVAL;
900 *seconds = MSVCRT__dstbias;
901 return 0;
903 #endif
905 /*********************************************************************
906 * __p__timezone (MSVCRT.@)
908 MSVCRT_long * CDECL MSVCRT___p__timezone(void)
910 return &MSVCRT___timezone;
913 /*********************************************************************
914 * _get_tzname (MSVCRT.@)
916 int CDECL MSVCRT__get_tzname(MSVCRT_size_t *ret, char *buf, MSVCRT_size_t bufsize, int index)
918 char *timezone;
920 switch(index)
922 case 0:
923 timezone = tzname_std;
924 break;
925 case 1:
926 timezone = tzname_dst;
927 break;
928 default:
929 *MSVCRT__errno() = MSVCRT_EINVAL;
930 return MSVCRT_EINVAL;
933 if(!ret || (!buf && bufsize > 0) || (buf && !bufsize))
935 *MSVCRT__errno() = MSVCRT_EINVAL;
936 return MSVCRT_EINVAL;
939 *ret = strlen(timezone)+1;
940 if(!buf && !bufsize)
941 return 0;
942 if(*ret > bufsize)
944 buf[0] = 0;
945 return MSVCRT_ERANGE;
948 strcpy(buf, timezone);
949 return 0;
952 /*********************************************************************
953 * __p_tzname (MSVCRT.@)
955 char ** CDECL __p__tzname(void)
957 return MSVCRT__tzname;
960 static inline BOOL strftime_date(char *str, MSVCRT_size_t *pos, MSVCRT_size_t max,
961 BOOL alternate, const struct MSVCRT_tm *mstm, MSVCRT___lc_time_data *time_data)
963 char *format;
964 SYSTEMTIME st;
965 MSVCRT_size_t ret;
966 LCID lcid;
968 st.wYear = mstm->tm_year + 1900;
969 st.wMonth = mstm->tm_mon + 1;
970 st.wDayOfWeek = mstm->tm_wday;
971 st.wDay = mstm->tm_mday;
972 st.wHour = mstm->tm_hour;
973 st.wMinute = mstm->tm_min;
974 st.wSecond = mstm->tm_sec;
975 st.wMilliseconds = 0;
977 #if _MSVCR_VER < 110
978 lcid = time_data->lcid;
979 #else
980 lcid = LocaleNameToLCID(time_data->locname, 0);
981 #endif
983 format = alternate ? time_data->str.names.date : time_data->str.names.short_date;
984 ret = GetDateFormatA(lcid, 0, &st, format, NULL, 0);
985 if(ret && ret<max-*pos)
986 ret = GetDateFormatA(lcid, 0, &st, format, str+*pos, max-*pos);
987 if(!ret) {
988 *str = 0;
989 *MSVCRT__errno() = MSVCRT_EINVAL;
990 return FALSE;
991 }else if(ret > max-*pos) {
992 *str = 0;
993 *MSVCRT__errno() = MSVCRT_ERANGE;
994 return FALSE;
996 *pos += ret-1;
997 return TRUE;
1000 static inline BOOL strftime_time(char *str, MSVCRT_size_t *pos, MSVCRT_size_t max,
1001 const struct MSVCRT_tm *mstm, MSVCRT___lc_time_data *time_data)
1003 SYSTEMTIME st;
1004 MSVCRT_size_t ret;
1005 LCID lcid;
1007 st.wYear = mstm->tm_year + 1900;
1008 st.wMonth = mstm->tm_mon + 1;
1009 st.wDayOfWeek = mstm->tm_wday;
1010 st.wDay = mstm->tm_mday;
1011 st.wHour = mstm->tm_hour;
1012 st.wMinute = mstm->tm_min;
1013 st.wSecond = mstm->tm_sec;
1014 st.wMilliseconds = 0;
1016 #if _MSVCR_VER < 110
1017 lcid = time_data->lcid;
1018 #else
1019 lcid = LocaleNameToLCID(time_data->locname, 0);
1020 #endif
1022 ret = GetTimeFormatA(lcid, 0, &st, time_data->str.names.time, NULL, 0);
1023 if(ret && ret<max-*pos)
1024 ret = GetTimeFormatA(lcid, 0, &st, time_data->str.names.time,
1025 str+*pos, max-*pos);
1026 if(!ret) {
1027 *str = 0;
1028 *MSVCRT__errno() = MSVCRT_EINVAL;
1029 return FALSE;
1030 }else if(ret > max-*pos) {
1031 *str = 0;
1032 *MSVCRT__errno() = MSVCRT_ERANGE;
1033 return FALSE;
1035 *pos += ret-1;
1036 return TRUE;
1039 static inline BOOL strftime_str(char *str, MSVCRT_size_t *pos, MSVCRT_size_t max, char *src)
1041 MSVCRT_size_t len = strlen(src);
1042 if(len > max-*pos) {
1043 *str = 0;
1044 *MSVCRT__errno() = MSVCRT_ERANGE;
1045 return FALSE;
1048 memcpy(str+*pos, src, len);
1049 *pos += len;
1050 return TRUE;
1053 static inline BOOL strftime_int(char *str, MSVCRT_size_t *pos, MSVCRT_size_t max,
1054 int src, int prec, int l, int h)
1056 MSVCRT_size_t len;
1058 if(src<l || src>h) {
1059 *str = 0;
1060 *MSVCRT__errno() = MSVCRT_EINVAL;
1061 return FALSE;
1064 len = MSVCRT__snprintf(str+*pos, max-*pos, "%0*d", prec, src);
1065 if(len == -1) {
1066 *str = 0;
1067 *MSVCRT__errno() = MSVCRT_ERANGE;
1068 return FALSE;
1071 *pos += len;
1072 return TRUE;
1075 static MSVCRT_size_t strftime_helper(char *str, MSVCRT_size_t max, const char *format,
1076 const struct MSVCRT_tm *mstm, MSVCRT___lc_time_data *time_data, MSVCRT__locale_t loc)
1078 MSVCRT_size_t ret, tmp;
1079 BOOL alternate;
1081 TRACE("(%p %ld %s %p %p)\n", str, max, format, mstm, time_data);
1083 if(!str || !format) {
1084 if(str && max)
1085 *str = 0;
1086 *MSVCRT__errno() = MSVCRT_EINVAL;
1087 return 0;
1090 if(!time_data)
1091 time_data = loc ? loc->locinfo->lc_time_curr : get_locinfo()->lc_time_curr;
1093 for(ret=0; *format && ret<max; format++) {
1094 if(*format != '%') {
1095 if(MSVCRT__isleadbyte_l((unsigned char)*format, loc)) {
1096 str[ret++] = *(format++);
1097 if(ret == max) continue;
1098 if(!str[ret]) goto einval_error;
1100 str[ret++] = *format;
1101 continue;
1104 format++;
1105 if(*format == '#') {
1106 alternate = TRUE;
1107 format++;
1108 }else {
1109 alternate = FALSE;
1112 if(!mstm)
1113 goto einval_error;
1115 switch(*format) {
1116 case 'c':
1117 if(!strftime_date(str, &ret, max, alternate, mstm, time_data))
1118 return 0;
1119 if(ret < max)
1120 str[ret++] = ' ';
1121 if(!strftime_time(str, &ret, max, mstm, time_data))
1122 return 0;
1123 break;
1124 case 'x':
1125 if(!strftime_date(str, &ret, max, alternate, mstm, time_data))
1126 return 0;
1127 break;
1128 case 'X':
1129 if(!strftime_time(str, &ret, max, mstm, time_data))
1130 return 0;
1131 break;
1132 case 'a':
1133 if(mstm->tm_wday<0 || mstm->tm_wday>6)
1134 goto einval_error;
1135 if(!strftime_str(str, &ret, max, time_data->str.names.short_wday[mstm->tm_wday]))
1136 return 0;
1137 break;
1138 case 'A':
1139 if(mstm->tm_wday<0 || mstm->tm_wday>6)
1140 goto einval_error;
1141 if(!strftime_str(str, &ret, max, time_data->str.names.wday[mstm->tm_wday]))
1142 return 0;
1143 break;
1144 case 'b':
1145 if(mstm->tm_mon<0 || mstm->tm_mon>11)
1146 goto einval_error;
1147 if(!strftime_str(str, &ret, max, time_data->str.names.short_mon[mstm->tm_mon]))
1148 return 0;
1149 break;
1150 case 'B':
1151 if(mstm->tm_mon<0 || mstm->tm_mon>11)
1152 goto einval_error;
1153 if(!strftime_str(str, &ret, max, time_data->str.names.mon[mstm->tm_mon]))
1154 return 0;
1155 break;
1156 case 'd':
1157 if(!strftime_int(str, &ret, max, mstm->tm_mday, alternate ? 0 : 2, 0, 31))
1158 return 0;
1159 break;
1160 case 'H':
1161 if(!strftime_int(str, &ret, max, mstm->tm_hour, alternate ? 0 : 2, 0, 23))
1162 return 0;
1163 break;
1164 case 'I':
1165 tmp = mstm->tm_hour;
1166 if(tmp > 12)
1167 tmp -= 12;
1168 else if(!tmp)
1169 tmp = 12;
1170 if(!strftime_int(str, &ret, max, tmp, alternate ? 0 : 2, 1, 12))
1171 return 0;
1172 break;
1173 case 'j':
1174 if(!strftime_int(str, &ret, max, mstm->tm_yday+1, alternate ? 0 : 3, 1, 366))
1175 return 0;
1176 break;
1177 case 'm':
1178 if(!strftime_int(str, &ret, max, mstm->tm_mon+1, alternate ? 0 : 2, 1, 12))
1179 return 0;
1180 break;
1181 case 'M':
1182 if(!strftime_int(str, &ret, max, mstm->tm_min, alternate ? 0 : 2, 0, 59))
1183 return 0;
1184 break;
1185 case 'p':
1186 if(mstm->tm_hour<0 || mstm->tm_hour>23)
1187 goto einval_error;
1188 if(!strftime_str(str, &ret, max, mstm->tm_hour<12 ?
1189 time_data->str.names.am : time_data->str.names.pm))
1190 return 0;
1191 break;
1192 case 'S':
1193 if(!strftime_int(str, &ret, max, mstm->tm_sec, alternate ? 0 : 2, 0, 59))
1194 return 0;
1195 break;
1196 case 'w':
1197 if(!strftime_int(str, &ret, max, mstm->tm_wday, 0, 0, 6))
1198 return 0;
1199 break;
1200 case 'y':
1201 if(!strftime_int(str, &ret, max, mstm->tm_year%100, alternate ? 0 : 2, 0, 99))
1202 return 0;
1203 break;
1204 case 'Y':
1205 tmp = 1900+mstm->tm_year;
1206 if(!strftime_int(str, &ret, max, tmp, alternate ? 0 : 4, 0, 9999))
1207 return 0;
1208 break;
1209 case 'z':
1210 case 'Z':
1211 MSVCRT__tzset();
1212 if(MSVCRT__get_tzname(&tmp, str+ret, max-ret, mstm->tm_isdst ? 1 : 0))
1213 return 0;
1214 ret += tmp-1;
1215 break;
1216 case 'U':
1217 case 'W':
1218 if(mstm->tm_wday<0 || mstm->tm_wday>6 || mstm->tm_yday<0 || mstm->tm_yday>365)
1219 goto einval_error;
1220 if(*format == 'U')
1221 tmp = mstm->tm_wday;
1222 else if(!mstm->tm_wday)
1223 tmp = 6;
1224 else
1225 tmp = mstm->tm_wday-1;
1227 tmp = mstm->tm_yday/7 + (tmp<=mstm->tm_yday%7);
1228 if(!strftime_int(str, &ret, max, tmp, alternate ? 0 : 2, 0, 53))
1229 return 0;
1230 break;
1231 case '%':
1232 str[ret++] = '%';
1233 break;
1234 default:
1235 WARN("unknown format %c\n", *format);
1236 goto einval_error;
1240 if(ret == max) {
1241 if(max)
1242 *str = 0;
1243 *MSVCRT__errno() = MSVCRT_ERANGE;
1244 return 0;
1247 str[ret] = 0;
1248 return ret;
1250 einval_error:
1251 *str = 0;
1252 *MSVCRT__errno() = MSVCRT_EINVAL;
1253 return 0;
1256 #if _MSVCR_VER >= 80
1257 /********************************************************************
1258 * _strftime_l (MSVCR80.@)
1260 MSVCRT_size_t CDECL MSVCRT__strftime_l( char *str, MSVCRT_size_t max, const char *format,
1261 const struct MSVCRT_tm *mstm, MSVCRT__locale_t loc )
1263 return strftime_helper(str, max, format, mstm, NULL, loc);
1265 #endif
1267 /*********************************************************************
1268 * _Strftime (MSVCRT.@)
1270 MSVCRT_size_t CDECL _Strftime(char *str, MSVCRT_size_t max, const char *format,
1271 const struct MSVCRT_tm *mstm, MSVCRT___lc_time_data *time_data)
1273 return strftime_helper(str, max, format, mstm, time_data, NULL);
1276 /*********************************************************************
1277 * strftime (MSVCRT.@)
1279 MSVCRT_size_t CDECL MSVCRT_strftime( char *str, MSVCRT_size_t max, const char *format,
1280 const struct MSVCRT_tm *mstm )
1282 return strftime_helper(str, max, format, mstm, NULL, NULL);
1285 static MSVCRT_size_t wcsftime_helper( MSVCRT_wchar_t *str, MSVCRT_size_t max,
1286 const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm,
1287 MSVCRT___lc_time_data *time_data, MSVCRT__locale_t loc )
1289 char *s, *fmt;
1290 MSVCRT_size_t len;
1292 TRACE("%p %ld %s %p %p %p\n", str, max, debugstr_w(format), mstm, time_data, loc);
1294 len = MSVCRT__wcstombs_l( NULL, format, 0, loc ) + 1;
1295 if (!(fmt = MSVCRT_malloc( len ))) return 0;
1296 MSVCRT__wcstombs_l(fmt, format, len, loc);
1298 if ((s = MSVCRT_malloc( max*4 )))
1300 if (!strftime_helper( s, max*4, fmt, mstm, time_data, loc )) s[0] = 0;
1301 len = MSVCRT__mbstowcs_l( str, s, max, loc );
1302 MSVCRT_free( s );
1304 else len = 0;
1306 MSVCRT_free( fmt );
1307 return len;
1310 /*********************************************************************
1311 * _wcsftime_l (MSVCRT.@)
1313 MSVCRT_size_t CDECL MSVCRT__wcsftime_l( MSVCRT_wchar_t *str, MSVCRT_size_t max,
1314 const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm, MSVCRT__locale_t loc )
1316 return wcsftime_helper(str, max, format, mstm, NULL, loc);
1319 /*********************************************************************
1320 * wcsftime (MSVCRT.@)
1322 MSVCRT_size_t CDECL MSVCRT_wcsftime( MSVCRT_wchar_t *str, MSVCRT_size_t max,
1323 const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm )
1325 return wcsftime_helper(str, max, format, mstm, NULL, NULL);
1328 #if _MSVCR_VER >= 110
1329 /*********************************************************************
1330 * _Wcsftime (MSVCR110.@)
1332 MSVCRT_size_t CDECL _Wcsftime(MSVCRT_wchar_t *str, MSVCRT_size_t max,
1333 const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm,
1334 MSVCRT___lc_time_data *time_data)
1336 return wcsftime_helper(str, max, format, mstm, time_data, NULL);
1338 #endif
1340 static char* asctime_buf(char *buf, const struct MSVCRT_tm *mstm)
1342 static const char wday[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
1343 static const char month[12][4] = {"Jan", "Feb", "Mar", "Apr", "May",
1344 "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
1346 if (!mstm || mstm->tm_sec<0 || mstm->tm_sec>59
1347 || mstm->tm_min<0 || mstm->tm_min>59
1348 || mstm->tm_hour<0 || mstm->tm_hour>23
1349 || mstm->tm_mon<0 || mstm->tm_mon>11
1350 || mstm->tm_wday<0 || mstm->tm_wday>6
1351 || mstm->tm_year<0 || mstm->tm_mday<0
1352 || mstm->tm_mday>MonthLengths[IsLeapYear(1900+mstm->tm_year)][mstm->tm_mon]) {
1353 *MSVCRT__errno() = MSVCRT_EINVAL;
1354 return NULL;
1357 #if _MSVCR_VER>=140
1358 /* C89 (4.12.3.1) uses space-padding for day of month. */
1359 MSVCRT__snprintf(buf, 26, "%s %s %2d %02d:%02d:%02d %c%03d\n", wday[mstm->tm_wday],
1360 month[mstm->tm_mon], mstm->tm_mday, mstm->tm_hour, mstm->tm_min,
1361 mstm->tm_sec, '1'+(mstm->tm_year+900)/1000, (900+mstm->tm_year)%1000);
1362 #else
1363 MSVCRT__snprintf(buf, 26, "%s %s %02d %02d:%02d:%02d %c%03d\n", wday[mstm->tm_wday],
1364 month[mstm->tm_mon], mstm->tm_mday, mstm->tm_hour, mstm->tm_min,
1365 mstm->tm_sec, '1'+(mstm->tm_year+900)/1000, (900+mstm->tm_year)%1000);
1366 #endif
1367 return buf;
1370 /*********************************************************************
1371 * asctime (MSVCRT.@)
1373 char * CDECL MSVCRT_asctime(const struct MSVCRT_tm *mstm)
1375 thread_data_t *data = msvcrt_get_thread_data();
1377 /* asctime returns date in format that always has exactly 26 characters */
1378 if (!data->asctime_buffer) {
1379 data->asctime_buffer = MSVCRT_malloc(26);
1380 if (!data->asctime_buffer) {
1381 *MSVCRT__errno() = MSVCRT_ENOMEM;
1382 return NULL;
1386 return asctime_buf(data->asctime_buffer, mstm);
1389 /*********************************************************************
1390 * asctime_s (MSVCRT.@)
1392 int CDECL MSVCRT_asctime_s(char* time, MSVCRT_size_t size, const struct MSVCRT_tm *mstm)
1394 if (!MSVCRT_CHECK_PMT(time != NULL)) return MSVCRT_EINVAL;
1395 if (size) time[0] = 0;
1396 if (!MSVCRT_CHECK_PMT(size >= 26)) return MSVCRT_EINVAL;
1397 if (!MSVCRT_CHECK_PMT(mstm != NULL)) return MSVCRT_EINVAL;
1398 if (!MSVCRT_CHECK_PMT(mstm->tm_sec >= 0 && mstm->tm_sec < 60)) return MSVCRT_EINVAL;
1399 if (!MSVCRT_CHECK_PMT(mstm->tm_min >= 0 && mstm->tm_min < 60)) return MSVCRT_EINVAL;
1400 if (!MSVCRT_CHECK_PMT(mstm->tm_hour >= 0 && mstm->tm_hour < 24)) return MSVCRT_EINVAL;
1401 if (!MSVCRT_CHECK_PMT(mstm->tm_mon >= 0 && mstm->tm_mon < 12)) return MSVCRT_EINVAL;
1402 if (!MSVCRT_CHECK_PMT(mstm->tm_wday >= 0 && mstm->tm_wday < 7)) return MSVCRT_EINVAL;
1403 if (!MSVCRT_CHECK_PMT(mstm->tm_year >= 0)) return MSVCRT_EINVAL;
1404 if (!MSVCRT_CHECK_PMT(mstm->tm_mday >= 0)) return MSVCRT_EINVAL;
1405 if (!MSVCRT_CHECK_PMT(mstm->tm_mday <= MonthLengths[IsLeapYear(1900+mstm->tm_year)][mstm->tm_mon])) return MSVCRT_EINVAL;
1407 asctime_buf(time, mstm);
1408 return 0;
1411 /*********************************************************************
1412 * _wasctime (MSVCRT.@)
1414 MSVCRT_wchar_t * CDECL MSVCRT__wasctime(const struct MSVCRT_tm *mstm)
1416 thread_data_t *data = msvcrt_get_thread_data();
1417 char buffer[26];
1419 if(!data->wasctime_buffer) {
1420 data->wasctime_buffer = MSVCRT_malloc(26*sizeof(MSVCRT_wchar_t));
1421 if(!data->wasctime_buffer) {
1422 *MSVCRT__errno() = MSVCRT_ENOMEM;
1423 return NULL;
1427 if(!asctime_buf(buffer, mstm))
1428 return NULL;
1430 MultiByteToWideChar(CP_ACP, 0, buffer, -1, data->wasctime_buffer, 26);
1431 return data->wasctime_buffer;
1434 /*********************************************************************
1435 * _wasctime_s (MSVCRT.@)
1437 int CDECL MSVCRT__wasctime_s(MSVCRT_wchar_t* time, MSVCRT_size_t size, const struct MSVCRT_tm *mstm)
1439 char buffer[26];
1440 int ret;
1442 if (!MSVCRT_CHECK_PMT(time != NULL)) return MSVCRT_EINVAL;
1443 if (size) time[0] = 0;
1444 if (!MSVCRT_CHECK_PMT(size >= 26)) return MSVCRT_EINVAL;
1445 if (!MSVCRT_CHECK_PMT(mstm != NULL)) return MSVCRT_EINVAL;
1447 ret = MSVCRT_asctime_s(buffer, sizeof(buffer), mstm);
1448 if(ret)
1449 return ret;
1450 MultiByteToWideChar(CP_ACP, 0, buffer, -1, time, size);
1451 return 0;
1454 /*********************************************************************
1455 * _ctime64 (MSVCRT.@)
1457 char * CDECL MSVCRT__ctime64(const MSVCRT___time64_t *time)
1459 struct MSVCRT_tm *t;
1460 t = MSVCRT__localtime64( time );
1461 if (!t) return NULL;
1462 return MSVCRT_asctime( t );
1465 /*********************************************************************
1466 * _ctime64_s (MSVCRT.@)
1468 int CDECL MSVCRT__ctime64_s(char *res, MSVCRT_size_t len, const MSVCRT___time64_t *time)
1470 struct MSVCRT_tm *t;
1472 if (!MSVCRT_CHECK_PMT( res != NULL )) return MSVCRT_EINVAL;
1473 if (!MSVCRT_CHECK_PMT( len >= 26 )) return MSVCRT_EINVAL;
1474 res[0] = '\0';
1475 if (!MSVCRT_CHECK_PMT( time != NULL )) return MSVCRT_EINVAL;
1476 if (!MSVCRT_CHECK_PMT( *time > 0 )) return MSVCRT_EINVAL;
1478 t = MSVCRT__localtime64( time );
1479 strcpy( res, MSVCRT_asctime( t ) );
1480 return 0;
1483 /*********************************************************************
1484 * _ctime32 (MSVCRT.@)
1486 char * CDECL MSVCRT__ctime32(const MSVCRT___time32_t *time)
1488 struct MSVCRT_tm *t;
1489 t = MSVCRT__localtime32( time );
1490 if (!t) return NULL;
1491 return MSVCRT_asctime( t );
1494 /*********************************************************************
1495 * _ctime32_s (MSVCRT.@)
1497 int CDECL MSVCRT__ctime32_s(char *res, MSVCRT_size_t len, const MSVCRT___time32_t *time)
1499 struct MSVCRT_tm *t;
1501 if (!MSVCRT_CHECK_PMT( res != NULL )) return MSVCRT_EINVAL;
1502 if (!MSVCRT_CHECK_PMT( len >= 26 )) return MSVCRT_EINVAL;
1503 res[0] = '\0';
1504 if (!MSVCRT_CHECK_PMT( time != NULL )) return MSVCRT_EINVAL;
1505 if (!MSVCRT_CHECK_PMT( *time > 0 )) return MSVCRT_EINVAL;
1507 t = MSVCRT__localtime32( time );
1508 strcpy( res, MSVCRT_asctime( t ) );
1509 return 0;
1512 /*********************************************************************
1513 * ctime (MSVCRT.@)
1515 #ifdef _WIN64
1516 char * CDECL MSVCRT_ctime(const MSVCRT___time64_t *time)
1518 return MSVCRT__ctime64( time );
1520 #else
1521 char * CDECL MSVCRT_ctime(const MSVCRT___time32_t *time)
1523 return MSVCRT__ctime32( time );
1525 #endif
1527 /*********************************************************************
1528 * _wctime64 (MSVCRT.@)
1530 MSVCRT_wchar_t * CDECL MSVCRT__wctime64(const MSVCRT___time64_t *time)
1532 return MSVCRT__wasctime( MSVCRT__localtime64(time) );
1535 /*********************************************************************
1536 * _wctime32 (MSVCRT.@)
1538 MSVCRT_wchar_t * CDECL MSVCRT__wctime32(const MSVCRT___time32_t *time)
1540 return MSVCRT__wasctime( MSVCRT__localtime32(time) );
1543 /*********************************************************************
1544 * _wctime (MSVCRT.@)
1546 #ifdef _WIN64
1547 MSVCRT_wchar_t * CDECL MSVCRT__wctime(const MSVCRT___time64_t *time)
1549 return MSVCRT__wctime64( time );
1551 #else
1552 MSVCRT_wchar_t * CDECL MSVCRT__wctime(const MSVCRT___time32_t *time)
1554 return MSVCRT__wctime32( time );
1556 #endif
1558 /*********************************************************************
1559 * _wctime64_s (MSVCRT.@)
1561 int CDECL MSVCRT__wctime64_s(MSVCRT_wchar_t *buf,
1562 MSVCRT_size_t size, const MSVCRT___time64_t *time)
1564 struct MSVCRT_tm tm;
1565 int ret;
1567 if(!MSVCRT_CHECK_PMT(buf != NULL)) return MSVCRT_EINVAL;
1568 if(!MSVCRT_CHECK_PMT(size != 0)) return MSVCRT_EINVAL;
1569 buf[0] = 0;
1570 if(!MSVCRT_CHECK_PMT(time != NULL)) return MSVCRT_EINVAL;
1571 if(!MSVCRT_CHECK_PMT(*time >= 0)) return MSVCRT_EINVAL;
1572 if(!MSVCRT_CHECK_PMT(*time <= _MAX__TIME64_T)) return MSVCRT_EINVAL;
1574 ret = _localtime64_s(&tm, time);
1575 if(ret != 0)
1576 return ret;
1578 return MSVCRT__wasctime_s(buf, size, &tm);
1581 /*********************************************************************
1582 * _wctime32_s (MSVCRT.@)
1584 int CDECL MSVCRT__wctime32_s(MSVCRT_wchar_t *buf, MSVCRT_size_t size,
1585 const MSVCRT___time32_t *time)
1587 struct MSVCRT_tm tm;
1588 int ret;
1590 if(!MSVCRT_CHECK_PMT(buf != NULL)) return MSVCRT_EINVAL;
1591 if(!MSVCRT_CHECK_PMT(size != 0)) return MSVCRT_EINVAL;
1592 buf[0] = 0;
1593 if(!MSVCRT_CHECK_PMT(time != NULL)) return MSVCRT_EINVAL;
1594 if(!MSVCRT_CHECK_PMT(*time >= 0)) return MSVCRT_EINVAL;
1596 ret = _localtime32_s(&tm, time);
1597 if(ret != 0)
1598 return ret;
1600 return MSVCRT__wasctime_s(buf, size, &tm);
1603 #if _MSVCR_VER >= 80
1605 /*********************************************************************
1606 * _get_timezone (MSVCR80.@)
1608 int CDECL _get_timezone(LONG *timezone)
1610 if(!MSVCRT_CHECK_PMT(timezone != NULL)) return MSVCRT_EINVAL;
1612 *timezone = MSVCRT___timezone;
1613 return 0;
1616 /*********************************************************************
1617 * _get_daylight (MSVCR80.@)
1619 int CDECL _get_daylight(int *hours)
1621 if(!MSVCRT_CHECK_PMT(hours != NULL)) return MSVCRT_EINVAL;
1623 *hours = MSVCRT___daylight;
1624 return 0;
1627 #endif /* _MSVCR_VER >= 80 */
1629 #if _MSVCR_VER >= 140
1631 #define TIME_UTC 1
1633 struct _timespec32
1635 MSVCRT___time32_t tv_sec;
1636 LONG tv_nsec;
1639 struct _timespec64
1641 MSVCRT___time64_t tv_sec;
1642 LONG tv_nsec;
1645 /*********************************************************************
1646 * _timespec64_get (UCRTBASE.@)
1648 int CDECL _timespec64_get(struct _timespec64 *ts, int base)
1650 ULONGLONG time;
1651 FILETIME ft;
1653 if(!MSVCRT_CHECK_PMT(ts != NULL)) return 0;
1654 if(base != TIME_UTC) return 0;
1656 GetSystemTimePreciseAsFileTime(&ft);
1657 time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
1659 ts->tv_sec = time / TICKSPERSEC - SECS_1601_TO_1970;
1660 ts->tv_nsec = time % TICKSPERSEC * 100;
1661 return base;
1664 /*********************************************************************
1665 * _timespec32_get (UCRTBASE.@)
1667 int CDECL _timespec32_get(struct _timespec32 *ts, int base)
1669 struct _timespec64 ts64;
1671 if(_timespec64_get(&ts64, base) != base)
1672 return 0;
1673 if(ts64.tv_sec != (MSVCRT___time32_t)ts64.tv_sec)
1674 return 0;
1676 ts->tv_sec = ts64.tv_sec;
1677 ts->tv_nsec = ts64.tv_nsec;
1678 return base;
1680 #endif /* _MSVCR_VER >= 140 */