Commit 3f09feda authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

Reimplement time functions with Win32 APIs.

Implement localtime()/gmtime().
parent 068b4ec7
...@@ -625,7 +625,7 @@ ...@@ -625,7 +625,7 @@
@ cdecl gets(str) MSVCRT_gets @ cdecl gets(str) MSVCRT_gets
@ cdecl getwc(ptr) MSVCRT_getwc @ cdecl getwc(ptr) MSVCRT_getwc
@ cdecl getwchar() MSVCRT_getwchar @ cdecl getwchar() MSVCRT_getwchar
@ cdecl gmtime(ptr) @ cdecl gmtime(ptr) MSVCRT_gmtime
@ cdecl is_wctype(long long) ntdll.iswctype @ cdecl is_wctype(long long) ntdll.iswctype
@ cdecl isalnum(long) MSVCRT_isalnum @ cdecl isalnum(long) MSVCRT_isalnum
@ cdecl isalpha(long) MSVCRT_isalpha @ cdecl isalpha(long) MSVCRT_isalpha
...@@ -656,7 +656,7 @@ ...@@ -656,7 +656,7 @@
@ cdecl ldexp( double long) MSVCRT_ldexp @ cdecl ldexp( double long) MSVCRT_ldexp
@ cdecl ldiv(long long) MSVCRT_ldiv @ cdecl ldiv(long long) MSVCRT_ldiv
@ cdecl localeconv() MSVCRT_localeconv @ cdecl localeconv() MSVCRT_localeconv
@ cdecl localtime(ptr) @ cdecl localtime(ptr) MSVCRT_localtime
@ cdecl log(double) @ cdecl log(double)
@ cdecl log10(double) @ cdecl log10(double)
@ cdecl -i386 longjmp(ptr long) MSVCRT_longjmp @ cdecl -i386 longjmp(ptr long) MSVCRT_longjmp
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Copyright 1996 Jukka Iivonen * Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes * Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths * Copyright 2000 Jon Griffiths
* Copyright 2004 Hans Leidekker
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -38,47 +39,133 @@ ...@@ -38,47 +39,133 @@
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
/* INTERNAL: Return formatted current time/date */ static const int MonthLengths[2][12] =
char* msvcrt_get_current_time(char* out, const char* format)
{ {
static const MSVCRT_time_t bad_time = (MSVCRT_time_t)-1; { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
time_t t; { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
struct tm *_tm = NULL; };
char *retval = NULL;
static inline int IsLeapYear(int Year)
if (time(&t) != bad_time && (_tm = localtime(&t)) && {
strftime(out,9,format,_tm) == 8) return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
retval = out;
return retval;
} }
#define SECSPERDAY 86400
/* 1601 to 1970 is 369 years plus 89 leap days */
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
/* native uses a single static buffer for localtime/gmtime/mktime */
static struct MSVCRT_tm tm;
/********************************************************************** /**********************************************************************
* mktime (MSVCRT.@) * mktime (MSVCRT.@)
*/ */
MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t) MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
{ {
MSVCRT_time_t res; MSVCRT_time_t secs;
struct tm tm;
SYSTEMTIME st;
tm.tm_sec = t->tm_sec; FILETIME lft, uft;
tm.tm_min = t->tm_min; ULONGLONG time;
tm.tm_hour = t->tm_hour;
tm.tm_mday = t->tm_mday; st.wSecond = t->tm_sec;
tm.tm_mon = t->tm_mon; st.wMinute = t->tm_min;
tm.tm_year = t->tm_year; st.wHour = t->tm_hour;
tm.tm_isdst = t->tm_isdst; st.wDay = t->tm_mday - 1;
res = mktime(&tm); st.wMonth = t->tm_mon;
if (res != -1) st.wYear = t->tm_year + 1900;
{
t->tm_sec = tm.tm_sec; SystemTimeToFileTime(&st, &lft);
t->tm_min = tm.tm_min; LocalFileTimeToFileTime(&lft, &uft);
t->tm_hour = tm.tm_hour;
t->tm_mday = tm.tm_mday; time = ((ULONGLONG)uft.dwHighDateTime << 32) | uft.dwLowDateTime;
t->tm_mon = tm.tm_mon; secs = time / TICKSPERSEC - SECS_1601_TO_1970;
t->tm_year = tm.tm_year;
t->tm_isdst = tm.tm_isdst; return secs;
}
/*********************************************************************
* localtime (MSVCRT.@)
*/
struct MSVCRT_tm* MSVCRT_localtime(const MSVCRT_time_t* secs)
{
int i;
FILETIME ft, lft;
SYSTEMTIME st;
DWORD tzid;
TIME_ZONE_INFORMATION tzinfo;
ULONGLONG time = *secs * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
ft.dwHighDateTime = (UINT)(time >> 32);
ft.dwLowDateTime = (UINT)time;
FileTimeToLocalFileTime(&ft, &lft);
FileTimeToSystemTime(&lft, &st);
if (st.wYear < 1970) return NULL;
tm.tm_sec = st.wSecond;
tm.tm_min = st.wMinute;
tm.tm_hour = st.wHour;
tm.tm_mday = st.wDay;
tm.tm_year = st.wYear - 1900;
tm.tm_mon = st.wMonth + 1;
tm.tm_wday = st.wDayOfWeek;
for (i = 0; i < st.wMonth; i++) {
tm.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
}
tm.tm_yday += st.wDay;
tzid = GetTimeZoneInformation(&tzinfo);
if (tzid == TIME_ZONE_ID_UNKNOWN) {
tm.tm_isdst = -1;
} else {
tm.tm_isdst = (tzid == TIME_ZONE_ID_DAYLIGHT?1:0);
} }
return res;
return &tm;
}
struct MSVCRT_tm* MSVCRT_gmtime(const MSVCRT_time_t* secs)
{
int i;
FILETIME ft, lft;
SYSTEMTIME st;
ULONGLONG time = *secs * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
ft.dwHighDateTime = (UINT)(time >> 32);
ft.dwLowDateTime = (UINT)time;
FileTimeToSystemTime(&lft, &st);
if (st.wYear < 1970) return NULL;
tm.tm_sec = st.wSecond;
tm.tm_min = st.wMinute;
tm.tm_hour = st.wHour;
tm.tm_mday = st.wDay;
tm.tm_year = st.wYear - 1900;
tm.tm_mon = st.wMonth + 1;
tm.tm_wday = st.wDayOfWeek;
for (i = 0; i < st.wMonth; i++) {
tm.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
}
tm.tm_yday += st.wDay;
tm.tm_isdst = 0;
return &tm;
} }
/********************************************************************** /**********************************************************************
...@@ -86,7 +173,11 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t) ...@@ -86,7 +173,11 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
*/ */
char* _strdate(char* date) char* _strdate(char* date)
{ {
return msvcrt_get_current_time(date,"%m/%d/%y"); LPCSTR format = "MM'/'dd'/'yy";
GetDateFormatA(LOCALE_NEUTRAL, 0, NULL, format, date, 9);
return date;
} }
/********************************************************************* /*********************************************************************
...@@ -94,7 +185,11 @@ char* _strdate(char* date) ...@@ -94,7 +185,11 @@ char* _strdate(char* date)
*/ */
char* _strtime(char* date) char* _strtime(char* date)
{ {
return msvcrt_get_current_time(date,"%H:%M:%S"); LPCSTR format = "HH':'mm':'ss";
GetTimeFormatA(LOCALE_NEUTRAL, 0, NULL, format, date, 9);
return date;
} }
/********************************************************************* /*********************************************************************
...@@ -102,16 +197,19 @@ char* _strtime(char* date) ...@@ -102,16 +197,19 @@ char* _strtime(char* date)
*/ */
MSVCRT_clock_t MSVCRT_clock(void) MSVCRT_clock_t MSVCRT_clock(void)
{ {
struct tms alltimes; FILETIME ftc, fte, ftk, ftu;
clock_t res; ULONGLONG utime, ktime;
times(&alltimes); MSVCRT_clock_t clock;
res = alltimes.tms_utime + alltimes.tms_stime +
alltimes.tms_cutime + alltimes.tms_cstime; GetProcessTimes(GetCurrentProcess(), &ftc, &fte, &ftk, &ftu);
/* FIXME: We need some symbolic representation for CLOCKS_PER_SEC,
* 10 holds only for Windows/Linux_i86) ktime = ((ULONGLONG)ftk.dwHighDateTime << 32) | ftk.dwLowDateTime;
*/ utime = ((ULONGLONG)ftu.dwHighDateTime << 32) | ftu.dwLowDateTime;
return 10*res;
clock = ((utime + ktime) / TICKSPERSEC) * CLOCKS_PER_SEC;
return clock;
} }
/********************************************************************* /*********************************************************************
...@@ -119,7 +217,7 @@ MSVCRT_clock_t MSVCRT_clock(void) ...@@ -119,7 +217,7 @@ MSVCRT_clock_t MSVCRT_clock(void)
*/ */
double MSVCRT_difftime(MSVCRT_time_t time1, MSVCRT_time_t time2) double MSVCRT_difftime(MSVCRT_time_t time1, MSVCRT_time_t time2)
{ {
return (double)(time1 - time2); return (double)(time1 - time2);
} }
/********************************************************************* /*********************************************************************
...@@ -127,16 +225,15 @@ double MSVCRT_difftime(MSVCRT_time_t time1, MSVCRT_time_t time2) ...@@ -127,16 +225,15 @@ double MSVCRT_difftime(MSVCRT_time_t time1, MSVCRT_time_t time2)
*/ */
MSVCRT_time_t MSVCRT_time(MSVCRT_time_t* buf) MSVCRT_time_t MSVCRT_time(MSVCRT_time_t* buf)
{ {
MSVCRT_time_t curtime = time(NULL); MSVCRT_time_t curtime;
struct _timeb tb;
_ftime(&tb);
curtime = tb.time;
return buf ? *buf = curtime : curtime; return buf ? *buf = curtime : curtime;
} }
#define SECSPERDAY 86400
/* 1601 to 1970 is 369 years plus 89 leap days */
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
/********************************************************************* /*********************************************************************
* _ftime (MSVCRT.@) * _ftime (MSVCRT.@)
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment