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 LONGLONG init_time
;
43 void msvcrt_init_clock(void)
45 LARGE_INTEGER systime
;
47 NtQuerySystemTime(&systime
);
48 init_time
= systime
.QuadPart
;
51 static const int MonthLengths
[2][12] =
53 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
54 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
58 static const int MAX_SECONDS
= 60;
60 static const int MAX_SECONDS
= 59;
63 static inline BOOL
IsLeapYear(int Year
)
65 return Year
% 4 == 0 && (Year
% 100 != 0 || Year
% 400 == 0);
68 static inline void write_invalid_msvcrt_tm( struct MSVCRT_tm
*tm
)
81 /*********************************************************************
82 * _daylight (MSVCRT.@)
84 int MSVCRT___daylight
= 1;
86 /*********************************************************************
87 * _timezone (MSVCRT.@)
89 MSVCRT_long MSVCRT___timezone
= 28800;
91 /*********************************************************************
94 int MSVCRT__dstbias
= -3600;
96 /*********************************************************************
99 * Some apps (notably Mozilla) insist on writing to these, so the buffer
100 * must be large enough.
102 static char tzname_std
[64] = "PST";
103 static char tzname_dst
[64] = "PDT";
104 char *MSVCRT__tzname
[2] = { tzname_std
, tzname_dst
};
106 static TIME_ZONE_INFORMATION tzi
= {0};
107 /*********************************************************************
110 void CDECL
MSVCRT__tzset(void)
112 char *tz
= MSVCRT_getenv("TZ");
117 BOOL neg_zone
= FALSE
;
119 memset(&tzi
, 0, sizeof(tzi
));
121 /* Parse timezone information: tzn[+|-]hh[:mm[:ss]][dzn] */
122 lstrcpynA(MSVCRT__tzname
[0], tz
, 3);
128 }else if(*tz
== '+') {
131 MSVCRT___timezone
= strtol(tz
, &tz
, 10)*3600;
133 MSVCRT___timezone
+= strtol(tz
+1, &tz
, 10)*60;
135 MSVCRT___timezone
+= strtol(tz
+1, &tz
, 10);
138 MSVCRT___timezone
= -MSVCRT___timezone
;
140 MSVCRT___daylight
= *tz
;
141 lstrcpynA(MSVCRT__tzname
[1], tz
, 3);
142 }else if(GetTimeZoneInformation(&tzi
) != TIME_ZONE_ID_INVALID
) {
143 MSVCRT___timezone
= tzi
.Bias
*60;
144 if(tzi
.StandardDate
.wMonth
)
145 MSVCRT___timezone
+= tzi
.StandardBias
*60;
147 if(tzi
.DaylightDate
.wMonth
) {
148 MSVCRT___daylight
= 1;
149 MSVCRT__dstbias
= (tzi
.DaylightBias
-tzi
.StandardBias
)*60;
151 MSVCRT___daylight
= 0;
155 if(!WideCharToMultiByte(CP_ACP
, 0, tzi
.StandardName
, -1, MSVCRT__tzname
[0],
156 sizeof(tzname_std
), NULL
, &error
) || error
)
157 *MSVCRT__tzname
[0] = 0;
158 if(!WideCharToMultiByte(CP_ACP
, 0, tzi
.DaylightName
, -1, MSVCRT__tzname
[1],
159 sizeof(tzname_dst
), NULL
, &error
) || error
)
160 *MSVCRT__tzname
[0] = 0;
162 _munlock(_TIME_LOCK
);
165 static void _tzset_init(void)
167 static BOOL init
= FALSE
;
175 _munlock(_TIME_LOCK
);
179 static BOOL
is_dst(const SYSTEMTIME
*st
)
181 TIME_ZONE_INFORMATION tmp
;
184 if(!MSVCRT___daylight
)
187 if(tzi
.DaylightDate
.wMonth
) {
189 }else if(st
->wYear
>= 2007) {
190 memset(&tmp
, 0, sizeof(tmp
));
191 tmp
.StandardDate
.wMonth
= 11;
192 tmp
.StandardDate
.wDay
= 1;
193 tmp
.StandardDate
.wHour
= 2;
194 tmp
.DaylightDate
.wMonth
= 3;
195 tmp
.DaylightDate
.wDay
= 2;
196 tmp
.DaylightDate
.wHour
= 2;
198 memset(&tmp
, 0, sizeof(tmp
));
199 tmp
.StandardDate
.wMonth
= 10;
200 tmp
.StandardDate
.wDay
= 5;
201 tmp
.StandardDate
.wHour
= 2;
202 tmp
.DaylightDate
.wMonth
= 4;
203 tmp
.DaylightDate
.wDay
= 1;
204 tmp
.DaylightDate
.wHour
= 2;
208 tmp
.StandardBias
= 0;
209 tmp
.DaylightBias
= MSVCRT__dstbias
/60;
210 if(!SystemTimeToTzSpecificLocalTime(&tmp
, st
, &out
))
213 return memcmp(st
, &out
, sizeof(SYSTEMTIME
));
216 #define SECSPERDAY 86400
217 /* 1601 to 1970 is 369 years plus 89 leap days */
218 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
219 #define TICKSPERSEC 10000000
220 #define TICKSPERMSEC 10000
221 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
223 static MSVCRT___time64_t
mktime_helper(struct MSVCRT_tm
*mstm
, BOOL local
)
227 MSVCRT___time64_t ret
= 0;
229 BOOL use_dst
= FALSE
;
231 ret
= mstm
->tm_year
+ mstm
->tm_mon
/12;
233 if(mstm
->tm_mon
< 0) {
238 if(ret
<70 || ret
>1100) {
239 *MSVCRT__errno() = MSVCRT_EINVAL
;
243 memset(&st
, 0, sizeof(SYSTEMTIME
));
245 st
.wMonth
= mstm
->tm_mon
+1;
248 if(!SystemTimeToFileTime(&st
, &ft
)) {
249 *MSVCRT__errno() = MSVCRT_EINVAL
;
253 ret
= ((MSVCRT___time64_t
)ft
.dwHighDateTime
<<32)+ft
.dwLowDateTime
;
254 ret
+= (MSVCRT___time64_t
)mstm
->tm_sec
*TICKSPERSEC
;
255 ret
+= (MSVCRT___time64_t
)mstm
->tm_min
*60*TICKSPERSEC
;
256 ret
+= (MSVCRT___time64_t
)mstm
->tm_hour
*60*60*TICKSPERSEC
;
257 ret
+= (MSVCRT___time64_t
)(mstm
->tm_mday
-1)*SECSPERDAY
*TICKSPERSEC
;
259 ft
.dwLowDateTime
= ret
& 0xffffffff;
260 ft
.dwHighDateTime
= ret
>> 32;
261 FileTimeToSystemTime(&ft
, &st
);
265 use_dst
= is_dst(&st
);
266 if((mstm
->tm_isdst
<=-1 && use_dst
) || (mstm
->tm_isdst
>=1)) {
269 ret
+= (MSVCRT___time64_t
)MSVCRT__dstbias
*TICKSPERSEC
;
271 ft
.dwLowDateTime
= ret
& 0xffffffff;
272 ft
.dwHighDateTime
= ret
>> 32;
273 FileTimeToSystemTime(&ft
, &tmp
);
281 }else if(mstm
->tm_isdst
==0 && use_dst
) {
282 ret
-= (MSVCRT___time64_t
)MSVCRT__dstbias
*TICKSPERSEC
;
283 ft
.dwLowDateTime
= ret
& 0xffffffff;
284 ft
.dwHighDateTime
= ret
>> 32;
285 FileTimeToSystemTime(&ft
, &st
);
286 ret
+= (MSVCRT___time64_t
)MSVCRT__dstbias
*TICKSPERSEC
;
288 ret
+= (MSVCRT___time64_t
)MSVCRT___timezone
*TICKSPERSEC
;
291 mstm
->tm_sec
= st
.wSecond
;
292 mstm
->tm_min
= st
.wMinute
;
293 mstm
->tm_hour
= st
.wHour
;
294 mstm
->tm_mday
= st
.wDay
;
295 mstm
->tm_mon
= st
.wMonth
-1;
296 mstm
->tm_year
= st
.wYear
-1900;
297 mstm
->tm_wday
= st
.wDayOfWeek
;
298 for(i
=mstm
->tm_yday
=0; i
<st
.wMonth
-1; i
++)
299 mstm
->tm_yday
+= MonthLengths
[IsLeapYear(st
.wYear
)][i
];
300 mstm
->tm_yday
+= st
.wDay
-1;
301 mstm
->tm_isdst
= use_dst
? 1 : 0;
303 if(ret
< TICKS_1601_TO_1970
) {
304 *MSVCRT__errno() = MSVCRT_EINVAL
;
307 ret
= (ret
-TICKS_1601_TO_1970
)/TICKSPERSEC
;
311 /**********************************************************************
312 * _mktime64 (MSVCRT.@)
314 MSVCRT___time64_t CDECL
MSVCRT__mktime64(struct MSVCRT_tm
*mstm
)
316 return mktime_helper(mstm
, TRUE
);
319 /**********************************************************************
320 * _mktime32 (MSVCRT.@)
322 MSVCRT___time32_t CDECL
MSVCRT__mktime32(struct MSVCRT_tm
*mstm
)
324 MSVCRT___time64_t ret
= MSVCRT__mktime64( mstm
);
325 return ret
== (MSVCRT___time32_t
)ret
? ret
: -1;
328 /**********************************************************************
332 MSVCRT___time64_t CDECL
MSVCRT_mktime(struct MSVCRT_tm
*mstm
)
334 return MSVCRT__mktime64( mstm
);
337 MSVCRT___time32_t CDECL
MSVCRT_mktime(struct MSVCRT_tm
*mstm
)
339 return MSVCRT__mktime32( mstm
);
343 /**********************************************************************
344 * _mkgmtime64 (MSVCRT.@)
346 * time->tm_isdst value is ignored
348 MSVCRT___time64_t CDECL
MSVCRT__mkgmtime64(struct MSVCRT_tm
*time
)
350 return mktime_helper(time
, FALSE
);
353 /**********************************************************************
354 * _mkgmtime32 (MSVCRT.@)
356 MSVCRT___time32_t CDECL
MSVCRT__mkgmtime32(struct MSVCRT_tm
*time
)
358 MSVCRT___time64_t ret
= MSVCRT__mkgmtime64(time
);
359 return ret
== (MSVCRT___time32_t
)ret
? ret
: -1;
362 /**********************************************************************
363 * _mkgmtime (MSVCRT.@)
366 MSVCRT___time64_t CDECL
MSVCRT__mkgmtime(struct MSVCRT_tm
*time
)
368 return MSVCRT__mkgmtime64(time
);
371 MSVCRT___time32_t CDECL
MSVCRT__mkgmtime(struct MSVCRT_tm
*time
)
373 return MSVCRT__mkgmtime32(time
);
377 /*********************************************************************
378 * _localtime64_s (MSVCRT.@)
380 int CDECL
_localtime64_s(struct MSVCRT_tm
*res
, const MSVCRT___time64_t
*secs
)
387 if (!res
|| !secs
|| *secs
< 0 || *secs
> _MAX__TIME64_T
)
390 write_invalid_msvcrt_tm(res
);
392 *MSVCRT__errno() = MSVCRT_EINVAL
;
393 return MSVCRT_EINVAL
;
397 time
= (*secs
- MSVCRT___timezone
) * (ULONGLONG
)TICKSPERSEC
+ TICKS_1601_TO_1970
;
399 ft
.dwHighDateTime
= (UINT
)(time
>> 32);
400 ft
.dwLowDateTime
= (UINT
)time
;
401 FileTimeToSystemTime(&ft
, &st
);
403 res
->tm_isdst
= is_dst(&st
) ? 1 : 0;
405 time
-= MSVCRT__dstbias
* (ULONGLONG
)TICKSPERSEC
;
406 ft
.dwHighDateTime
= (UINT
)(time
>> 32);
407 ft
.dwLowDateTime
= (UINT
)time
;
408 FileTimeToSystemTime(&ft
, &st
);
411 res
->tm_sec
= st
.wSecond
;
412 res
->tm_min
= st
.wMinute
;
413 res
->tm_hour
= st
.wHour
;
414 res
->tm_mday
= st
.wDay
;
415 res
->tm_year
= st
.wYear
- 1900;
416 res
->tm_mon
= st
.wMonth
- 1;
417 res
->tm_wday
= st
.wDayOfWeek
;
418 for (i
= res
->tm_yday
= 0; i
< st
.wMonth
- 1; i
++)
419 res
->tm_yday
+= MonthLengths
[IsLeapYear(st
.wYear
)][i
];
420 res
->tm_yday
+= st
.wDay
- 1;
425 /*********************************************************************
426 * _localtime64 (MSVCRT.@)
428 struct MSVCRT_tm
* CDECL
MSVCRT__localtime64(const MSVCRT___time64_t
* secs
)
430 thread_data_t
*data
= msvcrt_get_thread_data();
432 if(!data
->time_buffer
)
433 data
->time_buffer
= MSVCRT_malloc(sizeof(struct MSVCRT_tm
));
435 if(_localtime64_s(data
->time_buffer
, secs
))
437 return data
->time_buffer
;
440 /*********************************************************************
441 * _localtime32 (MSVCRT.@)
443 struct MSVCRT_tm
* CDECL
MSVCRT__localtime32(const MSVCRT___time32_t
* secs
)
445 MSVCRT___time64_t secs64
;
451 return MSVCRT__localtime64( &secs64
);
454 /*********************************************************************
455 * _localtime32_s (MSVCRT.@)
457 int CDECL
_localtime32_s(struct MSVCRT_tm
*time
, const MSVCRT___time32_t
*secs
)
459 MSVCRT___time64_t secs64
;
461 if (!time
|| !secs
|| *secs
< 0)
464 write_invalid_msvcrt_tm(time
);
466 *MSVCRT__errno() = MSVCRT_EINVAL
;
467 return MSVCRT_EINVAL
;
471 return _localtime64_s(time
, &secs64
);
474 /*********************************************************************
475 * localtime (MSVCRT.@)
478 struct MSVCRT_tm
* CDECL
MSVCRT_localtime(const MSVCRT___time64_t
* secs
)
480 return MSVCRT__localtime64( secs
);
483 struct MSVCRT_tm
* CDECL
MSVCRT_localtime(const MSVCRT___time32_t
* secs
)
485 return MSVCRT__localtime32( secs
);
489 /*********************************************************************
490 * _gmtime64 (MSVCRT.@)
492 int CDECL
MSVCRT__gmtime64_s(struct MSVCRT_tm
*res
, const MSVCRT___time64_t
*secs
)
499 if (!res
|| !secs
|| *secs
< 0 || *secs
> _MAX__TIME64_T
) {
501 write_invalid_msvcrt_tm(res
);
504 *MSVCRT__errno() = MSVCRT_EINVAL
;
505 return MSVCRT_EINVAL
;
508 time
= *secs
* (ULONGLONG
)TICKSPERSEC
+ TICKS_1601_TO_1970
;
510 ft
.dwHighDateTime
= (UINT
)(time
>> 32);
511 ft
.dwLowDateTime
= (UINT
)time
;
513 FileTimeToSystemTime(&ft
, &st
);
515 res
->tm_sec
= st
.wSecond
;
516 res
->tm_min
= st
.wMinute
;
517 res
->tm_hour
= st
.wHour
;
518 res
->tm_mday
= st
.wDay
;
519 res
->tm_year
= st
.wYear
- 1900;
520 res
->tm_mon
= st
.wMonth
- 1;
521 res
->tm_wday
= st
.wDayOfWeek
;
522 for (i
= res
->tm_yday
= 0; i
< st
.wMonth
- 1; i
++) {
523 res
->tm_yday
+= MonthLengths
[IsLeapYear(st
.wYear
)][i
];
526 res
->tm_yday
+= st
.wDay
- 1;
532 /*********************************************************************
533 * _gmtime64 (MSVCRT.@)
535 struct MSVCRT_tm
* CDECL
MSVCRT__gmtime64(const MSVCRT___time64_t
*secs
)
537 thread_data_t
* const data
= msvcrt_get_thread_data();
539 if(!data
->time_buffer
)
540 data
->time_buffer
= MSVCRT_malloc(sizeof(struct MSVCRT_tm
));
542 if(MSVCRT__gmtime64_s(data
->time_buffer
, secs
))
544 return data
->time_buffer
;
547 /*********************************************************************
548 * _gmtime32_s (MSVCRT.@)
550 int CDECL
MSVCRT__gmtime32_s(struct MSVCRT_tm
*res
, const MSVCRT___time32_t
*secs
)
552 MSVCRT___time64_t secs64
;
556 return MSVCRT__gmtime64_s(res
, &secs64
);
558 return MSVCRT__gmtime64_s(res
, NULL
);
561 /*********************************************************************
562 * _gmtime32 (MSVCRT.@)
564 struct MSVCRT_tm
* CDECL
MSVCRT__gmtime32(const MSVCRT___time32_t
* secs
)
566 MSVCRT___time64_t secs64
;
572 return MSVCRT__gmtime64( &secs64
);
575 /*********************************************************************
579 struct MSVCRT_tm
* CDECL
MSVCRT_gmtime(const MSVCRT___time64_t
* secs
)
581 return MSVCRT__gmtime64( secs
);
584 struct MSVCRT_tm
* CDECL
MSVCRT_gmtime(const MSVCRT___time32_t
* secs
)
586 return MSVCRT__gmtime32( secs
);
590 /**********************************************************************
591 * _strdate (MSVCRT.@)
593 char* CDECL
MSVCRT__strdate(char* date
)
595 static const char format
[] = "MM'/'dd'/'yy";
597 GetDateFormatA(LOCALE_NEUTRAL
, 0, NULL
, format
, date
, 9);
602 /**********************************************************************
603 * _strdate_s (MSVCRT.@)
605 int CDECL
_strdate_s(char* date
, MSVCRT_size_t size
)
611 *MSVCRT__errno() = MSVCRT_EINVAL
;
612 return MSVCRT_EINVAL
;
616 *MSVCRT__errno() = MSVCRT_ERANGE
;
617 return MSVCRT_ERANGE
;
620 MSVCRT__strdate(date
);
624 /**********************************************************************
625 * _wstrdate (MSVCRT.@)
627 MSVCRT_wchar_t
* CDECL
MSVCRT__wstrdate(MSVCRT_wchar_t
* date
)
629 static const WCHAR format
[] = { 'M','M','\'','/','\'','d','d','\'','/','\'','y','y',0 };
631 GetDateFormatW(LOCALE_NEUTRAL
, 0, NULL
, format
, date
, 9);
636 /**********************************************************************
637 * _wstrdate_s (MSVCRT.@)
639 int CDECL
_wstrdate_s(MSVCRT_wchar_t
* date
, MSVCRT_size_t size
)
645 *MSVCRT__errno() = MSVCRT_EINVAL
;
646 return MSVCRT_EINVAL
;
650 *MSVCRT__errno() = MSVCRT_ERANGE
;
651 return MSVCRT_ERANGE
;
654 MSVCRT__wstrdate(date
);
658 /*********************************************************************
659 * _strtime (MSVCRT.@)
661 char* CDECL
MSVCRT__strtime(char* time
)
663 static const char format
[] = "HH':'mm':'ss";
665 GetTimeFormatA(LOCALE_NEUTRAL
, 0, NULL
, format
, time
, 9);
670 /*********************************************************************
671 * _strtime_s (MSVCRT.@)
673 int CDECL
_strtime_s(char* time
, MSVCRT_size_t size
)
679 *MSVCRT__errno() = MSVCRT_EINVAL
;
680 return MSVCRT_EINVAL
;
684 *MSVCRT__errno() = MSVCRT_ERANGE
;
685 return MSVCRT_ERANGE
;
688 MSVCRT__strtime(time
);
692 /*********************************************************************
693 * _wstrtime (MSVCRT.@)
695 MSVCRT_wchar_t
* CDECL
MSVCRT__wstrtime(MSVCRT_wchar_t
* time
)
697 static const WCHAR format
[] = { 'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0 };
699 GetTimeFormatW(LOCALE_NEUTRAL
, 0, NULL
, format
, time
, 9);
704 /*********************************************************************
705 * _wstrtime_s (MSVCRT.@)
707 int CDECL
_wstrtime_s(MSVCRT_wchar_t
* time
, MSVCRT_size_t size
)
713 *MSVCRT__errno() = MSVCRT_EINVAL
;
714 return MSVCRT_EINVAL
;
718 *MSVCRT__errno() = MSVCRT_ERANGE
;
719 return MSVCRT_ERANGE
;
722 MSVCRT__wstrtime(time
);
726 /*********************************************************************
729 MSVCRT_clock_t CDECL
MSVCRT_clock(void)
731 LARGE_INTEGER systime
;
733 NtQuerySystemTime(&systime
);
734 return (systime
.QuadPart
- init_time
) / (TICKSPERSEC
/ MSVCRT_CLOCKS_PER_SEC
);
737 /*********************************************************************
738 * _difftime64 (MSVCRT.@)
740 double CDECL
MSVCRT__difftime64(MSVCRT___time64_t time1
, MSVCRT___time64_t time2
)
742 return (double)(time1
- time2
);
745 /*********************************************************************
746 * _difftime32 (MSVCRT.@)
748 double CDECL
MSVCRT__difftime32(MSVCRT___time32_t time1
, MSVCRT___time32_t time2
)
750 return (double)(time1
- time2
);
753 /*********************************************************************
754 * difftime (MSVCRT.@)
757 double CDECL
MSVCRT_difftime(MSVCRT___time64_t time1
, MSVCRT___time64_t time2
)
759 return MSVCRT__difftime64( time1
, time2
);
762 double CDECL
MSVCRT_difftime(MSVCRT___time32_t time1
, MSVCRT___time32_t time2
)
764 return MSVCRT__difftime32( time1
, time2
);
768 /*********************************************************************
769 * _ftime64 (MSVCRT.@)
771 void CDECL
MSVCRT__ftime64(struct MSVCRT___timeb64
*buf
)
778 GetSystemTimeAsFileTime(&ft
);
780 time
= ((ULONGLONG
)ft
.dwHighDateTime
<< 32) | ft
.dwLowDateTime
;
782 buf
->time
= time
/ TICKSPERSEC
- SECS_1601_TO_1970
;
783 buf
->millitm
= (time
% TICKSPERSEC
) / TICKSPERMSEC
;
784 buf
->timezone
= MSVCRT___timezone
/ 60;
785 buf
->dstflag
= GetDaylightFlag();
788 /*********************************************************************
789 * _ftime64_s (MSVCRT.@)
791 int CDECL
MSVCRT__ftime64_s(struct MSVCRT___timeb64
*buf
)
793 if (!MSVCRT_CHECK_PMT( buf
!= NULL
)) return MSVCRT_EINVAL
;
794 MSVCRT__ftime64(buf
);
798 /*********************************************************************
799 * _ftime32 (MSVCRT.@)
801 void CDECL
MSVCRT__ftime32(struct MSVCRT___timeb32
*buf
)
803 struct MSVCRT___timeb64 buf64
;
805 MSVCRT__ftime64( &buf64
);
806 buf
->time
= buf64
.time
;
807 buf
->millitm
= buf64
.millitm
;
808 buf
->timezone
= buf64
.timezone
;
809 buf
->dstflag
= buf64
.dstflag
;
812 /*********************************************************************
813 * _ftime32_s (MSVCRT.@)
815 int CDECL
MSVCRT__ftime32_s(struct MSVCRT___timeb32
*buf
)
817 if (!MSVCRT_CHECK_PMT( buf
!= NULL
)) return MSVCRT_EINVAL
;
818 MSVCRT__ftime32(buf
);
822 /*********************************************************************
826 void CDECL
MSVCRT__ftime(struct MSVCRT___timeb64
*buf
)
828 MSVCRT__ftime64( buf
);
831 void CDECL
MSVCRT__ftime(struct MSVCRT___timeb32
*buf
)
833 MSVCRT__ftime32( buf
);
837 /*********************************************************************
840 MSVCRT___time64_t CDECL
MSVCRT__time64(MSVCRT___time64_t
*buf
)
842 MSVCRT___time64_t curtime
;
843 struct MSVCRT___timeb64 tb
;
845 MSVCRT__ftime64(&tb
);
848 return buf
? *buf
= curtime
: curtime
;
851 /*********************************************************************
854 MSVCRT___time32_t CDECL
MSVCRT__time32(MSVCRT___time32_t
*buf
)
856 MSVCRT___time32_t curtime
;
857 struct MSVCRT___timeb64 tb
;
859 MSVCRT__ftime64(&tb
);
862 return buf
? *buf
= curtime
: curtime
;
865 /*********************************************************************
869 MSVCRT___time64_t CDECL
MSVCRT_time(MSVCRT___time64_t
* buf
)
871 return MSVCRT__time64( buf
);
874 MSVCRT___time32_t CDECL
MSVCRT_time(MSVCRT___time32_t
* buf
)
876 return MSVCRT__time32( buf
);
880 /*********************************************************************
881 * __p__daylight (MSVCRT.@)
883 int * CDECL
MSVCRT___p__daylight(void)
885 return &MSVCRT___daylight
;
888 /*********************************************************************
889 * __p__dstbias (MSVCRT.@)
891 int * CDECL
MSVCRT___p__dstbias(void)
893 return &MSVCRT__dstbias
;
897 /*********************************************************************
898 * _get_dstbias (MSVCR80.@)
900 int CDECL
MSVCRT__get_dstbias(int *seconds
)
902 if (!MSVCRT_CHECK_PMT(seconds
!= NULL
)) return MSVCRT_EINVAL
;
903 *seconds
= MSVCRT__dstbias
;
908 /*********************************************************************
909 * __p__timezone (MSVCRT.@)
911 MSVCRT_long
* CDECL
MSVCRT___p__timezone(void)
913 return &MSVCRT___timezone
;
916 /*********************************************************************
917 * _get_tzname (MSVCRT.@)
919 int CDECL
MSVCRT__get_tzname(MSVCRT_size_t
*ret
, char *buf
, MSVCRT_size_t bufsize
, int index
)
926 timezone
= tzname_std
;
929 timezone
= tzname_dst
;
932 *MSVCRT__errno() = MSVCRT_EINVAL
;
933 return MSVCRT_EINVAL
;
936 if(!ret
|| (!buf
&& bufsize
> 0) || (buf
&& !bufsize
))
938 *MSVCRT__errno() = MSVCRT_EINVAL
;
939 return MSVCRT_EINVAL
;
942 *ret
= strlen(timezone
)+1;
948 return MSVCRT_ERANGE
;
951 strcpy(buf
, timezone
);
955 /*********************************************************************
956 * __p_tzname (MSVCRT.@)
958 char ** CDECL
__p__tzname(void)
960 return MSVCRT__tzname
;
964 #define STRFTIME_CHAR char
965 #define STRFTIME_TD(td, name) td->str.names.name
967 #define STRFTIME_CHAR MSVCRT_wchar_t
968 #define STRFTIME_TD(td, name) td->wstr.names.name
971 #define strftime_str(a,b,c,d) strftime_nstr(a,b,c,d,MSVCRT_SIZE_MAX)
972 static inline BOOL
strftime_nstr(STRFTIME_CHAR
*str
, MSVCRT_size_t
*pos
,
973 MSVCRT_size_t max
, const STRFTIME_CHAR
*src
, MSVCRT_size_t len
)
979 *MSVCRT__errno() = MSVCRT_ERANGE
;
991 static inline BOOL
strftime_int(STRFTIME_CHAR
*str
, MSVCRT_size_t
*pos
, MSVCRT_size_t max
,
992 int src
, int prec
, int l
, int h
)
995 static const WCHAR fmt
[] = {'%','0','*','d',0};
999 if(!MSVCRT_CHECK_PMT(src
>=l
&& src
<=h
)) {
1004 #if _MSVCR_VER <= 90
1005 len
= MSVCRT__snprintf(str
+*pos
, max
-*pos
, "%0*d", prec
, src
);
1007 len
= MSVCRT__snwprintf(str
+*pos
, max
-*pos
, fmt
, prec
, src
);
1011 *MSVCRT__errno() = MSVCRT_ERANGE
;
1019 static inline BOOL
strftime_format(STRFTIME_CHAR
*str
, MSVCRT_size_t
*pos
, MSVCRT_size_t max
,
1020 const struct MSVCRT_tm
*mstm
, MSVCRT___lc_time_data
*time_data
, const STRFTIME_CHAR
*format
)
1022 MSVCRT_size_t count
;
1025 while(*format
&& ret
)
1028 while(format
[0] == format
[count
]) count
++;
1032 if(count
% 2 == 0) break;
1036 while(format
[count
] && format
[count
] != '\'') count
++;
1038 ret
= strftime_nstr(str
, pos
, max
, format
, count
);
1039 if(!ret
) return FALSE
;
1040 if(format
[count
] == '\'') count
++;
1045 if(!MSVCRT_CHECK_PMT(mstm
->tm_wday
>=0 && mstm
->tm_wday
<=6))
1054 ret
= strftime_int(str
, pos
, max
, mstm
->tm_mday
, count
==1 ? 0 : 2, 1, 31);
1057 ret
= strftime_str(str
, pos
, max
, STRFTIME_TD(time_data
, short_wday
)[mstm
->tm_wday
]);
1060 ret
= strftime_nstr(str
, pos
, max
, format
, count
-4);
1062 ret
= strftime_str(str
, pos
, max
, STRFTIME_TD(time_data
, wday
)[mstm
->tm_wday
]);
1069 if(!MSVCRT_CHECK_PMT(mstm
->tm_mon
>=0 && mstm
->tm_mon
<=11))
1078 ret
= strftime_int(str
, pos
, max
, mstm
->tm_mon
+1, count
==1 ? 0 : 2, 1, 12);
1081 ret
= strftime_str(str
, pos
, max
, STRFTIME_TD(time_data
, short_mon
)[mstm
->tm_mon
]);
1084 ret
= strftime_nstr(str
, pos
, max
, format
, count
-4);
1086 ret
= strftime_str(str
, pos
, max
, STRFTIME_TD(time_data
, mon
)[mstm
->tm_mon
]);
1094 if(!MSVCRT_CHECK_PMT(mstm
->tm_year
>= -1900 && mstm
->tm_year
<= 8099))
1096 if(!MSVCRT_CHECK_PMT(mstm
->tm_year
>= 0))
1106 ret
= strftime_nstr(str
, pos
, max
, format
, 1);
1110 ret
= strftime_nstr(str
, pos
, max
, format
, count
-2);
1112 ret
= strftime_int(str
, pos
, max
, (mstm
->tm_year
+1900)%100, 2, 0, 99);
1115 ret
= strftime_nstr(str
, pos
, max
, format
, count
-4);
1117 ret
= strftime_int(str
, pos
, max
, mstm
->tm_year
+1900, 4, 0, 9999);
1122 if(!MSVCRT_CHECK_PMT(mstm
->tm_hour
>=0 && mstm
->tm_hour
<=23))
1128 ret
= strftime_nstr(str
, pos
, max
, format
, count
-2);
1130 ret
= strftime_int(str
, pos
, max
, (mstm
->tm_hour
+ 11) % 12 + 1,
1131 count
== 1 ? 0 : 2, 1, 12);
1135 ret
= strftime_nstr(str
, pos
, max
, format
, count
-2);
1137 ret
= strftime_int(str
, pos
, max
, mstm
->tm_hour
, count
== 1 ? 0 : 2, 0, 23);
1141 ret
= strftime_nstr(str
, pos
, max
, format
, count
-2);
1143 ret
= strftime_int(str
, pos
, max
, mstm
->tm_min
, count
== 1 ? 0 : 2, 0, 59);
1147 ret
= strftime_nstr(str
, pos
, max
, format
, count
-2);
1149 ret
= strftime_int(str
, pos
, max
, mstm
->tm_sec
, count
== 1 ? 0 : 2, 0, MAX_SECONDS
);
1154 if(!MSVCRT_CHECK_PMT(mstm
->tm_hour
>=0 && mstm
->tm_hour
<=23))
1159 ret
= strftime_nstr(str
, pos
, max
,
1160 mstm
->tm_hour
< 12 ? STRFTIME_TD(time_data
, am
) : STRFTIME_TD(time_data
, pm
),
1161 (*format
== 't' && count
== 1) ? 1 : MSVCRT_SIZE_MAX
);
1164 ret
= strftime_nstr(str
, pos
, max
, format
, count
);
1174 static inline BOOL
strftime_tzdiff(STRFTIME_CHAR
*str
, MSVCRT_size_t
*pos
, MSVCRT_size_t max
, BOOL is_dst
)
1176 MSVCRT_long tz
= MSVCRT___timezone
+ (is_dst
? MSVCRT__dstbias
: 0);
1187 str
[(*pos
)++] = sign
;
1188 if(!strftime_int(str
, pos
, max
, tz
/60/60, 2, 0, 99))
1190 return strftime_int(str
, pos
, max
, tz
/60%60, 2, 0, 59);
1194 static MSVCRT_size_t
strftime_impl(STRFTIME_CHAR
*str
, MSVCRT_size_t max
,
1195 const STRFTIME_CHAR
*format
, const struct MSVCRT_tm
*mstm
,
1196 MSVCRT___lc_time_data
*time_data
, MSVCRT__locale_t loc
)
1198 MSVCRT_size_t ret
, tmp
;
1200 int year
= mstm
? mstm
->tm_year
+ 1900 : -1;
1202 if(!str
|| !format
) {
1205 *MSVCRT__errno() = MSVCRT_EINVAL
;
1210 time_data
= loc
? loc
->locinfo
->lc_time_curr
: get_locinfo()->lc_time_curr
;
1212 for(ret
=0; *format
&& ret
<max
; format
++) {
1213 if(*format
!= '%') {
1214 if(MSVCRT__isleadbyte_l((unsigned char)*format
, loc
)) {
1215 str
[ret
++] = *(format
++);
1216 if(ret
== max
) continue;
1217 if(!MSVCRT_CHECK_PMT(str
[ret
]))
1220 str
[ret
++] = *format
;
1225 if(*format
== '#') {
1232 if(!MSVCRT_CHECK_PMT(mstm
))
1238 if(time_data
== &cloc_time_data
&& !alternate
)
1240 static const WCHAR datetime_format
[] =
1241 { '%','a',' ','%','b',' ','%','e',' ','%','T',' ','%','Y',0 };
1242 tmp
= strftime_impl(str
+ret
, max
-ret
, datetime_format
, mstm
, time_data
, loc
);
1249 if(!strftime_format(str
, &ret
, max
, mstm
, time_data
,
1250 alternate
? STRFTIME_TD(time_data
, date
) : STRFTIME_TD(time_data
, short_date
)))
1254 if(!strftime_format(str
, &ret
, max
, mstm
, time_data
, STRFTIME_TD(time_data
, time
)))
1258 if(!strftime_format(str
, &ret
, max
, mstm
, time_data
,
1259 alternate
? STRFTIME_TD(time_data
, date
) : STRFTIME_TD(time_data
, short_date
)))
1263 if(!strftime_format(str
, &ret
, max
, mstm
, time_data
, STRFTIME_TD(time_data
, time
)))
1267 if(!MSVCRT_CHECK_PMT(mstm
->tm_wday
>=0 && mstm
->tm_wday
<=6))
1269 if(!strftime_str(str
, &ret
, max
, STRFTIME_TD(time_data
, short_wday
)[mstm
->tm_wday
]))
1273 if(!MSVCRT_CHECK_PMT(mstm
->tm_wday
>=0 && mstm
->tm_wday
<=6))
1275 if(!strftime_str(str
, &ret
, max
, STRFTIME_TD(time_data
, wday
)[mstm
->tm_wday
]))
1282 if(!MSVCRT_CHECK_PMT(mstm
->tm_mon
>=0 && mstm
->tm_mon
<=11))
1284 if(!strftime_str(str
, &ret
, max
, STRFTIME_TD(time_data
, short_mon
)[mstm
->tm_mon
]))
1288 if(!MSVCRT_CHECK_PMT(mstm
->tm_mon
>=0 && mstm
->tm_mon
<=11))
1290 if(!strftime_str(str
, &ret
, max
, STRFTIME_TD(time_data
, mon
)[mstm
->tm_mon
]))
1295 if(!MSVCRT_CHECK_PMT(year
>=0 && year
<=9999))
1297 if(!strftime_int(str
, &ret
, max
, year
/100, alternate
? 0 : 2, 0, 99))
1302 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mday
, alternate
? 0 : 2, 1, 31))
1307 if(!MSVCRT_CHECK_PMT(year
>=0 && year
<=9999))
1309 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mon
+1, alternate
? 0 : 2, 1, 12))
1313 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mday
, alternate
? 0 : 2, 1, 31))
1317 if(!strftime_int(str
, &ret
, max
, year
%100, alternate
? 0 : 2, 0, 99))
1321 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mday
, alternate
? 0 : 2, 1, 31))
1323 if(!alternate
&& str
[ret
-2] == '0')
1327 if(!strftime_int(str
, &ret
, max
, year
, alternate
? 0 : 4, 0, 9999))
1331 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mon
+1, alternate
? 0 : 2, 1, 12))
1335 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mday
, alternate
? 0 : 2, 1, 31))
1340 if(!MSVCRT_CHECK_PMT(year
>=0 && year
<=9999))
1345 int iso_year
= year
;
1346 int iso_days
= mstm
->tm_yday
- (mstm
->tm_wday
? mstm
->tm_wday
: 7) + 4;
1348 iso_days
+= 365 + IsLeapYear(--iso_year
);
1349 else if(iso_days
>= 365 + IsLeapYear(iso_year
))
1350 iso_days
-= 365 + IsLeapYear(iso_year
++);
1352 if(*format
== 'G') {
1353 if(!strftime_int(str
, &ret
, max
, iso_year
, 4, 0, 9999))
1355 } else if(*format
== 'g') {
1356 if(!strftime_int(str
, &ret
, max
, iso_year
%100, 2, 0, 99))
1359 if(!strftime_int(str
, &ret
, max
, iso_days
/7 + 1, alternate
? 0 : 2, 0, 53))
1366 if(!strftime_int(str
, &ret
, max
, mstm
->tm_hour
, alternate
? 0 : 2, 0, 23))
1370 if(!MSVCRT_CHECK_PMT(mstm
->tm_hour
>=0 && mstm
->tm_hour
<=23))
1372 if(!strftime_int(str
, &ret
, max
, (mstm
->tm_hour
+ 11) % 12 + 1,
1373 alternate
? 0 : 2, 1, 12))
1377 if(!strftime_int(str
, &ret
, max
, mstm
->tm_yday
+1, alternate
? 0 : 3, 1, 366))
1381 if(!strftime_int(str
, &ret
, max
, mstm
->tm_mon
+1, alternate
? 0 : 2, 1, 12))
1385 if(!strftime_int(str
, &ret
, max
, mstm
->tm_min
, alternate
? 0 : 2, 0, 59))
1394 if(!MSVCRT_CHECK_PMT(mstm
->tm_hour
>=0 && mstm
->tm_hour
<=23))
1396 if(!strftime_str(str
, &ret
, max
, mstm
->tm_hour
<12 ?
1397 STRFTIME_TD(time_data
, am
) : STRFTIME_TD(time_data
, pm
)))
1402 if(time_data
== &cloc_time_data
)
1404 if(!MSVCRT_CHECK_PMT(mstm
->tm_hour
>=0 && mstm
->tm_hour
<=23))
1406 if(!strftime_int(str
, &ret
, max
, (mstm
->tm_hour
+ 11) % 12 + 1,
1407 alternate
? 0 : 2, 1, 12))
1411 if(!strftime_int(str
, &ret
, max
, mstm
->tm_min
, alternate
? 0 : 2, 0, 59))
1415 if(!strftime_int(str
, &ret
, max
, mstm
->tm_sec
, alternate
? 0 : 2, 0, MAX_SECONDS
))
1419 if(!strftime_str(str
, &ret
, max
, mstm
->tm_hour
<12 ?
1420 STRFTIME_TD(time_data
, am
) : STRFTIME_TD(time_data
, pm
)))
1425 if(!strftime_format(str
, &ret
, max
, mstm
, time_data
, STRFTIME_TD(time_data
, time
)))
1430 if(!strftime_int(str
, &ret
, max
, mstm
->tm_hour
, alternate
? 0 : 2, 0, 23))
1434 if(!strftime_int(str
, &ret
, max
, mstm
->tm_min
, alternate
? 0 : 2, 0, 59))
1439 if(!strftime_int(str
, &ret
, max
, mstm
->tm_sec
, alternate
? 0 : 2, 0, MAX_SECONDS
))
1447 if(!strftime_int(str
, &ret
, max
, mstm
->tm_hour
, alternate
? 0 : 2, 0, 23))
1451 if(!strftime_int(str
, &ret
, max
, mstm
->tm_min
, alternate
? 0 : 2, 0, 59))
1455 if(!strftime_int(str
, &ret
, max
, mstm
->tm_sec
, alternate
? 0 : 2, 0, MAX_SECONDS
))
1459 if(!MSVCRT_CHECK_PMT(mstm
->tm_wday
>=0 && mstm
->tm_wday
<=6))
1461 tmp
= mstm
->tm_wday
? mstm
->tm_wday
: 7;
1462 if(!strftime_int(str
, &ret
, max
, tmp
, 0, 1, 7))
1467 if(!strftime_int(str
, &ret
, max
, mstm
->tm_wday
, 0, 0, 6))
1472 if(!MSVCRT_CHECK_PMT(year
>=0 && year
<=9999))
1474 if(!MSVCRT_CHECK_PMT(year
>=1900))
1477 if(!strftime_int(str
, &ret
, max
, year
%100, alternate
? 0 : 2, 0, 99))
1481 if(!strftime_int(str
, &ret
, max
, year
, alternate
? 0 : 4, 0, 9999))
1487 if(!strftime_tzdiff(str
, &ret
, max
, mstm
->tm_isdst
))
1493 #if _MSVCR_VER <= 90
1494 if(MSVCRT__get_tzname(&tmp
, str
+ret
, max
-ret
, mstm
->tm_isdst
? 1 : 0))
1497 if(MSVCRT__mbstowcs_s_l(&tmp
, str
+ret
, max
-ret
,
1498 mstm
->tm_isdst
? tzname_dst
: tzname_std
,
1499 MSVCRT__TRUNCATE
, loc
) == MSVCRT_STRUNCATE
)
1506 if(!MSVCRT_CHECK_PMT(mstm
->tm_wday
>=0 && mstm
->tm_wday
<=6))
1508 if(!MSVCRT_CHECK_PMT(mstm
->tm_yday
>=0 && mstm
->tm_yday
<=365))
1511 tmp
= mstm
->tm_wday
;
1512 else if(!mstm
->tm_wday
)
1515 tmp
= mstm
->tm_wday
-1;
1517 tmp
= mstm
->tm_yday
/7 + (tmp
<=mstm
->tm_yday
%7);
1518 if(!strftime_int(str
, &ret
, max
, tmp
, alternate
? 0 : 2, 0, 53))
1525 WARN("unknown format %c\n", *format
);
1526 MSVCRT_INVALID_PMT("unknown format", MSVCRT_EINVAL
);
1534 *MSVCRT__errno() = MSVCRT_ERANGE
;
1546 static MSVCRT_size_t
strftime_helper(char *str
, MSVCRT_size_t max
, const char *format
,
1547 const struct MSVCRT_tm
*mstm
, MSVCRT___lc_time_data
*time_data
, MSVCRT__locale_t loc
)
1549 #if _MSVCR_VER <= 90
1550 TRACE("(%p %ld %s %p %p %p)\n", str
, max
, format
, mstm
, time_data
, loc
);
1551 return strftime_impl(str
, max
, format
, mstm
, time_data
, loc
);
1553 MSVCRT_wchar_t
*s
, *fmt
;
1556 TRACE("(%p %ld %s %p %p %p)\n", str
, max
, format
, mstm
, time_data
, loc
);
1558 if (!MSVCRT_CHECK_PMT(str
!= NULL
)) return 0;
1559 if (!MSVCRT_CHECK_PMT(max
!= 0)) return 0;
1561 if (!MSVCRT_CHECK_PMT(format
!= NULL
)) return 0;
1563 len
= MSVCRT__mbstowcs_l( NULL
, format
, 0, loc
) + 1;
1564 if (!len
|| !(fmt
= MSVCRT_malloc( len
*sizeof(MSVCRT_wchar_t
) ))) return 0;
1565 MSVCRT__mbstowcs_l(fmt
, format
, len
, loc
);
1567 if ((s
= MSVCRT_malloc( max
*sizeof(MSVCRT_wchar_t
) )))
1569 len
= strftime_impl( s
, max
, fmt
, mstm
, time_data
, loc
);
1571 len
= MSVCRT__wcstombs_l( str
, s
, max
, loc
);
1581 #if _MSVCR_VER >= 80
1582 /********************************************************************
1583 * _strftime_l (MSVCR80.@)
1585 MSVCRT_size_t CDECL
MSVCRT__strftime_l( char *str
, MSVCRT_size_t max
, const char *format
,
1586 const struct MSVCRT_tm
*mstm
, MSVCRT__locale_t loc
)
1588 return strftime_helper(str
, max
, format
, mstm
, NULL
, loc
);
1592 /*********************************************************************
1593 * _Strftime (MSVCRT.@)
1595 MSVCRT_size_t CDECL
_Strftime(char *str
, MSVCRT_size_t max
, const char *format
,
1596 const struct MSVCRT_tm
*mstm
, MSVCRT___lc_time_data
*time_data
)
1598 return strftime_helper(str
, max
, format
, mstm
, time_data
, NULL
);
1601 /*********************************************************************
1602 * strftime (MSVCRT.@)
1604 MSVCRT_size_t CDECL
MSVCRT_strftime( char *str
, MSVCRT_size_t max
, const char *format
,
1605 const struct MSVCRT_tm
*mstm
)
1607 return strftime_helper(str
, max
, format
, mstm
, NULL
, NULL
);
1610 static MSVCRT_size_t
wcsftime_helper( MSVCRT_wchar_t
*str
, MSVCRT_size_t max
,
1611 const MSVCRT_wchar_t
*format
, const struct MSVCRT_tm
*mstm
,
1612 MSVCRT___lc_time_data
*time_data
, MSVCRT__locale_t loc
)
1614 #if _MSVCR_VER <= 90
1618 TRACE("%p %ld %s %p %p %p\n", str
, max
, debugstr_w(format
), mstm
, time_data
, loc
);
1620 len
= MSVCRT__wcstombs_l( NULL
, format
, 0, loc
) + 1;
1621 if (!(fmt
= MSVCRT_malloc( len
))) return 0;
1622 MSVCRT__wcstombs_l(fmt
, format
, len
, loc
);
1624 if ((s
= MSVCRT_malloc( max
*4 )))
1626 if (!strftime_impl( s
, max
*4, fmt
, mstm
, time_data
, loc
)) s
[0] = 0;
1627 len
= MSVCRT__mbstowcs_l( str
, s
, max
, loc
);
1635 TRACE("%p %ld %s %p %p %p\n", str
, max
, debugstr_w(format
), mstm
, time_data
, loc
);
1636 return strftime_impl(str
, max
, format
, mstm
, time_data
, loc
);
1640 /*********************************************************************
1641 * _wcsftime_l (MSVCRT.@)
1643 MSVCRT_size_t CDECL
MSVCRT__wcsftime_l( MSVCRT_wchar_t
*str
, MSVCRT_size_t max
,
1644 const MSVCRT_wchar_t
*format
, const struct MSVCRT_tm
*mstm
, MSVCRT__locale_t loc
)
1646 return wcsftime_helper(str
, max
, format
, mstm
, NULL
, loc
);
1649 /*********************************************************************
1650 * wcsftime (MSVCRT.@)
1652 MSVCRT_size_t CDECL
MSVCRT_wcsftime( MSVCRT_wchar_t
*str
, MSVCRT_size_t max
,
1653 const MSVCRT_wchar_t
*format
, const struct MSVCRT_tm
*mstm
)
1655 return wcsftime_helper(str
, max
, format
, mstm
, NULL
, NULL
);
1658 #if _MSVCR_VER >= 110
1659 /*********************************************************************
1660 * _Wcsftime (MSVCR110.@)
1662 MSVCRT_size_t CDECL
_Wcsftime(MSVCRT_wchar_t
*str
, MSVCRT_size_t max
,
1663 const MSVCRT_wchar_t
*format
, const struct MSVCRT_tm
*mstm
,
1664 MSVCRT___lc_time_data
*time_data
)
1666 return wcsftime_helper(str
, max
, format
, mstm
, time_data
, NULL
);
1670 static char* asctime_buf(char *buf
, const struct MSVCRT_tm
*mstm
)
1672 static const char wday
[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
1673 static const char month
[12][4] = {"Jan", "Feb", "Mar", "Apr", "May",
1674 "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
1676 if (!mstm
|| mstm
->tm_sec
<0 || mstm
->tm_sec
>59
1677 || mstm
->tm_min
<0 || mstm
->tm_min
>59
1678 || mstm
->tm_hour
<0 || mstm
->tm_hour
>23
1679 || mstm
->tm_mon
<0 || mstm
->tm_mon
>11
1680 || mstm
->tm_wday
<0 || mstm
->tm_wday
>6
1681 || mstm
->tm_year
<0 || mstm
->tm_mday
<0
1682 || mstm
->tm_mday
>MonthLengths
[IsLeapYear(1900+mstm
->tm_year
)][mstm
->tm_mon
]) {
1683 *MSVCRT__errno() = MSVCRT_EINVAL
;
1688 /* C89 (4.12.3.1) uses space-padding for day of month. */
1689 MSVCRT__snprintf(buf
, 26, "%s %s %2d %02d:%02d:%02d %c%03d\n", wday
[mstm
->tm_wday
],
1690 month
[mstm
->tm_mon
], mstm
->tm_mday
, mstm
->tm_hour
, mstm
->tm_min
,
1691 mstm
->tm_sec
, '1'+(mstm
->tm_year
+900)/1000, (900+mstm
->tm_year
)%1000);
1693 MSVCRT__snprintf(buf
, 26, "%s %s %02d %02d:%02d:%02d %c%03d\n", wday
[mstm
->tm_wday
],
1694 month
[mstm
->tm_mon
], mstm
->tm_mday
, mstm
->tm_hour
, mstm
->tm_min
,
1695 mstm
->tm_sec
, '1'+(mstm
->tm_year
+900)/1000, (900+mstm
->tm_year
)%1000);
1700 /*********************************************************************
1701 * asctime (MSVCRT.@)
1703 char * CDECL
MSVCRT_asctime(const struct MSVCRT_tm
*mstm
)
1705 thread_data_t
*data
= msvcrt_get_thread_data();
1707 /* asctime returns date in format that always has exactly 26 characters */
1708 if (!data
->asctime_buffer
) {
1709 data
->asctime_buffer
= MSVCRT_malloc(26);
1710 if (!data
->asctime_buffer
) {
1711 *MSVCRT__errno() = MSVCRT_ENOMEM
;
1716 return asctime_buf(data
->asctime_buffer
, mstm
);
1719 /*********************************************************************
1720 * asctime_s (MSVCRT.@)
1722 int CDECL
MSVCRT_asctime_s(char* time
, MSVCRT_size_t size
, const struct MSVCRT_tm
*mstm
)
1724 if (!MSVCRT_CHECK_PMT(time
!= NULL
)) return MSVCRT_EINVAL
;
1725 if (size
) time
[0] = 0;
1726 if (!MSVCRT_CHECK_PMT(size
>= 26)) return MSVCRT_EINVAL
;
1727 if (!MSVCRT_CHECK_PMT(mstm
!= NULL
)) return MSVCRT_EINVAL
;
1728 if (!MSVCRT_CHECK_PMT(mstm
->tm_sec
>= 0 && mstm
->tm_sec
< 60)) return MSVCRT_EINVAL
;
1729 if (!MSVCRT_CHECK_PMT(mstm
->tm_min
>= 0 && mstm
->tm_min
< 60)) return MSVCRT_EINVAL
;
1730 if (!MSVCRT_CHECK_PMT(mstm
->tm_hour
>= 0 && mstm
->tm_hour
< 24)) return MSVCRT_EINVAL
;
1731 if (!MSVCRT_CHECK_PMT(mstm
->tm_mon
>= 0 && mstm
->tm_mon
< 12)) return MSVCRT_EINVAL
;
1732 if (!MSVCRT_CHECK_PMT(mstm
->tm_wday
>= 0 && mstm
->tm_wday
< 7)) return MSVCRT_EINVAL
;
1733 if (!MSVCRT_CHECK_PMT(mstm
->tm_year
>= 0)) return MSVCRT_EINVAL
;
1734 if (!MSVCRT_CHECK_PMT(mstm
->tm_mday
>= 0)) return MSVCRT_EINVAL
;
1735 if (!MSVCRT_CHECK_PMT(mstm
->tm_mday
<= MonthLengths
[IsLeapYear(1900+mstm
->tm_year
)][mstm
->tm_mon
])) return MSVCRT_EINVAL
;
1737 asctime_buf(time
, mstm
);
1741 /*********************************************************************
1742 * _wasctime (MSVCRT.@)
1744 MSVCRT_wchar_t
* CDECL
MSVCRT__wasctime(const struct MSVCRT_tm
*mstm
)
1746 thread_data_t
*data
= msvcrt_get_thread_data();
1749 if(!data
->wasctime_buffer
) {
1750 data
->wasctime_buffer
= MSVCRT_malloc(26*sizeof(MSVCRT_wchar_t
));
1751 if(!data
->wasctime_buffer
) {
1752 *MSVCRT__errno() = MSVCRT_ENOMEM
;
1757 if(!asctime_buf(buffer
, mstm
))
1760 MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, data
->wasctime_buffer
, 26);
1761 return data
->wasctime_buffer
;
1764 /*********************************************************************
1765 * _wasctime_s (MSVCRT.@)
1767 int CDECL
MSVCRT__wasctime_s(MSVCRT_wchar_t
* time
, MSVCRT_size_t size
, const struct MSVCRT_tm
*mstm
)
1772 if (!MSVCRT_CHECK_PMT(time
!= NULL
)) return MSVCRT_EINVAL
;
1773 if (size
) time
[0] = 0;
1774 if (!MSVCRT_CHECK_PMT(size
>= 26)) return MSVCRT_EINVAL
;
1775 if (!MSVCRT_CHECK_PMT(mstm
!= NULL
)) return MSVCRT_EINVAL
;
1777 ret
= MSVCRT_asctime_s(buffer
, sizeof(buffer
), mstm
);
1780 MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, time
, size
);
1784 /*********************************************************************
1785 * _ctime64 (MSVCRT.@)
1787 char * CDECL
MSVCRT__ctime64(const MSVCRT___time64_t
*time
)
1789 struct MSVCRT_tm
*t
;
1790 t
= MSVCRT__localtime64( time
);
1791 if (!t
) return NULL
;
1792 return MSVCRT_asctime( t
);
1795 /*********************************************************************
1796 * _ctime64_s (MSVCRT.@)
1798 int CDECL
MSVCRT__ctime64_s(char *res
, MSVCRT_size_t len
, const MSVCRT___time64_t
*time
)
1800 struct MSVCRT_tm
*t
;
1802 if (!MSVCRT_CHECK_PMT( res
!= NULL
)) return MSVCRT_EINVAL
;
1803 if (!MSVCRT_CHECK_PMT( len
>= 26 )) return MSVCRT_EINVAL
;
1805 if (!MSVCRT_CHECK_PMT( time
!= NULL
)) return MSVCRT_EINVAL
;
1806 if (!MSVCRT_CHECK_PMT( *time
> 0 )) return MSVCRT_EINVAL
;
1808 t
= MSVCRT__localtime64( time
);
1809 strcpy( res
, MSVCRT_asctime( t
) );
1813 /*********************************************************************
1814 * _ctime32 (MSVCRT.@)
1816 char * CDECL
MSVCRT__ctime32(const MSVCRT___time32_t
*time
)
1818 struct MSVCRT_tm
*t
;
1819 t
= MSVCRT__localtime32( time
);
1820 if (!t
) return NULL
;
1821 return MSVCRT_asctime( t
);
1824 /*********************************************************************
1825 * _ctime32_s (MSVCRT.@)
1827 int CDECL
MSVCRT__ctime32_s(char *res
, MSVCRT_size_t len
, const MSVCRT___time32_t
*time
)
1829 struct MSVCRT_tm
*t
;
1831 if (!MSVCRT_CHECK_PMT( res
!= NULL
)) return MSVCRT_EINVAL
;
1832 if (!MSVCRT_CHECK_PMT( len
>= 26 )) return MSVCRT_EINVAL
;
1834 if (!MSVCRT_CHECK_PMT( time
!= NULL
)) return MSVCRT_EINVAL
;
1835 if (!MSVCRT_CHECK_PMT( *time
> 0 )) return MSVCRT_EINVAL
;
1837 t
= MSVCRT__localtime32( time
);
1838 strcpy( res
, MSVCRT_asctime( t
) );
1842 /*********************************************************************
1846 char * CDECL
MSVCRT_ctime(const MSVCRT___time64_t
*time
)
1848 return MSVCRT__ctime64( time
);
1851 char * CDECL
MSVCRT_ctime(const MSVCRT___time32_t
*time
)
1853 return MSVCRT__ctime32( time
);
1857 /*********************************************************************
1858 * _wctime64 (MSVCRT.@)
1860 MSVCRT_wchar_t
* CDECL
MSVCRT__wctime64(const MSVCRT___time64_t
*time
)
1862 return MSVCRT__wasctime( MSVCRT__localtime64(time
) );
1865 /*********************************************************************
1866 * _wctime32 (MSVCRT.@)
1868 MSVCRT_wchar_t
* CDECL
MSVCRT__wctime32(const MSVCRT___time32_t
*time
)
1870 return MSVCRT__wasctime( MSVCRT__localtime32(time
) );
1873 /*********************************************************************
1874 * _wctime (MSVCRT.@)
1877 MSVCRT_wchar_t
* CDECL
MSVCRT__wctime(const MSVCRT___time64_t
*time
)
1879 return MSVCRT__wctime64( time
);
1882 MSVCRT_wchar_t
* CDECL
MSVCRT__wctime(const MSVCRT___time32_t
*time
)
1884 return MSVCRT__wctime32( time
);
1888 /*********************************************************************
1889 * _wctime64_s (MSVCRT.@)
1891 int CDECL
MSVCRT__wctime64_s(MSVCRT_wchar_t
*buf
,
1892 MSVCRT_size_t size
, const MSVCRT___time64_t
*time
)
1894 struct MSVCRT_tm tm
;
1897 if(!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1898 if(!MSVCRT_CHECK_PMT(size
!= 0)) return MSVCRT_EINVAL
;
1900 if(!MSVCRT_CHECK_PMT(time
!= NULL
)) return MSVCRT_EINVAL
;
1901 if(!MSVCRT_CHECK_PMT(*time
>= 0)) return MSVCRT_EINVAL
;
1902 if(!MSVCRT_CHECK_PMT(*time
<= _MAX__TIME64_T
)) return MSVCRT_EINVAL
;
1904 ret
= _localtime64_s(&tm
, time
);
1908 return MSVCRT__wasctime_s(buf
, size
, &tm
);
1911 /*********************************************************************
1912 * _wctime32_s (MSVCRT.@)
1914 int CDECL
MSVCRT__wctime32_s(MSVCRT_wchar_t
*buf
, MSVCRT_size_t size
,
1915 const MSVCRT___time32_t
*time
)
1917 struct MSVCRT_tm tm
;
1920 if(!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1921 if(!MSVCRT_CHECK_PMT(size
!= 0)) return MSVCRT_EINVAL
;
1923 if(!MSVCRT_CHECK_PMT(time
!= NULL
)) return MSVCRT_EINVAL
;
1924 if(!MSVCRT_CHECK_PMT(*time
>= 0)) return MSVCRT_EINVAL
;
1926 ret
= _localtime32_s(&tm
, time
);
1930 return MSVCRT__wasctime_s(buf
, size
, &tm
);
1933 #if _MSVCR_VER >= 80
1935 /*********************************************************************
1936 * _get_timezone (MSVCR80.@)
1938 int CDECL
_get_timezone(LONG
*timezone
)
1940 if(!MSVCRT_CHECK_PMT(timezone
!= NULL
)) return MSVCRT_EINVAL
;
1942 *timezone
= MSVCRT___timezone
;
1946 /*********************************************************************
1947 * _get_daylight (MSVCR80.@)
1949 int CDECL
_get_daylight(int *hours
)
1951 if(!MSVCRT_CHECK_PMT(hours
!= NULL
)) return MSVCRT_EINVAL
;
1953 *hours
= MSVCRT___daylight
;
1957 #endif /* _MSVCR_VER >= 80 */
1959 #if _MSVCR_VER >= 140
1965 MSVCRT___time32_t tv_sec
;
1971 MSVCRT___time64_t tv_sec
;
1975 /*********************************************************************
1976 * _timespec64_get (UCRTBASE.@)
1978 int CDECL
_timespec64_get(struct _timespec64
*ts
, int base
)
1983 if(!MSVCRT_CHECK_PMT(ts
!= NULL
)) return 0;
1984 if(base
!= TIME_UTC
) return 0;
1986 GetSystemTimePreciseAsFileTime(&ft
);
1987 time
= ((ULONGLONG
)ft
.dwHighDateTime
<< 32) | ft
.dwLowDateTime
;
1989 ts
->tv_sec
= time
/ TICKSPERSEC
- SECS_1601_TO_1970
;
1990 ts
->tv_nsec
= time
% TICKSPERSEC
* 100;
1994 /*********************************************************************
1995 * _timespec32_get (UCRTBASE.@)
1997 int CDECL
_timespec32_get(struct _timespec32
*ts
, int base
)
1999 struct _timespec64 ts64
;
2001 if(_timespec64_get(&ts64
, base
) != base
)
2003 if(ts64
.tv_sec
!= (MSVCRT___time32_t
)ts64
.tv_sec
)
2006 ts
->tv_sec
= ts64
.tv_sec
;
2007 ts
->tv_nsec
= ts64
.tv_nsec
;
2010 #endif /* _MSVCR_VER >= 140 */