Variant Date/Time

Daniel Walker diwalker at earthlink.net
Sun Aug 12 12:29:35 CDT 2001


Changelog:
Daniel Walker diwalker at earthink.net
 - Fixed a typo in variant.c
 - implemented SystemTimetoVariantTime/VariantTimetoSystemTime
        There was another implementation of SystemTimetoVariantTime 
        submitted that didn't work for dates prior to 1900. 
 - implemented VarDateFromUDate/VarUdateFromDate
 - implemented VariantTimeToDosDateTime

Modified files:
    include/: oleauto.h
    dlls/oleaut32/: variant.c
                    oleaut32.spec
-------------- next part --------------
Index: dlls/oleaut32/oleaut32.spec
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/oleaut32.spec,v
retrieving revision 1.27
diff -u -r1.27 oleaut32.spec
--- dlls/oleaut32/oleaut32.spec	2001/07/24 00:59:28	1.27
+++ dlls/oleaut32/oleaut32.spec	2001/08/12 16:24:31
@@ -23,7 +23,7 @@
 10 stdcall VariantCopy(ptr ptr) VariantCopy
 11 stdcall VariantCopyInd(ptr ptr) VariantCopyInd
 12 stdcall VariantChangeType(ptr ptr long long) VariantChangeType
-13 stub VariantTimeToDosDateTime
+13 stdcall VariantTimeToDosDateTime(double ptr ptr) VariantTimeToDosDateTime
 14 stdcall DosDateTimeToVariantTime(long long ptr) DosDateTimeToVariantTime
 15 stdcall SafeArrayCreate(long long ptr) SafeArrayCreate
 16 stdcall SafeArrayDestroy(ptr) SafeArrayDestroy
@@ -152,8 +152,8 @@
 171 stub ClearCustData
 180 stub CreateTypeLib2
 183 stdcall LoadTypeLibEx (ptr long ptr) LoadTypeLibEx
-184 stub SystemTimeToVariantTime
-185 stub VariantTimeToSystemTime
+184 stdcall SystemTimeToVariantTime(ptr ptr) SystemTimeToVariantTime
+185 stdcall VariantTimeToSystemTime(double ptr) VariantTimeToSystemTime
 186 stdcall UnRegisterTypeLib (ptr long long long long) UnRegisterTypeLib
 190 stub VarDecFromUI1
 191 stub VarDecFromI2
@@ -263,8 +263,8 @@
 297 stub LPSAFEARRAY_Unmarshal
 320 stdcall DllRegisterServer() OLEAUT32_DllRegisterServer
 321 stdcall DllUnregisterServer() OLEAUT32_DllUnregisterServer
-330 stub VarDateFromUdate
-331 stub VarUdateFromDate
+330 stdcall VarDateFromUdate(ptr long ptr) VarDateFromUdate
+331 stdcall VarUdateFromDate(double long ptr) VarUdateFromDate
 332 stub GetAltMonthNames
 380 stub UserHWND_from_local
 381 stub UserHWND_to_local
Index: dlls/oleaut32/variant.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/variant.c,v
retrieving revision 1.17
diff -u -r1.17 variant.c
--- dlls/oleaut32/variant.c	2001/07/02 19:59:42	1.17
+++ dlls/oleaut32/variant.c	2001/08/12 16:24:38
@@ -383,7 +383,7 @@
 			 * Note: The day must be converted from [1-366] to [0-365]
 			 */
 			/*pTm->tm_yday = nDay - 1;*/
-			/* find which mount this day corresponds to.
+			/* find which month this day corresponds to.
 			 */
 			if( nDay <= 31 )
 			{
@@ -4331,3 +4331,257 @@
     return TmToDATE( &t, pvtime );
 }
 
