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 @@
@ cdecl gets(str) MSVCRT_gets
@ cdecl getwc(ptr) MSVCRT_getwc
@ cdecl getwchar() MSVCRT_getwchar
@ cdecl gmtime(ptr)
@ cdecl gmtime(ptr) MSVCRT_gmtime
@ cdecl is_wctype(long long) ntdll.iswctype
@ cdecl isalnum(long) MSVCRT_isalnum
@ cdecl isalpha(long) MSVCRT_isalpha
......@@ -656,7 +656,7 @@
@ cdecl ldexp( double long) MSVCRT_ldexp
@ cdecl ldiv(long long) MSVCRT_ldiv
@ cdecl localeconv() MSVCRT_localeconv
@ cdecl localtime(ptr)
@ cdecl localtime(ptr) MSVCRT_localtime
@ cdecl log(double)
@ cdecl log10(double)
@ cdecl -i386 longjmp(ptr long) MSVCRT_longjmp
......
......@@ -5,6 +5,7 @@
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
* Copyright 2004 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -38,47 +39,133 @@
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
/* INTERNAL: Return formatted current time/date */
char* msvcrt_get_current_time(char* out, const char* format)
static const int MonthLengths[2][12] =
{
static const MSVCRT_time_t bad_time = (MSVCRT_time_t)-1;
time_t t;
struct tm *_tm = NULL;
char *retval = NULL;
if (time(&t) != bad_time && (_tm = localtime(&t)) &&
strftime(out,9,format,_tm) == 8)
retval = out;
return retval;
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
static inline int IsLeapYear(int Year)
{
return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
}
#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.@)
*/
MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
{
MSVCRT_time_t res;
struct tm tm;
tm.tm_sec = t->tm_sec;
tm.tm_min = t->tm_min;
tm.tm_hour = t->tm_hour;
tm.tm_mday = t->tm_mday;
tm.tm_mon = t->tm_mon;
tm.tm_year = t->tm_year;
tm.tm_isdst = t->tm_isdst;
res = mktime(&tm);
if (res != -1)
{
t->tm_sec = tm.tm_sec;
t->tm_min = tm.tm_min;
t->tm_hour = tm.tm_hour;
t->tm_mday = tm.tm_mday;
t->tm_mon = tm.tm_mon;
t->tm_year = tm.tm_year;
t->tm_isdst = tm.tm_isdst;
MSVCRT_time_t secs;
SYSTEMTIME st;
FILETIME lft, uft;
ULONGLONG time;
st.wSecond = t->tm_sec;
st.wMinute = t->tm_min;
st.wHour = t->tm_hour;
st.wDay = t->tm_mday - 1;
st.wMonth = t->tm_mon;
st.wYear = t->tm_year + 1900;
SystemTimeToFileTime(&st, &lft);
LocalFileTimeToFileTime(&lft, &uft);
time = ((ULONGLONG)uft.dwHighDateTime << 32) | uft.dwLowDateTime;
secs = time / TICKSPERSEC - SECS_1601_TO_1970;
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 &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];
}
return res;
tm.tm_yday += st.wDay;
tm.tm_isdst = 0;
return &tm;
}
/**********************************************************************
......@@ -86,7 +173,11 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
*/
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)
*/
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)
*/
MSVCRT_clock_t MSVCRT_clock(void)
{
struct tms alltimes;
clock_t res;
times(&alltimes);
res = alltimes.tms_utime + alltimes.tms_stime +
alltimes.tms_cutime + alltimes.tms_cstime;
/* FIXME: We need some symbolic representation for CLOCKS_PER_SEC,
* 10 holds only for Windows/Linux_i86)
*/
return 10*res;
FILETIME ftc, fte, ftk, ftu;
ULONGLONG utime, ktime;
MSVCRT_clock_t clock;
GetProcessTimes(GetCurrentProcess(), &ftc, &fte, &ftk, &ftu);
ktime = ((ULONGLONG)ftk.dwHighDateTime << 32) | ftk.dwLowDateTime;
utime = ((ULONGLONG)ftu.dwHighDateTime << 32) | ftu.dwLowDateTime;
clock = ((utime + ktime) / TICKSPERSEC) * CLOCKS_PER_SEC;
return clock;
}
/*********************************************************************
......@@ -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 curtime = time(NULL);
MSVCRT_time_t curtime;
struct _timeb tb;
_ftime(&tb);
curtime = tb.time;
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.@)
*/
......
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