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

Alexandre Julliard julliard at winehq.org
Tue Feb 2 10:45:29 CST 2010


Module: wine
Branch: master
Commit: 1b51c21fb30ee3fa4366d3628d343361e1696ef3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1b51c21fb30ee3fa4366d3628d343361e1696ef3

Author: André Hentschel <nerv at dawncrow.de>
Date:   Mon Feb  1 21:26:44 2010 +0100

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

---

 dlls/oleaut32/tests/vartest.c |   30 ++++++++++-----
 dlls/oleaut32/variant.c       |   81 +++++++++++++++++++++++++++--------------
 2 files changed, 74 insertions(+), 37 deletions(-)

diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c
index 8d7cf11..377a847 100644
--- a/dlls/oleaut32/tests/vartest.c
+++ b/dlls/oleaut32/tests/vartest.c
@@ -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,
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index 56ab2b3..dabe746 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -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;
 }




More information about the wine-cvs mailing list