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
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
)
65 /*********************************************************************
66 * _daylight (MSVCRT.@)
68 int MSVCRT___daylight
= 1;
70 /*********************************************************************
71 * _timezone (MSVCRT.@)
73 MSVCRT_long MSVCRT___timezone
= 28800;
75 /*********************************************************************
78 int MSVCRT__dstbias
= -3600;
80 /*********************************************************************
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 /*********************************************************************
94 void CDECL
MSVCRT__tzset(void)
96 char *tz
= MSVCRT_getenv("TZ");
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);
112 }else if(*tz
== '+') {
115 MSVCRT___timezone
= strtol(tz
, &tz
, 10)*3600;
117 MSVCRT___timezone
+= strtol(tz
+1, &tz
, 10)*60;
119 MSVCRT___timezone
+= strtol(tz
+1, &tz
, 10);
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;
135 MSVCRT___daylight
= 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
;
159 _munlock(_TIME_LOCK
);
163 static BOOL
is_dst(const SYSTEMTIME
*st
)
165 TIME_ZONE_INFORMATION tmp
;
168 if(!MSVCRT___daylight
)
171 if(tzi
.DaylightDate
.wMonth
) {
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;
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;
192 tmp
.StandardBias
= 0;
193 tmp
.DaylightBias
= MSVCRT__dstbias
/60;
194 if(!SystemTimeToTzSpecificLocalTime(&tmp
, st
, &out
))
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
)
211 MSVCRT___time64_t ret
= 0;
213 BOOL use_dst
= FALSE
;
215 ret
= mstm
->tm_year
+ mstm
->tm_mon
/12;
217 if(mstm
->tm_mon
< 0) {
222 if(ret
<70 || ret
>1100) {
223 *MSVCRT__errno() = MSVCRT_EINVAL
;
227 memset(&st
, 0, sizeof(SYSTEMTIME
));
229 st
.wMonth
= mstm
->tm_mon
+1;
232 if(!SystemTimeToFileTime(&st
, &ft
)) {
233 *MSVCRT__errno() = MSVCRT_EINVAL
;
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
);
249 use_dst
= is_dst(&st
);
250 if((mstm
->tm_isdst
<=-1 && use_dst
) || (mstm
->tm_isdst
>=1)) {
253 ret
+= (MSVCRT___time64_t
)MSVCRT__dstbias
*TICKSPERSEC
;
255 ft
.dwLowDateTime
= ret
& 0xffffffff;
256 ft
.dwHighDateTime
= ret
>> 32;
257 FileTimeToSystemTime(&ft
, &tmp
);
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
;
291 ret
= (ret
-TICKS_1601_TO_1970
)/TICKSPERSEC
;
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 /**********************************************************************
316 MSVCRT___time64_t CDECL
MSVCRT_mktime(struct MSVCRT_tm
*mstm
)
318 return MSVCRT__mktime64( mstm
);
321 MSVCRT___time32_t CDECL
MSVCRT_mktime(struct MSVCRT_tm
*mstm
)
323 return MSVCRT__mktime32( mstm
);
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.@)
350 MSVCRT___time64_t CDECL
MSVCRT__mkgmtime(struct MSVCRT_tm
*time
)
352 return MSVCRT__mkgmtime64(time
);
355 MSVCRT___time32_t CDECL
MSVCRT__mkgmtime(struct MSVCRT_tm
*time
)
357 return MSVCRT__mkgmtime32(time
);
361 /*********************************************************************
362 * _localtime64_s (MSVCRT.@)
364 int CDECL
_localtime64_s(struct MSVCRT_tm
*res
, const MSVCRT___time64_t
*secs
)
371 if (!res
|| !secs
|| *secs
< 0 || *secs
> _MAX__TIME64_T
)
374 write_invalid_msvcrt_tm(res
);
376 *MSVCRT__errno() = MSVCRT_EINVAL
;
377 return MSVCRT_EINVAL
;
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;
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;
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
))
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
;
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)
448 write_invalid_msvcrt_tm(time
);
450 *MSVCRT__errno() = MSVCRT_EINVAL
;
451 return MSVCRT_EINVAL
;
455 return _localtime64_s(time
, &secs64
);
458 /*********************************************************************
459 * localtime (MSVCRT.@)
462 struct MSVCRT_tm
* CDECL
MSVCRT_localtime(const MSVCRT___time64_t
* secs
)
464 return MSVCRT__localtime64( secs
);
467 struct MSVCRT_tm
* CDECL
MSVCRT_localtime(const MSVCRT___time32_t
* secs
)
469 return MSVCRT__localtime32( secs
);
473 /*********************************************************************
474 * _gmtime64 (MSVCRT.@)
476 int CDECL
MSVCRT__gmtime64_s(struct MSVCRT_tm
*res
, const MSVCRT___time64_t
*secs
)
483 if (!res
|| !secs
|| *secs
< 0 || *secs
> _MAX__TIME64_T
) {
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;
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
))
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
;
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
;
556 return MSVCRT__gmtime64( &secs64
);
559 /*********************************************************************
563 struct MSVCRT_tm
* CDECL
MSVCRT_gmtime(const MSVCRT___time64_t
* secs
)
565 return MSVCRT__gmtime64( secs
);
568 struct MSVCRT_tm
* CDECL
MSVCRT_gmtime(const MSVCRT___time32_t
* secs
)
570 return MSVCRT__gmtime32( secs
);
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);
586 /**********************************************************************
587 * _strdate_s (MSVCRT.@)
589 int CDECL
_strdate_s(char* date
, MSVCRT_size_t size
)
595 *MSVCRT__errno() = MSVCRT_EINVAL
;
596 return MSVCRT_EINVAL
;
600 *MSVCRT__errno() = MSVCRT_ERANGE
;
601 return MSVCRT_ERANGE
;
604 MSVCRT__strdate(date
);
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);
620 /**********************************************************************
621 * _wstrdate_s (MSVCRT.@)
623 int CDECL
_wstrdate_s(MSVCRT_wchar_t
* date
, MSVCRT_size_t size
)
629 *MSVCRT__errno() = MSVCRT_EINVAL
;
630 return MSVCRT_EINVAL
;
634 *MSVCRT__errno() = MSVCRT_ERANGE
;
635 return MSVCRT_ERANGE
;
638 MSVCRT__wstrdate(date
);
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);
654 /*********************************************************************
655 * _strtime_s (MSVCRT.@)
657 int CDECL
_strtime_s(char* time
, MSVCRT_size_t size
)
663 *MSVCRT__errno() = MSVCRT_EINVAL
;
664 return MSVCRT_EINVAL
;
668 *MSVCRT__errno() = MSVCRT_ERANGE
;
669 return MSVCRT_ERANGE
;
672 MSVCRT__strtime(time
);
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);
688 /*********************************************************************
689 * _wstrtime_s (MSVCRT.@)
691 int CDECL
_wstrtime_s(MSVCRT_wchar_t
* time
, MSVCRT_size_t size
)
697 *MSVCRT__errno() = MSVCRT_EINVAL
;
698 return MSVCRT_EINVAL
;
702 *MSVCRT__errno() = MSVCRT_ERANGE
;
703 return MSVCRT_ERANGE
;
706 MSVCRT__wstrtime(time
);
710 /*********************************************************************
713 MSVCRT_clock_t CDECL
MSVCRT_clock(void)
715 static LONGLONG start_time
;
716 LARGE_INTEGER systime
;
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
))
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.@)
754 double CDECL
MSVCRT_difftime(MSVCRT___time64_t time1
, MSVCRT___time64_t time2
)
756 return MSVCRT__difftime64( time1
, time2
);
759 double CDECL
MSVCRT_difftime(MSVCRT___time32_t time1
, MSVCRT___time32_t time2
)
761 return MSVCRT__difftime32( time1
, time2
);
765 /*********************************************************************
766 * _ftime64 (MSVCRT.@)
768 void CDECL
MSVCRT__ftime64(struct MSVCRT___timeb64
*buf
)
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
);
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
);
819 /*********************************************************************
823 void CDECL
MSVCRT__ftime(struct MSVCRT___timeb64
*buf
)
825 MSVCRT__ftime64( buf
);
828 void CDECL
MSVCRT__ftime(struct MSVCRT___timeb32
*buf
)
830 MSVCRT__ftime32( buf
);
834 /*********************************************************************
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
);
845 return buf
? *buf
= curtime
: curtime
;
848 /*********************************************************************
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
);
859 return buf
? *buf
= curtime
: curtime
;
862 /*********************************************************************
866 MSVCRT___time64_t CDECL
MSVCRT_time(MSVCRT___time64_t
* buf
)
868 return MSVCRT__time64( buf
);
871 MSVCRT___time32_t CDECL
MSVCRT_time(MSVCRT___time32_t
* buf
)
873 return MSVCRT__time32( buf
);
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
;
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
;
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
)
923 timezone
= tzname_std
;
926 timezone
= tzname_dst
;
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;
945 return MSVCRT_ERANGE
;
948 strcpy(buf
, timezone
);
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
)
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;
978 lcid
= time_data
->lcid
;
980 lcid
= LocaleNameToLCID(time_data
->locname
, 0);
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
);
989 *MSVCRT__errno() = MSVCRT_EINVAL
;
991 }else if(ret
> max
-*pos
) {
993 *MSVCRT__errno() = MSVCRT_ERANGE
;
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
)
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
;
1019 lcid
= LocaleNameToLCID(time_data
->locname
, 0);
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
);
1028 *MSVCRT__errno() = MSVCRT_EINVAL
;
1030 }else if(ret
> max
-*pos
) {
1032 *MSVCRT__errno() = MSVCRT_ERANGE
;
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
) {
1044 *MSVCRT__errno() = MSVCRT_ERANGE
;
1048 memcpy(str
+*pos
, src
, len
);
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
)
1058 if(src
<l
|| src
>h
) {
1060 *MSVCRT__errno() = MSVCRT_EINVAL
;
1064 len
= MSVCRT__snprintf(str
+*pos
, max
-*pos
, "%0*d", prec
, src
);
1067 *MSVCRT__errno() = MSVCRT_ERANGE
;
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
;
1081 TRACE("(%p %ld %s %p %p)\n", str
, max
, format
, mstm
, time_data
);
1083 if(!str
|| !format
) {
1086 *MSVCRT__errno() = MSVCRT_EINVAL
;
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
;
1105 if(*format
== '#') {
1117 if(!strftime_date(str
, &ret
, max
, alternate
, mstm
, time_data
))
1121 if(!strftime_time(str
, &ret
, max
, mstm
, time_data
))
1125 if(!strftime_date(str
, &ret
, max
, alternate
, mstm
, time_data
))
1129 if(!strftime_time(str
, &ret
, max
, mstm
, time_data
))
1133 if(mstm
->tm_wday
<0 || mstm
->tm_wday
>6)
1135 if(!strftime_str(str
, &ret
, max
, time_data
->str
.names
.short_wday
[mstm
->tm_wday
]))
1139 if(mstm
->tm_wday
<0 || mstm
->tm_wday
>6)
1141 if(!strftime_str(str
, &ret
, max
, time_data
->str
.names
.wday
[mstm
->tm_wday
]))
1145 if(mstm
->tm_mon
<0 || mstm
->tm_mon
>11)
1147 if(!strftime_str(str
, &ret
, max
, time_data
->str
.names
.short_mon
[mstm
->tm_mon
]))
1151 if(mstm
->tm_mon
<0 || mstm
->tm_mon
>11)
1153 if(!strftime_str(str
, &ret
, max
, time_data
->str
.names
.mon
[mstm
->tm_mon
]))
1157 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mday
, alternate
? 0 : 2, 0, 31))
1161 if(!strftime_int(str
, &ret
, max
, mstm
->tm_hour
, alternate
? 0 : 2, 0, 23))
1165 tmp
= mstm
->tm_hour
;
1170 if(!strftime_int(str
, &ret
, max
, tmp
, alternate
? 0 : 2, 1, 12))
1174 if(!strftime_int(str
, &ret
, max
, mstm
->tm_yday
+1, alternate
? 0 : 3, 1, 366))
1178 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mon
+1, alternate
? 0 : 2, 1, 12))
1182 if(!strftime_int(str
, &ret
, max
, mstm
->tm_min
, alternate
? 0 : 2, 0, 59))
1186 if(mstm
->tm_hour
<0 || mstm
->tm_hour
>23)
1188 if(!strftime_str(str
, &ret
, max
, mstm
->tm_hour
<12 ?
1189 time_data
->str
.names
.am
: time_data
->str
.names
.pm
))
1193 if(!strftime_int(str
, &ret
, max
, mstm
->tm_sec
, alternate
? 0 : 2, 0, 59))
1197 if(!strftime_int(str
, &ret
, max
, mstm
->tm_wday
, 0, 0, 6))
1201 if(!strftime_int(str
, &ret
, max
, mstm
->tm_year
%100, alternate
? 0 : 2, 0, 99))
1205 tmp
= 1900+mstm
->tm_year
;
1206 if(!strftime_int(str
, &ret
, max
, tmp
, alternate
? 0 : 4, 0, 9999))
1212 if(MSVCRT__get_tzname(&tmp
, str
+ret
, max
-ret
, mstm
->tm_isdst
? 1 : 0))
1218 if(mstm
->tm_wday
<0 || mstm
->tm_wday
>6 || mstm
->tm_yday
<0 || mstm
->tm_yday
>365)
1221 tmp
= mstm
->tm_wday
;
1222 else if(!mstm
->tm_wday
)
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))
1235 WARN("unknown format %c\n", *format
);
1243 *MSVCRT__errno() = MSVCRT_ERANGE
;
1252 *MSVCRT__errno() = MSVCRT_EINVAL
;
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
);
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
)
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
);
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
);
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
;
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);
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);
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
;
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
);
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();
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
;
1427 if(!asctime_buf(buffer
, mstm
))
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
)
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
);
1450 MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, time
, size
);
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
;
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
) );
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
;
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
) );
1512 /*********************************************************************
1516 char * CDECL
MSVCRT_ctime(const MSVCRT___time64_t
*time
)
1518 return MSVCRT__ctime64( time
);
1521 char * CDECL
MSVCRT_ctime(const MSVCRT___time32_t
*time
)
1523 return MSVCRT__ctime32( time
);
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.@)
1547 MSVCRT_wchar_t
* CDECL
MSVCRT__wctime(const MSVCRT___time64_t
*time
)
1549 return MSVCRT__wctime64( time
);
1552 MSVCRT_wchar_t
* CDECL
MSVCRT__wctime(const MSVCRT___time32_t
*time
)
1554 return MSVCRT__wctime32( time
);
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
;
1567 if(!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1568 if(!MSVCRT_CHECK_PMT(size
!= 0)) return MSVCRT_EINVAL
;
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
);
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
;
1590 if(!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1591 if(!MSVCRT_CHECK_PMT(size
!= 0)) return MSVCRT_EINVAL
;
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
);
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
;
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
;
1627 #endif /* _MSVCR_VER >= 80 */
1629 #if _MSVCR_VER >= 140
1635 MSVCRT___time32_t tv_sec
;
1641 MSVCRT___time64_t tv_sec
;
1645 /*********************************************************************
1646 * _timespec64_get (UCRTBASE.@)
1648 int CDECL
_timespec64_get(struct _timespec64
*ts
, int base
)
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;
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
)
1673 if(ts64
.tv_sec
!= (MSVCRT___time32_t
)ts64
.tv_sec
)
1676 ts
->tv_sec
= ts64
.tv_sec
;
1677 ts
->tv_nsec
= ts64
.tv_nsec
;
1680 #endif /* _MSVCR_VER >= 140 */