+/**********************************************************************
+ *              VariantTimeToDosDateTime [OLEAUT32.??]
+ * Convert variant representation of time to the date and time representation
+ * stored in dos.
+ */
+INT WINAPI VariantTimeToDosDateTime(DATE pvtime,
+				    USHORT *wDosDate, USHORT *wDosTime)
+{
+    struct tm t;
+    wDosTime = 0;
+    wDosDate = 0;
+
+    TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", *wDosDate, *wDosTime, &pvtime );
+    
+    if (DateToTm(pvtime, (LCID)NULL, &t) < 0) return 0;
+
+    *wDosTime = *wDosTime | (t.tm_sec / 2);
+    *wDosTime = *wDosTime | (t.tm_min << 5);
+    *wDosTime = *wDosTime | (t.tm_hour << 11);
+
+    *wDosDate = *wDosDate | t.tm_mday ;
+    *wDosDate = *wDosDate | t.tm_mon << 5;
+    *wDosDate = *wDosDate | ((t.tm_year - 1980) << 9) ;
+	
+    return 1;
+}
+
+
+HRESULT WINAPI SystemTimeToVariantTime(
+  LPSYSTEMTIME  lpSystemTime,  
+  double        *pvtime           
+)
+{
+	UINT16 Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+	UINT16 Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+	
+        struct tm t;
+
+	TRACE(" %d/%d/%d %d:%d:%d\n",
+	     lpSystemTime->wMonth, lpSystemTime->wDay,
+             lpSystemTime->wYear, lpSystemTime->wHour,
+             lpSystemTime->wMinute, lpSystemTime->wSecond);
+
+	if (lpSystemTime->wYear >= 1900)
+	{
+		t.tm_sec = lpSystemTime->wSecond;
+    		t.tm_min = lpSystemTime->wMinute;
+    		t.tm_hour = lpSystemTime->wHour;
+    
+		t.tm_mday = lpSystemTime->wDay;
+		t.tm_mon = lpSystemTime->wMonth;
+		t.tm_year = lpSystemTime->wYear;
+
+		return TmToDATE( &t, pvtime );
+	}
+	else
+	{
+		t.tm_sec = lpSystemTime->wSecond;
+    		t.tm_min = lpSystemTime->wMinute;
+    		t.tm_hour = lpSystemTime->wHour;
+    
+		if (isleap(lpSystemTime->wYear) )
+			t.tm_mday = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
+		else
+			t.tm_mday = Days_Per_Month[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
+	
+		t.tm_mon = 13 - lpSystemTime->wMonth;
+		t.tm_year = 1900 + 1899 - lpSystemTime->wYear;
+
+		TmToDATE( &t, pvtime );
+
+		*pvtime *= -1;
+		
+		return 1;
+	}
+	
+return 0;
+}
+
+HRESULT WINAPI VariantTimeToSystemTime( 
+  double vtime,              
+  LPSYSTEMTIME  lpSystemTime  
+)
+{
+ double t = 0, timeofday = 0;
+
+ UINT16 Days_Per_Month[] =    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ UINT16 Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+ /* The Month_Code is used to find the Day of the Week (LY = LeapYear)*/
+ UINT16 Month_Code[] =    {0, 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
+ UINT16 Month_Code_LY[] = {0, 0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
+
+ /* The Century_Code is used to find the Day of the Week */
+ UINT16 Century_Code[]  = {0, 6, 4, 2};
+
+ struct tm r;
+
+	TRACE(" Variant = %f SYSTEMTIME ptr %p", vtime, lpSystemTime);
+
+	if (vtime >= 0)
+	{
+
+		if (DateToTm(vtime, (LCID)NULL, &r ) <= 0) return 0;
+
+		lpSystemTime->wSecond = r.tm_sec; 
+		lpSystemTime->wMinute = r.tm_min; 
+		lpSystemTime->wHour = r.tm_hour; 
+    
+		lpSystemTime->wDay = r.tm_mday; 
+
+		lpSystemTime->wMonth = r.tm_mon; 
+
+		if (lpSystemTime->wMonth == 12)
+			lpSystemTime->wMonth = 1;
+		else
+			lpSystemTime->wMonth++;
+
+		lpSystemTime->wYear = r.tm_year; 
+
+	}
+	else
+	{
+		vtime = -1*vtime;
+
+		if (DateToTm(vtime, (LCID)NULL, &r ) <= 0) return 0;
+
+		lpSystemTime->wSecond = r.tm_sec; 
+		lpSystemTime->wMinute = r.tm_min; 
+		lpSystemTime->wHour = r.tm_hour; 
+    
+		lpSystemTime->wMonth = 13 - r.tm_mon;
+ 
+		if (lpSystemTime->wMonth == 1)
+			lpSystemTime->wMonth = 12;
+		else
+			lpSystemTime->wMonth--;
+
+		lpSystemTime->wYear = 1899 - (r.tm_year - 1900); 
+
+		if (!isleap(lpSystemTime->wYear) )
+			lpSystemTime->wDay = Days_Per_Month[13 - lpSystemTime->wMonth] - r.tm_mday; 
+		else
+			lpSystemTime->wDay = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - r.tm_mday; 
+
+
+	}
+
+	if (!isleap(lpSystemTime->wYear))
+	{
+		/*
+		(Century_Code+Month_Code+Year_Code+Day) % 7
+
+		The century code repeats every 400 years , so the array
+		works out like this,
+
+		Century_Code[0] is for 16th/20th Centry
+		Century_Code[1] is for 17th/21th Centry
+		Century_Code[2] is for 18th/22th Centry
+		Century_Code[3] is for 19th/23th Centry
+
+		The year code is found with the formula (year + (year / 4))
+		the "year" must be between 0 and 99 .
+
+		The Month Code (Month_Code[1]) starts with January and
+		ends with December.
+		*/
+
+		lpSystemTime->wDayOfWeek = (
+		Century_Code[(( (lpSystemTime->wYear+100) - lpSystemTime->wYear%100) /100) %4]+
+		((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
+		Month_Code[lpSystemTime->wMonth]+
+		lpSystemTime->wDay) % 7;
+	
+		if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
+		else lpSystemTime->wDayOfWeek -= 1;
+	}
+	else
+	{
+		lpSystemTime->wDayOfWeek = (
+		Century_Code[(((lpSystemTime->wYear+100) - lpSystemTime->wYear%100)/100)%4]+
+		((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
+		Month_Code_LY[lpSystemTime->wMonth]+
+		lpSystemTime->wDay) % 7;
+	
+		if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
+		else lpSystemTime->wDayOfWeek -= 1;
+	}
+
+	t = floor(vtime);
+	timeofday = vtime - t;
+
+	lpSystemTime->wMilliseconds = (timeofday 
+			- lpSystemTime->wHour*(1/24)
+			- lpSystemTime->wMinute*(1/1440) 
+			- lpSystemTime->wSecond*(1/86400) )*(1/5184000);
+
+	return 1;
+
+}
+
+HRESULT WINAPI VarUdateFromDate( 
+  DATE datein, ULONG dwFlags,             
+  UDATE *pudateout)
+{
+  HRESULT i = 0;
+  UINT16 Days_Per_Month[] =    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+  UINT16 Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+  
+  TRACE("DATE = %f\n", (double)datein);
+  i = VariantTimeToSystemTime(datein, &(pudateout->st) );
+
+  if (i == TRUE)
+  {
+	 pudateout->wDayOfYear = 0;
+
+	if (isleap(pudateout->st.wYear))
+	{
+	  for (i =1; i<pudateout->st.wMonth; i++)
+	    pudateout->wDayOfYear += Days_Per_Month[i];
+	}
+	else
+	{
+	  for (i =1; i<pudateout->st.wMonth; i++)
+	    pudateout->wDayOfYear += Days_Per_Month_LY[i];
+	}
+	
+     pudateout->wDayOfYear += pudateout->st.wDay;
+     dwFlags = 0; //VAR_VALIDDATE;
+  }
+  else dwFlags = 0;
+
+ return i;
+}
+
+HRESULT WINAPI VarDateFromUdate(UDATE *pudateout,
+				ULONG dwFlags, DATE *datein) 
+{
+    HRESULT i;
+    double t = 0;
+	TRACE(" %d/%d/%d %d:%d:%d\n",
+	     pudateout->st.wMonth, pudateout->st.wDay,
+             pudateout->st.wYear, pudateout->st.wHour,
+             pudateout->st.wMinute, pudateout->st.wSecond);
+
+
+    i = SystemTimeToVariantTime(&(pudateout->st), &t);
+    *datein = t;
+
+    if (i == TRUE) dwFlags = 0; //VAR_VALIDDATE;
+    else dwFlags = 0;
+
+    return i;	
+}
Index: include/oleauto.h
===================================================================
RCS file: /home/wine/wine/include/oleauto.h,v
retrieving revision 1.37
diff -u -r1.37 oleauto.h
--- include/oleauto.h	2001/05/31 21:32:08	1.37
+++ include/oleauto.h	2001/08/12 16:24:42
@@ -1,6 +1,7 @@
 #ifndef __WINE_OLEAUTO_H
 #define __WINE_OLEAUTO_H
 
+#include "winbase.h"
 #include "wtypes.h"
 #include "wine/obj_base.h"
 #include "wine/obj_oleaut.h"
@@ -13,6 +14,7 @@
 struct tagSAFEARRAY;
 struct tagSAFEARRAYBOUND;
 struct tagVARIANT;
+struct UDATE;
 
 #ifdef __cplusplus
 extern "C" {
@@ -519,8 +521,19 @@
     REGKIND_NONE
 } REGKIND;
 
+typedef struct {
+    SYSTEMTIME st;
+    USHORT wDayOfYear;
+} UDATE;
 
 INT WINAPI DosDateTimeToVariantTime(USHORT,USHORT,DATE*);
+INT WINAPI VariantTimeToDosDateTime(DATE, USHORT *, USHORT *);
+
+HRESULT WINAPI VariantTimeToSystemTime(double,LPSYSTEMTIME);
+HRESULT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME,double*);
+
+HRESULT WINAPI VarDateFromUdate(UDATE*,ULONG, DATE*);
+HRESULT WINAPI VarUdateFromDate(DATE, ULONG, UDATE *);
 
 ULONG WINAPI LHashValOfNameSysA(SYSKIND syskind,LCID lcid,LPCSTR szName);
 ULONG WINAPI LHashValOfNameSys (SYSKIND syskind,LCID lcid,LPCOLESTR szName);


More information about the wine-patches mailing list