From 149f70b369016e209f1d90fe4a24a7c2410630a1 Mon Sep 17 00:00:00 2001 From: Rein Klazes Date: Fri, 22 Oct 2004 19:54:17 +0000 Subject: [PATCH] Correct the calculation of the year for the 31'st of December of 2000 and every 400 years after that. Add a test used to find this bug. --- dlls/ntdll/tests/.cvsignore | 1 + dlls/ntdll/tests/Makefile.in | 3 +- dlls/ntdll/tests/time.c | 89 ++++++++++++++++++++++++++++++++++++ dlls/ntdll/time.c | 2 + 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 dlls/ntdll/tests/time.c diff --git a/dlls/ntdll/tests/.cvsignore b/dlls/ntdll/tests/.cvsignore index d19bd80703b..e2ef7e4097c 100644 --- a/dlls/ntdll/tests/.cvsignore +++ b/dlls/ntdll/tests/.cvsignore @@ -9,3 +9,4 @@ rtlbitmap.ok rtlstr.ok string.ok testlist.c +time.ok diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in index 3b05ba80a5d..af18eeda404 100644 --- a/dlls/ntdll/tests/Makefile.in +++ b/dlls/ntdll/tests/Makefile.in @@ -14,7 +14,8 @@ CTESTS = \ rtl.c \ rtlbitmap.c \ rtlstr.c \ - string.c + string.c \ + time.c @MAKE_TEST_RULES@ diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c new file mode 100644 index 00000000000..5672de579bf --- /dev/null +++ b/dlls/ntdll/tests/time.c @@ -0,0 +1,89 @@ +/* + * Unit test suite for ntdll time functions + * + * Copyright 2004 Rein Klazes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ntdll_test.h" +#define TICKSPERSEC 10000000 +#define TICKSPERMSEC 10000 +#define SECSPERDAY 86400 + +static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ; + +static const int MonthLengths[2][12] = +{ + { 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) ? 1 : 0; +} + +/* start time of the tests */ +TIME_FIELDS tftest = {1889,12,31,23,59,59,0,0}; + +static void test_pRtlTimeToTimeFields() +{ + LARGE_INTEGER litime ; + TIME_FIELDS tfresult; + int i=0; + litime.QuadPart = ((ULONGLONG)0x0144017a << 32) | 0xf0b0a980; + while( tftest.Year < 2110 ) { + /* test at the last second of the month */ + pRtlTimeToTimeFields( &litime, &tfresult); + ok( tfresult.Year == tftest.Year && tfresult.Month == tftest.Month && + tfresult.Day == tftest.Day && tfresult.Hour == tftest.Hour && + tfresult.Minute == tftest.Minute && tfresult.Second == tftest.Second, + "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i, + tftest.Year, tftest.Month, tftest.Day, + tftest.Hour, tftest.Minute,tftest.Second, + tfresult.Year, tfresult.Month, tfresult.Day, + tfresult.Hour, tfresult.Minute, tfresult.Second); + /* one second later is beginning of next month */ + litime.QuadPart += TICKSPERSEC ; + pRtlTimeToTimeFields( &litime, &tfresult); + ok( tfresult.Year == tftest.Year + (tftest.Month ==12) && + tfresult.Month == tftest.Month % 12 + 1 && + tfresult.Day == 1 && tfresult.Hour == 0 && + tfresult.Minute == 0 && tfresult.Second == 0, + "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i, + tftest.Year + (tftest.Month ==12), + tftest.Month % 12 + 1, 1, 0, 0, 0, + tfresult.Year, tfresult.Month, tfresult.Day, + tfresult.Hour, tfresult.Minute, tfresult.Second); + /* advance to the end of the month */ + litime.QuadPart -= TICKSPERSEC ; + if( tftest.Month == 12) { + tftest.Month = 1; + tftest.Year += 1; + } else + tftest.Month += 1; + tftest.Day = MonthLengths[IsLeapYear(tftest.Year)][tftest.Month - 1]; + litime.QuadPart += (LONGLONG) tftest.Day * TICKSPERSEC * SECSPERDAY; + } +} + +START_TEST(time) +{ + HMODULE mod = GetModuleHandleA("ntdll.dll"); + pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields"); + if (pRtlTimeToTimeFields) + test_pRtlTimeToTimeFields(); +} diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c index e45588025aa..7d3539c4cca 100644 --- a/dlls/ntdll/time.c +++ b/dlls/ntdll/time.c @@ -443,6 +443,8 @@ VOID WINAPI RtlTimeToTimeFields( 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;