oleaut32: rewrite RollUdate to be easier to change and to support more conversions
André Hentschel
nerv at dawncrow.de
Sun Jan 31 12:02:39 CST 2010
Old version of that function only used if-statements which is not the best solution for a math problem.
---
dlls/oleaut32/tests/vartest.c | 23 ++++++---
dlls/oleaut32/variant.c | 103 ++++++++++++++++++++++-------------------
2 files changed, 71 insertions(+), 55 deletions(-)
diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c
index 8d7cf11..dc8fbae 100644
--- a/dlls/oleaut32/tests/vartest.c
+++ b/dlls/oleaut32/tests/vartest.c
@@ -1639,6 +1639,7 @@ 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 */
@@ -1650,14 +1651,20 @@ static void test_VarDateFromUdate(void)
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(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 */
+
+ UD2T(0,1,1980,0,0,0,0,2,1,0,S_OK,29220.0); /* Test Day 0 = 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 */
}
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index 56ab2b3..7aa62ee 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -1129,71 +1129,78 @@ 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 };
+ INT16 iYear, iMonth, iDay, iHour, iMinute, iSecond;
+ INT16 iMonthTemp;
- 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 = (INT16)lpUd->st.wYear;
+ iMonth = (INT16)lpUd->st.wMonth;
+ iDay = (INT16)lpUd->st.wDay;
+ iHour = (INT16)lpUd->st.wHour;
+ iMinute = (INT16)lpUd->st.wMinute;
+ iSecond = (INT16)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)
+ /* 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 (iMonth<=0) {iMonth+=12; iYear--;}
+ if (iYear<=0) iYear+=2000;
+ if (iYear > 9999 || iYear < -9999)
+ return E_INVALIDARG; /* Invalid value */
- if (lpUd->st.wYear > 9999 || lpUd->st.wHour > 23 ||
- lpUd->st.wMinute > 59 || lpUd->st.wSecond > 59)
- return E_INVALIDARG; /* Invalid values */
-
- if (!lpUd->st.wDay)
- {
- /* Roll back the date one day */
- if (lpUd->st.wMonth == 1)
- {
- /* Roll back to December 31 of the previous year */
- lpUd->st.wDay = 31;
- lpUd->st.wMonth = 12;
- lpUd->st.wYear--;
- }
- else
- {
- lpUd->st.wMonth--; /* Previous month */
- if (lpUd->st.wMonth == 2 && IsLeapYear(lpUd->st.wYear))
- lpUd->st.wDay = 29; /* February has 29 days on leap years */
- else
- lpUd->st.wDay = days[lpUd->st.wMonth]; /* Last day of the month */
- }
- }
- else if (lpUd->st.wDay > 28)
+ if (iDay > 28)
{
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 = (WORD)iYear;
+ lpUd->st.wMonth = (WORD)iMonth;
+ lpUd->st.wDay = (WORD)iDay;
+ lpUd->st.wHour = (WORD)iHour;
+ lpUd->st.wMinute = (WORD)iMinute;
+ lpUd->st.wSecond = (WORD)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 +1257,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;
}
--
Best Regards, André Hentschel
More information about the wine-patches
mailing list