Commit 1b51c21f authored by André Hentschel's avatar André Hentschel Committed by Alexandre Julliard

oleaut32: Rewrite RollUdate to be easier to change and to support more conversions.

parent c4568edd
......@@ -1639,26 +1639,36 @@ static void test_VarDateFromUdate(void)
CHECKPTR(VarDateFromUdate);
UD2T(1,1,1980,0,0,0,0,2,1,0,S_OK,29221.0); /* 1 Jan 1980 */
UD2T(2,1,1980,0,0,0,0,3,2,0,S_OK,29222.0); /* 2 Jan 1980 */
UD2T(2,1,1980,0,0,0,0,4,5,0,S_OK,29222.0); /* 2 Jan 1980 */
UD2T(31,12,1990,0,0,0,0,0,0,0,S_OK,33238.0); /* 31 Dec 1990 */
UD2T(31,12,90,0,0,0,0,0,0,0,S_OK,33238.0); /* year < 100 is 1900+year! */
UD2T(30,12,1899,0,0,0,0,6,364,0,S_OK,0.0); /* 30 Dec 1899 - VT_DATE 0.0 */
UD2T(1,1,100,0,0,0,0,0,0,0,S_OK,-657434.0); /* 1 Jan 100 - Min */
UD2T(31,12,9999,0,0,0,0,0,0,0,S_OK,2958465.0); /* 31 Dec 9999 - Max */
UD2T(1,1,10000,0,0,0,0,0,0,0,E_INVALIDARG,0.0); /* > 31 Dec 9999 => err */
UD2T(1,1,-10000,0,0,0,0,0,0,0,E_INVALIDARG,0.0);/* < -9999 => err */
UD2T(30,12,1899,0,0,0,0,0,0,0,S_OK,0.0); /* 30 Dec 1899 0:00:00 */
UD2T(30,12,1899,0,0,0,999,0,0,0,S_OK,0.0); /* Ignore milliseconds */
UD2T(1,1,1980,18,1,16,0,2,1,0,S_OK,29221.75087962963); /* 6:18:02 PM */
todo_wine UD2T(0,1,1980,42,1,16,0,2,1,0,S_OK,29221.75087962963); /* Test rolled hours */
todo_wine UD2T(1,1,1980,17,61,16,0,2,1,0,S_OK,29221.75087962963); /* Test rolled minutes */
todo_wine UD2T(1,1,1980,18,0,76,0,2,1,0,S_OK,29221.75087962963); /* Test rolled seconds */
todo_wine UD2T(2,1,1980,-6,1,16,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled hours */
todo_wine UD2T(1,1,1980,19,-59,16,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled minutes */
todo_wine UD2T(1,1,1980,18,2,-44,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled seconds */
UD2T(0,1,1980,0,0,0,0,2,1,0,S_OK,29220.0); /* Rolls back to 31 Dec 1899 */
UD2T(1,13,1980,0,0,0,0,2,1,0,S_OK,29587.0); /* Rolls fwd to 1/1/1981 */
UD2T(1,1,1980,18,1,16,0,2,1,0,S_OK,29221.75087962963); /* 6:18:02 PM */
UD2T(0,1,1980,42,1,16,0,2,1,0,S_OK,29221.75087962963); /* Test fwdrolled hours */
UD2T(1,1,1980,17,61,16,0,2,1,0,S_OK,29221.75087962963); /* Test fwdrolled minutes */
UD2T(1,1,1980,18,0,76,0,2,1,0,S_OK,29221.75087962963); /* Test fwdrolled seconds */
UD2T(3,1,1980,-30,1,16,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled hours */
UD2T(1,1,1980,20,-119,16,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled minutes */
UD2T(1,1,1980,18,3,-104,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled seconds */
UD2T(1,12001,-1020,18,1,16,0,0,0,0,S_OK,29221.75087962963); /* Test rolled year and month */
UD2T(1,-23,1982,18,1,16,0,0,0,0,S_OK,29221.75087962963); /* Test backrolled month */
todo_wine UD2T(-59,3,1980,18,1,16,0,0,0,0,S_OK,29221.75087962963); /* Test backrolled days */
todo_wine UD2T(1,1,0,0,0,0,0,0,0,0,S_OK,36526); /* Test zero year */
UD2T(0,0,1980,0,0,0,0,0,0,0,S_OK,29189); /* Test zero day and month */
UD2T(0,1,1980,0,0,0,0,2,1,0,S_OK,29220.0); /* Test zero day = LastDayOfMonth */
UD2T(-1,1,1980,18,1,16,0,0,0,0,S_OK,29219.75087962963); /* Test day -1 = LastDayOfMonth - 1 */
UD2T(1,1,-1,18,1,16,0,0,0,0,S_OK,36161.75087962963); /* Test year -1 = 1999 */
UD2T(1,-1,1980,18,1,16,0,0,0,0,S_OK,29160.7508796296); /* Test month -1 = 11 */
UD2T(1,13,1980,0,0,0,0,2,1,0,S_OK,29587.0); /* Rolls fwd to 1/1/1981 */
}
static void test_st2dt(int line, WORD d, WORD m, WORD y, WORD h, WORD mn,
......
......@@ -1129,30 +1129,47 @@ static inline double VARIANT_JulianFromDMY(USHORT year, USHORT month, USHORT day
static HRESULT VARIANT_RollUdate(UDATE *lpUd)
{
static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
short iYear, iMonth, iDay, iHour, iMinute, iSecond;
TRACE("Raw date: %d/%d/%d %d:%d:%d\n", lpUd->st.wDay, lpUd->st.wMonth,
lpUd->st.wYear, lpUd->st.wHour, lpUd->st.wMinute, lpUd->st.wSecond);
/* interpret values signed */
iYear = lpUd->st.wYear;
iMonth = lpUd->st.wMonth;
iDay = lpUd->st.wDay;
iHour = lpUd->st.wHour;
iMinute = lpUd->st.wMinute;
iSecond = lpUd->st.wSecond;
/* Years < 100 are treated as 1900 + year */
if (lpUd->st.wYear < 100)
lpUd->st.wYear += 1900;
TRACE("Raw date: %d/%d/%d %d:%d:%d\n", iDay, iMonth,
iYear, iHour, iMinute, iSecond);
if (!lpUd->st.wMonth)
{
/* Roll back to December of the previous year */
lpUd->st.wMonth = 12;
lpUd->st.wYear--;
}
else while (lpUd->st.wMonth > 12)
if (iYear > 9999 || iYear < -9999)
return E_INVALIDARG; /* Invalid value */
/* Years < 100 are treated as 1900 + year */
if (iYear >= 0 && iYear < 100)
iYear += 1900;
iMinute += (iSecond - (iSecond % 60)) / 60;
iSecond = iSecond % 60;
iHour += (iMinute - (iMinute % 60)) / 60;
iMinute = iMinute % 60;
iDay += (iHour - (iHour % 24)) / 24;
iHour = iHour % 24;
/* FIXME: Roll Days */
iYear += (iMonth - (iMonth % 12)) / 12;
iMonth = iMonth % 12;
if (iSecond<0){iSecond+=60; iMinute--;}
if (iMinute<0){iMinute+=60; iHour--;}
if (iHour<0) {iHour+=24; iDay--;}
if (iDay<0)
{
/* Roll forward the correct number of months */
lpUd->st.wYear++;
lpUd->st.wMonth -= 12;
iDay+=days[iMonth];
iMonth--;
if (iMonth == 2 && IsLeapYear(iYear))
iDay++;
}
if (lpUd->st.wYear > 9999 || lpUd->st.wHour > 23 ||
lpUd->st.wMinute > 59 || lpUd->st.wSecond > 59)
return E_INVALIDARG; /* Invalid values */
if (iMonth<=0) {iMonth+=12; iYear--;}
if (iYear<0) iYear+=2000;
if (!lpUd->st.wDay)
{
......@@ -1178,22 +1195,30 @@ static HRESULT VARIANT_RollUdate(UDATE *lpUd)
int rollForward = 0;
/* Possibly need to roll the date forward */
if (lpUd->st.wMonth == 2 && IsLeapYear(lpUd->st.wYear))
rollForward = lpUd->st.wDay - 29; /* February has 29 days on leap years */
if (iMonth == 2 && IsLeapYear(iYear))
rollForward = iDay - 29; /* February has 29 days on leap years */
else
rollForward = lpUd->st.wDay - days[lpUd->st.wMonth];
rollForward = iDay - days[iMonth];
if (rollForward > 0)
{
lpUd->st.wDay = rollForward;
lpUd->st.wMonth++;
if (lpUd->st.wMonth > 12)
iDay = rollForward;
iMonth++;
if (iMonth > 12)
{
lpUd->st.wMonth = 1; /* Roll forward into January of the next year */
lpUd->st.wYear++;
iMonth = 1; /* Roll forward into January of the next year */
iYear++;
}
}
}
lpUd->st.wYear = iYear;
lpUd->st.wMonth = iMonth;
lpUd->st.wDay = iDay;
lpUd->st.wHour = iHour;
lpUd->st.wMinute = iMinute;
lpUd->st.wSecond = iSecond;
TRACE("Rolled date: %d/%d/%d %d:%d:%d\n", lpUd->st.wDay, lpUd->st.wMonth,
lpUd->st.wYear, lpUd->st.wHour, lpUd->st.wMinute, lpUd->st.wSecond);
return S_OK;
......@@ -1250,6 +1275,8 @@ INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
ud.st.wMinute = DOS_MINUTE(wDosTime);
ud.st.wSecond = DOS_SECOND(wDosTime);
ud.st.wDayOfWeek = ud.st.wMilliseconds = 0;
if (ud.st.wHour > 23 || ud.st.wMinute > 59 || ud.st.wSecond > 59)
return FALSE; /* Invalid values in Dos*/
return VarDateFromUdate(&ud, 0, pDateOut) == S_OK;
}
......
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