time.c six times: RtlTimeToTimeFields, RtlTimeFieldsToTime, SystemTimeToFileTime, mktime
Rein Klazes
rklazes at xs4all.nl
Fri Nov 5 09:46:06 CST 2004
Hi,
Changelog:
dlls/ntdll : time.c
dlls/ntdll/tests : time.c
dlls/kernel : time.c
dlls/kernel/tests : time.c
dlls/msvcrt : time.c
dlls/msvcrt/tests : time.c
- RtlTimeFieldsToTime should not normalize the time fields
structure. Instead return error when it is given an unormalized
date;
- Use better algorithms for RtlTimeToTimeFields and
RtlTimeFieldsToTime. RtlTimeToTimeFields is about 3 times
faster;
- add tests for RtlTimeFieldsToTime;
- SystemTimeToFileTime must fail if RtlTimeFieldsToTime fails.
Users of SystemTimeToFileTime must do likewise.
- remove a todo_wine from SystemTimeToFileTime tests.
- Since msvcrt.mktime must accept unnormalized dates,
it cannot use SystemTimeToFileTime and do the calculations
itself;
- add some tests for mktime accepting unnormalized dates.
Rein.
--
Rein Klazes
rklazes at xs4all.nl
-------------- next part --------------
--- wine/dlls/ntdll/time.c 2004-11-03 08:41:25.000000000 +0100
+++ mywine/dlls/ntdll/time.c 2004-11-05 16:17:52.000000000 +0100
@@ -338,23 +338,11 @@ static const int MonthLengths[2][MONSPER
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
-static const int YearDays[2][MONSPERYEAR+1] =
-{
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-};
-
static inline int IsLeapYear(int Year)
{
return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
}
-static inline void NormalizeTimeFields(CSHORT *FieldToNormalize, CSHORT *CarryField,int Modulus)
-{
- *FieldToNormalize = (CSHORT) (*FieldToNormalize - Modulus);
- *CarryField = (CSHORT) (*CarryField + 1);
-}
-
/***********************************************************************
* NTDLL_get_server_timeout
*
@@ -420,14 +408,15 @@ VOID WINAPI RtlTimeToTimeFields(
const LARGE_INTEGER *liTime,
PTIME_FIELDS TimeFields)
{
- int SecondsInDay, DeltaYear;
- int LeapYear, CurMonth;
+ int SecondsInDay;
+ long int cleaps, years, yearday, months;
long int Days;
- LONGLONG Time = liTime->QuadPart;
+ LONGLONG Time;
/* Extract millisecond from time and convert time into seconds */
- TimeFields->Milliseconds = (CSHORT) ((Time % TICKSPERSEC) / TICKSPERMSEC);
- Time = Time / TICKSPERSEC;
+ TimeFields->Milliseconds =
+ (CSHORT) (( liTime->QuadPart % TICKSPERSEC) / TICKSPERMSEC);
+ Time = liTime->QuadPart / TICKSPERSEC;
/* The native version of RtlTimeToTimeFields does not take leap seconds
* into account */
@@ -445,32 +434,27 @@ VOID WINAPI RtlTimeToTimeFields(
/* compute day of week */
TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK);
- /* compute year */
- /* FIXME: handle calendar modifications */
- TimeFields->Year = EPOCHYEAR;
- DeltaYear = Days / DAYSPERQUADRICENTENNIUM;
- TimeFields->Year += DeltaYear * 400;
- Days -= DeltaYear * DAYSPERQUADRICENTENNIUM;
- DeltaYear = Days / DAYSPERNORMALCENTURY;
- if( DeltaYear > 3) DeltaYear = 3; /* fix 31 Dec of 2000 and every
- 400 years after that */
- TimeFields->Year += DeltaYear * 100;
- Days -= DeltaYear * DAYSPERNORMALCENTURY;
- DeltaYear = Days / DAYSPERNORMALQUADRENNIUM;
- TimeFields->Year += DeltaYear * 4;
- Days -= DeltaYear * DAYSPERNORMALQUADRENNIUM;
- DeltaYear = Days / DAYSPERNORMALYEAR;
- if( DeltaYear > 3) DeltaYear = 3; /* fix 31 Dec of every leap year */
- TimeFields->Year += DeltaYear;
- Days -= DeltaYear * DAYSPERNORMALYEAR;
-
- LeapYear = IsLeapYear(TimeFields->Year);
-
- /* Compute month of year */
- CurMonth = 1;
- while (Days >= YearDays[LeapYear][CurMonth]) CurMonth++;
- TimeFields->Day = Days - YearDays[LeapYear][CurMonth-1] + 1;
- TimeFields->Month = CurMonth;
+ /* compute year, month and day of month. */
+ cleaps=( 3 * ((4 * Days + 1227) / DAYSPERQUADRICENTENNIUM) + 3 ) / 4;
+ Days += 28188 + cleaps;
+ years = (20 * Days - 2442) / (5 * DAYSPERNORMALQUADRENNIUM);
+ yearday = Days - (years * DAYSPERNORMALQUADRENNIUM)/4;
+ months = (64 * yearday) / 1959;
+ /* the result is based on a year starting on March.
+ * To convert take 12 from Januari and Februari and
+ * increase the year by one. */
+ if( months < 14 ) {
+ TimeFields->Month = months - 1;
+ TimeFields->Year = years + 1524;
+ } else {
+ TimeFields->Month = months - 13;
+ TimeFields->Year = years + 1525;
+ }
+ /* calculation of day of month is based on the wonderful
+ * sequence of INT( n * 30.6): it reproduces the
+ * 31-30-31-30-31-31 month lengths exactly for small n's */
+ TimeFields->Day = yearday - (1959 * months) / 64 ;
+ return;
}
/******************************************************************************
@@ -490,51 +474,49 @@ BOOLEAN WINAPI RtlTimeFieldsToTime(
PTIME_FIELDS tfTimeFields,
PLARGE_INTEGER Time)
{
- int CurYear, DeltaYear;
- LONGLONG rcTime;
- TIME_FIELDS TimeFields = *tfTimeFields;
-
- rcTime = 0;
+ int month, year, cleaps, day;
/* FIXME: normalize the TIME_FIELDS structure here */
- while (TimeFields.Second >= SECSPERMIN)
- { NormalizeTimeFields(&TimeFields.Second, &TimeFields.Minute, SECSPERMIN);
- }
- while (TimeFields.Minute >= MINSPERHOUR)
- { NormalizeTimeFields(&TimeFields.Minute, &TimeFields.Hour, MINSPERHOUR);
- }
- while (TimeFields.Hour >= HOURSPERDAY)
- { NormalizeTimeFields(&TimeFields.Hour, &TimeFields.Day, HOURSPERDAY);
- }
- while (TimeFields.Day > MonthLengths[IsLeapYear(TimeFields.Year)][TimeFields.Month - 1])
- { NormalizeTimeFields(&TimeFields.Day, &TimeFields.Month,
- MonthLengths[IsLeapYear(TimeFields.Year)][TimeFields.Month - 1]);
- }
- while (TimeFields.Month > MONSPERYEAR)
- { NormalizeTimeFields(&TimeFields.Month, &TimeFields.Year, MONSPERYEAR);
- }
+ /* No, native just returns 0 (error) if the fields are not */
+ if( tfTimeFields->Milliseconds< 0 || tfTimeFields->Milliseconds > 999 ||
+ tfTimeFields->Second < 0 || tfTimeFields->Second > 59 ||
+ tfTimeFields->Minute < 0 || tfTimeFields->Minute > 59 ||
+ tfTimeFields->Hour < 0 || tfTimeFields->Hour > 23 ||
+ tfTimeFields->Month < 1 || tfTimeFields->Month > 12 ||
+ tfTimeFields->Day < 1 ||
+ tfTimeFields->Day > MonthLengths
+ [ tfTimeFields->Month ==2 || IsLeapYear(tfTimeFields->Year)]
+ [ tfTimeFields->Month - 1] ||
+ tfTimeFields->Year < 1601 )
+ return FALSE;
- /* FIXME: handle calendar corrections here */
- CurYear = TimeFields.Year - EPOCHYEAR;
- DeltaYear = CurYear / 400;
- CurYear -= DeltaYear * 400;
- rcTime += DeltaYear * DAYSPERQUADRICENTENNIUM;
- DeltaYear = CurYear / 100;
- CurYear -= DeltaYear * 100;
- rcTime += DeltaYear * DAYSPERNORMALCENTURY;
- DeltaYear = CurYear / 4;
- CurYear -= DeltaYear * 4;
- rcTime += DeltaYear * DAYSPERNORMALQUADRENNIUM;
- rcTime += CurYear * DAYSPERNORMALYEAR;
- rcTime += YearDays[IsLeapYear(TimeFields.Year)][TimeFields.Month - 1];
- rcTime += TimeFields.Day - 1;
- rcTime *= SECSPERDAY;
- rcTime += TimeFields.Hour * SECSPERHOUR + TimeFields.Minute * SECSPERMIN + TimeFields.Second;
- rcTime *= TICKSPERSEC;
- rcTime += TimeFields.Milliseconds * TICKSPERMSEC;
- Time->QuadPart = rcTime;
+ /* now calculate a day count from the date
+ * First start counting years from March. This way the leap days
+ * are added at the end of the year, not somewhere in the middle.
+ * Formula's become so much less complicate that way.
+ * To convert: add 12 to the month numbers of Jan and Feb, and
+ * take 1 from the year */
+ if(tfTimeFields->Month < 3) {
+ month = tfTimeFields->Month + 13;
+ year = tfTimeFields->Year - 1;
+ } else {
+ month = tfTimeFields->Month + 1;
+ year = tfTimeFields->Year;
+ }
+ cleaps = (3 * (year / 100) + 3) / 4; /* nr of "century leap years"*/
+ day = (36525 * year) / 100 - cleaps + /* year * dayperyr, corrected */
+ (1959 * month) / 64 + /* months * daypermonth */
+ tfTimeFields->Day - /* day of the month */
+ 584817 ; /* zero that on 1601-01-01 */
+ /* done */
+
+ Time->QuadPart = (((((LONGLONG) day * HOURSPERDAY +
+ tfTimeFields->Hour) * MINSPERHOUR +
+ tfTimeFields->Minute) * SECSPERMIN +
+ tfTimeFields->Second ) * 1000 +
+ tfTimeFields->Milliseconds ) * TICKSPERMSEC;
- return TRUE;
+ return TRUE;
}
/***********************************************************************
--- wine/dlls/ntdll/tests/time.c 2004-10-30 08:54:46.000000000 +0200
+++ mywine/dlls/ntdll/tests/time.c 2004-11-03 17:26:01.000000000 +0100
@@ -27,6 +27,7 @@
#define SECSPERDAY 86400
static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
+static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) ;
static const int MonthLengths[2][12] =
{
@@ -44,7 +45,7 @@ TIME_FIELDS tftest = {1889,12,31,23,59,5
static void test_pRtlTimeToTimeFields()
{
- LARGE_INTEGER litime ;
+ LARGE_INTEGER litime , liresult;
TIME_FIELDS tfresult;
int i=0;
litime.QuadPart = ((ULONGLONG)0x0144017a << 32) | 0xf0b0a980;
@@ -59,6 +60,12 @@ static void test_pRtlTimeToTimeFields()
tftest.Hour, tftest.Minute,tftest.Second,
tfresult.Year, tfresult.Month, tfresult.Day,
tfresult.Hour, tfresult.Minute, tfresult.Second);
+ /* test the inverse */
+ pRtlTimeFieldsToTime( &tfresult, &liresult);
+ ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
+ tfresult.Year, tfresult.Month, tfresult.Day,
+ tfresult.Hour, tfresult.Minute, tfresult.Second,
+ (int) (liresult.QuadPart - litime.QuadPart) );
/* one second later is beginning of next month */
litime.QuadPart += TICKSPERSEC ;
pRtlTimeToTimeFields( &litime, &tfresult);
@@ -71,6 +78,12 @@ static void test_pRtlTimeToTimeFields()
tftest.Month % 12 + 1, 1, 0, 0, 0,
tfresult.Year, tfresult.Month, tfresult.Day,
tfresult.Hour, tfresult.Minute, tfresult.Second);
+ /* test the inverse */
+ pRtlTimeFieldsToTime( &tfresult, &liresult);
+ ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
+ tfresult.Year, tfresult.Month, tfresult.Day,
+ tfresult.Hour, tfresult.Minute, tfresult.Second,
+ (int) (liresult.QuadPart - litime.QuadPart) );
/* advance to the end of the month */
litime.QuadPart -= TICKSPERSEC ;
if( tftest.Month == 12) {
@@ -89,7 +102,8 @@ START_TEST(time)
#ifdef __WINE_WINTERNL_H
HMODULE mod = GetModuleHandleA("ntdll.dll");
pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
- if (pRtlTimeToTimeFields)
+ pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
+ if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
test_pRtlTimeToTimeFields();
#endif
}
--- wine/dlls/kernel/time.c 2004-10-30 08:54:35.000000000 +0200
+++ mywine/dlls/kernel/time.c 2004-11-05 16:35:54.000000000 +0100
@@ -277,7 +277,8 @@ BOOL WINAPI SetLocalTime(
LARGE_INTEGER st, st2;
NTSTATUS status;
- SystemTimeToFileTime( systime, &ft );
+ if( !SystemTimeToFileTime( systime, &ft ))
+ return FALSE;
st.u.LowPart = ft.dwLowDateTime;
st.u.HighPart = ft.dwHighDateTime;
RtlLocalTimeToSystemTime( &st, &st2 );
@@ -329,7 +330,8 @@ BOOL WINAPI SetSystemTime(
LARGE_INTEGER t;
NTSTATUS status;
- SystemTimeToFileTime( systime, &ft );
+ if( !SystemTimeToFileTime( systime, &ft ))
+ return FALSE;
t.u.LowPart = ft.dwLowDateTime;
t.u.HighPart = ft.dwHighDateTime;
if ((status = NtSetSystemTime(&t, NULL)))
@@ -820,7 +822,10 @@ BOOL WINAPI SystemTimeToFileTime( const
tf.Second = syst->wSecond;
tf.Milliseconds = syst->wMilliseconds;
- RtlTimeFieldsToTime(&tf, &t);
+ if( !RtlTimeFieldsToTime(&tf, &t)) {
+ SetLastError( ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
ft->dwLowDateTime = t.u.LowPart;
ft->dwHighDateTime = t.u.HighPart;
return TRUE;
--- wine/dlls/kernel/tests/time.c 2004-10-30 08:54:39.000000000 +0200
+++ mywine/dlls/kernel/tests/time.c 2004-11-04 22:08:29.000000000 +0100
@@ -136,7 +136,6 @@ static void test_invalid_arg()
ok( (ft.dwHighDateTime==NEWYEAR_1980_HI) && (ft.dwLowDateTime==NEWYEAR_1980_LO),
"filetime for 1/1/80 00:00:00 was %08lx %08lx\n", ft.dwHighDateTime, ft.dwLowDateTime);
- todo_wine {
/* now check SystemTimeToFileTime */
memset(&ft,0,sizeof ft);
@@ -155,16 +154,15 @@ static void test_invalid_arg()
/* with a bad hour */
SETUP_1980(st)
- st.wHour = 25;
+ st.wHour = 24;
ok( !SystemTimeToFileTime(&st, &ft), "bad hour\n");
/* with a bad minute */
SETUP_1980(st)
- st.wMinute = 61;
+ st.wMinute = 60;
ok( !SystemTimeToFileTime(&st, &ft), "bad minute\n");
- }
}
void test_GetTimeZoneInformation()
--- wine/dlls/msvcrt/time.c 2004-10-28 08:36:13.000000000 +0200
+++ mywine/dlls/msvcrt/time.c 2004-11-05 16:17:55.000000000 +0100
@@ -30,6 +30,7 @@
#endif
#include "msvcrt.h"
+#include "limits.h"
#include "winbase.h"
#include "wine/debug.h"
@@ -61,29 +62,72 @@ static struct MSVCRT_tm tm;
*/
MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
{
- MSVCRT_time_t secs;
- SYSTEMTIME st;
- FILETIME lft, uft;
- ULONGLONG time;
+ MSVCRT_time_t secs;
+ FILETIME lft, uft;
+ ULONGLONG time;
+ struct MSVCRT_tm ts;
+ int cleaps, day;
- st.wMilliseconds = 0;
- st.wSecond = t->tm_sec;
- st.wMinute = t->tm_min;
- st.wHour = t->tm_hour;
- st.wDay = t->tm_mday;
- st.wMonth = t->tm_mon + 1;
- st.wYear = t->tm_year + 1900;
+ ts=*t;
+ /* to prevent arithmetic overflows put constraints on some fields */
+ /* whether the effective date falls in the 1970-2038 time period */
+ /* will be tested later */
+ /* BTW, I have no idea what limits native msvcrt has. */
+ if ( ts.tm_year < 0 || ts.tm_year > 140 ||
+ ts.tm_mon < -840 || ts.tm_mon > 840 ||
+ ts.tm_mday < -20160 || ts.tm_mday > 20160 ||
+ ts.tm_hour < -484000 || ts.tm_hour > 484000 ||
+ ts.tm_min < -29000000 || ts.tm_min > 29000000 )
+ return -1;
+
+ /* normalize the tm month fields */
+ if( ts.tm_mon > 11) { ts.tm_year += ts.tm_mon / 12; ts.tm_mon %= 12; }
+ if( ts.tm_mon < 0) {
+ int dy = (11 - ts.tm_mon) / 12;
+ ts.tm_year -= dy;
+ ts.tm_mon += dy * 12;
+ }
+ /* now calculate a day count from the date
+ * First start counting years from March. This way the leap days
+ * are added at the end of the year, not somewhere in the middle.
+ * Formula's become so much less complicate that way.
+ * To convert: add 12 to the month numbers of Jan and Feb, and
+ * take 1 from the year */
+ if(ts.tm_mon < 2) {
+ ts.tm_mon += 14;
+ ts.tm_year += 1899;
+ } else {
+ ts.tm_mon += 2;
+ ts.tm_year += 1900;
+ }
+ cleaps = (3 * (ts.tm_year / 100) + 3) / 4; /* nr of "century leap years"*/
+ day = (36525 * ts.tm_year) / 100 - cleaps + /* year * dayperyr, corrected*/
+ (1959 * ts.tm_mon) / 64 + /* months * daypermonth */
+ ts.tm_mday - /* day of the month */
+ 584817 ; /* zero that on 1601-01-01 */
+ /* done */
- SystemTimeToFileTime(&st, &lft);
- LocalFileTimeToFileTime(&lft, &uft);
+ /* convert to 100 ns ticks */
+ time = ((((ULONGLONG) day * 24 +
+ ts.tm_hour) * 60 +
+ ts.tm_min) * 60 +
+ ts.tm_sec ) * TICKSPERSEC;
+
+ lft.dwHighDateTime = (DWORD) (time >> 32);
+ lft.dwLowDateTime = (DWORD) time;
- time = ((ULONGLONG)uft.dwHighDateTime << 32) | uft.dwLowDateTime;
- secs = time / TICKSPERSEC - SECS_1601_TO_1970;
- /* compute tm_wday, tm_yday and renormalize the other fields of the
- * tm structure */
- if( MSVCRT_localtime( &secs)) *t = tm;
+ LocalFileTimeToFileTime(&lft, &uft);
- return secs;
+ time = ((ULONGLONG)uft.dwHighDateTime << 32) | uft.dwLowDateTime;
+ time /= TICKSPERSEC;
+ if( time < SECS_1601_TO_1970 || time > (SECS_1601_TO_1970 + INT_MAX))
+ return -1;
+ secs = time - SECS_1601_TO_1970;
+ /* compute tm_wday, tm_yday and renormalize the other fields of the
+ * tm structure */
+ if( MSVCRT_localtime( &secs)) *t = tm;
+
+ return secs;
}
/*********************************************************************
--- wine/dlls/msvcrt/tests/time.c 2004-10-26 08:25:34.000000000 +0200
+++ mywine/dlls/msvcrt/tests/time.c 2004-11-04 18:59:50.000000000 +0100
@@ -52,7 +52,7 @@ static void test_mktime()
{
TIME_ZONE_INFORMATION tzinfo;
DWORD res = GetTimeZoneInformation(&tzinfo);
- struct tm my_tm;
+ struct tm my_tm, sav_tm;
time_t nulltime, local_time;
char TZ_env[256];
int secs;
@@ -73,10 +73,71 @@ static void test_mktime()
my_tm.tm_year = 70;
my_tm.tm_mon = 0;
my_tm.tm_isdst= 0;
+
+ sav_tm = my_tm;
local_time = mktime(&my_tm);
ok(((DWORD)local_time == SECSPERDAY), "mktime returned 0x%08lx\n",(DWORD)local_time);
+ /* now test some unnormalized struct tm's */
+ my_tm = sav_tm;
+ my_tm.tm_sec += 60;
+ my_tm.tm_min -= 1;
+ local_time = mktime(&my_tm);
+ ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time);
+ ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
+ my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
+ my_tm.tm_sec == sav_tm.tm_sec
+ , "mktime returned %3d-%02d-%02d %02d:%02d expected %3d-%02d-%02d %02d:%02d.\n",
+ my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
+ my_tm.tm_hour,my_tm.tm_sec,
+ sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
+ sav_tm.tm_hour,sav_tm.tm_sec);
+ my_tm = sav_tm;
+ my_tm.tm_min -= 60;
+ my_tm.tm_hour += 1;
+ local_time = mktime(&my_tm);
+ ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time);
+ ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
+ my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
+ my_tm.tm_sec == sav_tm.tm_sec
+ , "mktime returned %3d-%02d-%02d %02d:%02d expected %3d-%02d-%02d %02d:%02d.\n",
+ my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
+ my_tm.tm_hour,my_tm.tm_sec,
+ sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
+ sav_tm.tm_hour,sav_tm.tm_sec);
+ my_tm = sav_tm;
+ my_tm.tm_mon -= 12;
+ my_tm.tm_year += 1;
+ local_time = mktime(&my_tm);
+ ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time);
+ ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
+ my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
+ my_tm.tm_sec == sav_tm.tm_sec
+ , "mktime returned %3d-%02d-%02d %02d:%02d expected %3d-%02d-%02d %02d:%02d.\n",
+ my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
+ my_tm.tm_hour,my_tm.tm_sec,
+ sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
+ sav_tm.tm_hour,sav_tm.tm_sec);
+ my_tm = sav_tm;
+ my_tm.tm_mon += 12;
+ my_tm.tm_year -= 1;
+ local_time = mktime(&my_tm);
+ ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time);
+ ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
+ my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
+ my_tm.tm_sec == sav_tm.tm_sec
+ , "mktime returned %3d-%02d-%02d %02d:%02d expected %3d-%02d-%02d %02d:%02d.\n",
+ my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
+ my_tm.tm_hour,my_tm.tm_sec,
+ sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
+ sav_tm.tm_hour,sav_tm.tm_sec);
+ /* now a bad time example */
+ my_tm = sav_tm;
+ my_tm.tm_year -= 1;
+ local_time = mktime(&my_tm);
+ ok((local_time == -1), "(bad time) mktime returned 0x%08lx\n",(DWORD)local_time);
+ my_tm = sav_tm;
/* TEST that we are independent from the TZ variable */
/*Argh, msvcrt doesn't have setenv() */
_snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
More information about the wine-patches
mailing list