📄 variant.c
字号:
/* 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; /* Februaury 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)
{
int rollForward = 0;
/* Possibly need to roll the date forward */
if (lpUd->st.wMonth == 2 && IsLeapYear(lpUd->st.wYear))
rollForward = lpUd->st.wDay - 29; /* Februaury has 29 days on leap years */
else
rollForward = lpUd->st.wDay - days[lpUd->st.wMonth];
if (rollForward > 0)
{
lpUd->st.wDay = rollForward;
lpUd->st.wMonth++;
if (lpUd->st.wMonth > 12)
{
lpUd->st.wMonth = 1; /* Roll forward into January of the next year */
lpUd->st.wYear++;
}
}
}
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;
}
/**********************************************************************
* DosDateTimeToVariantTime [OLEAUT32.14]
*
* Convert a Dos format date and time into variant VT_DATE format.
*
* PARAMS
* wDosDate [I] Dos format date
* wDosTime [I] Dos format time
* pDateOut [O] Destination for VT_DATE format
*
* RETURNS
* Success: TRUE. pDateOut contains the converted time.
* Failure: FALSE, if wDosDate or wDosTime are invalid (see notes).
*
* NOTES
* - Dos format dates can only hold dates from 1-Jan-1980 to 31-Dec-2099.
* - Dos format times are accurate to only 2 second precision.
* - The format of a Dos Date is:
*| Bits Values Meaning
*| ---- ------ -------
*| 0-4 1-31 Day of the week. 0 rolls back one day. A value greater than
*| the days in the month rolls forward the extra days.
*| 5-8 1-12 Month of the year. 0 rolls back to December of the previous
*| year. 13-15 are invalid.
*| 9-15 0-119 Year based from 1980 (Max 2099). 120-127 are invalid.
* - The format of a Dos Time is:
*| Bits Values Meaning
*| ---- ------ -------
*| 0-4 0-29 Seconds/2. 30 and 31 are invalid.
*| 5-10 0-59 Minutes. 60-63 are invalid.
*| 11-15 0-23 Hours (24 hour clock). 24-32 are invalid.
*/
INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
double *pDateOut)
{
UDATE ud;
TRACE("(0x%x(%d/%d/%d),0x%x(%d:%d:%d),%p)\n",
wDosDate, DOS_YEAR(wDosDate), DOS_MONTH(wDosDate), DOS_DAY(wDosDate),
wDosTime, DOS_HOUR(wDosTime), DOS_MINUTE(wDosTime), DOS_SECOND(wDosTime),
pDateOut);
ud.st.wYear = DOS_YEAR(wDosDate);
ud.st.wMonth = DOS_MONTH(wDosDate);
if (ud.st.wYear > 2099 || ud.st.wMonth > 12)
return FALSE;
ud.st.wDay = DOS_DAY(wDosDate);
ud.st.wHour = DOS_HOUR(wDosTime);
ud.st.wMinute = DOS_MINUTE(wDosTime);
ud.st.wSecond = DOS_SECOND(wDosTime);
ud.st.wDayOfWeek = ud.st.wMilliseconds = 0;
return !VarDateFromUdate(&ud, 0, pDateOut);
}
/**********************************************************************
* VariantTimeToDosDateTime [OLEAUT32.13]
*
* Convert a variant format date into a Dos format date and time.
*
* dateIn [I] VT_DATE time format
* pwDosDate [O] Destination for Dos format date
* pwDosTime [O] Destination for Dos format time
*
* RETURNS
* Success: TRUE. pwDosDate and pwDosTime contains the converted values.
* Failure: FALSE, if dateIn cannot be represented in Dos format.
*
* NOTES
* See DosDateTimeToVariantTime() for Dos format details and bugs.
*/
INT WINAPI VariantTimeToDosDateTime(double dateIn, USHORT *pwDosDate, USHORT *pwDosTime)
{
UDATE ud;
TRACE("(%g,%p,%p)\n", dateIn, pwDosDate, pwDosTime);
if (FAILED(VarUdateFromDate(dateIn, 0, &ud)))
return FALSE;
if (ud.st.wYear < 1980 || ud.st.wYear > 2099)
return FALSE;
*pwDosDate = DOS_DATE(ud.st.wDay, ud.st.wMonth, ud.st.wYear);
*pwDosTime = DOS_TIME(ud.st.wHour, ud.st.wMinute, ud.st.wSecond);
TRACE("Returning 0x%x(%d/%d/%d), 0x%x(%d:%d:%d)\n",
*pwDosDate, DOS_YEAR(*pwDosDate), DOS_MONTH(*pwDosDate), DOS_DAY(*pwDosDate),
*pwDosTime, DOS_HOUR(*pwDosTime), DOS_MINUTE(*pwDosTime), DOS_SECOND(*pwDosTime));
return TRUE;
}
/***********************************************************************
* SystemTimeToVariantTime [OLEAUT32.184]
*
* Convert a System format date and time into variant VT_DATE format.
*
* PARAMS
* lpSt [I] System format date and time
* pDateOut [O] Destination for VT_DATE format date
*
* RETURNS
* Success: TRUE. *pDateOut contains the converted value.
* Failure: FALSE, if lpSt cannot be represented in VT_DATE format.
*/
INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut)
{
UDATE ud;
TRACE("(%p->%d/%d/%d %d:%d:%d,%p)\n", lpSt, lpSt->wDay, lpSt->wMonth,
lpSt->wYear, lpSt->wHour, lpSt->wMinute, lpSt->wSecond, pDateOut);
if (lpSt->wMonth > 12)
return FALSE;
memcpy(&ud.st, lpSt, sizeof(ud.st));
return !VarDateFromUdate(&ud, 0, pDateOut);
}
/***********************************************************************
* VariantTimeToSystemTime [OLEAUT32.185]
*
* Convert a variant VT_DATE into a System format date and time.
*
* PARAMS
* datein [I] Variant VT_DATE format date
* lpSt [O] Destination for System format date and time
*
* RETURNS
* Success: TRUE. *lpSt contains the converted value.
* Failure: FALSE, if dateIn is too large or small.
*/
INT WINAPI VariantTimeToSystemTime(double dateIn, LPSYSTEMTIME lpSt)
{
UDATE ud;
TRACE("(%g,%p)\n", dateIn, lpSt);
if (FAILED(VarUdateFromDate(dateIn, 0, &ud)))
return FALSE;
memcpy(lpSt, &ud.st, sizeof(ud.st));
return TRUE;
}
/***********************************************************************
* VarDateFromUdateEx [OLEAUT32.319]
*
* Convert an unpacked format date and time to a variant VT_DATE.
*
* PARAMS
* pUdateIn [I] Unpacked format date and time to convert
* lcid [I] Locale identifier for the conversion
* dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
* pDateOut [O] Destination for variant VT_DATE.
*
* RETURNS
* Success: S_OK. *pDateOut contains the converted value.
* Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format.
*/
HRESULT WINAPI VarDateFromUdateEx(UDATE *pUdateIn, LCID lcid, ULONG dwFlags, DATE *pDateOut)
{
UDATE ud;
double dateVal;
TRACE("(%p->%d/%d/%d %d:%d:%d:%d %d %d,0x%08x,0x%08x,%p)\n", pUdateIn,
pUdateIn->st.wMonth, pUdateIn->st.wDay, pUdateIn->st.wYear,
pUdateIn->st.wHour, pUdateIn->st.wMinute, pUdateIn->st.wSecond,
pUdateIn->st.wMilliseconds, pUdateIn->st.wDayOfWeek,
pUdateIn->wDayOfYear, lcid, dwFlags, pDateOut);
if (lcid != MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT))
FIXME("lcid possibly not handled, treating as en-us\n");
memcpy(&ud, pUdateIn, sizeof(ud));
if (dwFlags & VAR_VALIDDATE)
WARN("Ignoring VAR_VALIDDATE\n");
if (FAILED(VARIANT_RollUdate(&ud)))
return E_INVALIDARG;
/* Date */
dateVal = VARIANT_DateFromJulian(VARIANT_JulianFromDMY(ud.st.wYear, ud.st.wMonth, ud.st.wDay));
/* Time */
dateVal += ud.st.wHour / 24.0;
dateVal += ud.st.wMinute / 1440.0;
dateVal += ud.st.wSecond / 86400.0;
dateVal += ud.st.wMilliseconds / 86400000.0;
TRACE("Returning %g\n", dateVal);
*pDateOut = dateVal;
return S_OK;
}
/***********************************************************************
* VarDateFromUdate [OLEAUT32.330]
*
* Convert an unpacked format date and time to a variant VT_DATE.
*
* PARAMS
* pUdateIn [I] Unpacked format date and time to convert
* dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
* pDateOut [O] Destination for variant VT_DATE.
*
* RETURNS
* Success: S_OK. *pDateOut contains the converted value.
* Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format.
*
* NOTES
* This function uses the United States English locale for the conversion. Use
* VarDateFromUdateEx() for alternate locales.
*/
HRESULT WINAPI VarDateFromUdate(UDATE *pUdateIn, ULONG dwFlags, DATE *pDateOut)
{
LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
return VarDateFromUdateEx(pUdateIn, lcid, dwFlags, pDateOut);
}
/***********************************************************************
* VarUdateFromDate [OLEAUT32.331]
*
* Convert a variant VT_DATE into an unpacked format date and time.
*
* PARAMS
* datein [I] Variant VT_DATE format date
* dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
* lpUdate [O] Destination for unpacked format date and time
*
* RETURNS
* Success: S_OK. *lpUdate contains the converted value.
* Failure: E_INVALIDARG, if dateIn is too large or small.
*/
HRESULT WINAPI VarUdateFromDate(DATE dateIn, ULONG dwFlags, UDATE *lpUdate)
{
/* Cumulative totals of days per month */
static const USHORT cumulativeDays[] =
{
0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
double datePart, timePart;
int julianDays;
TRACE("(%g,0x%08x,%p)\n", dateIn, dwFlags, lpUdate);
if (dateIn <= (DATE_MIN - 1.0) || dateIn >= (DATE_MAX + 1.0))
return E_INVALIDARG;
datePart = dateIn < 0.0 ? ceil(dateIn) : floor(dateIn);
/* Compensate for int truncation (always downwards) */
timePart = dateIn - datePart + 0.00000000001;
if (timePart >= 1.0)
timePart -= 0.00000000001;
/* Date */
julianDays = VARIANT_JulianFromDate(dateIn);
VARIANT_DMYFromJulian(julianDays, &lpUdate->st.wYear, &lpUdate->st.wMonth,
&lpUdate->st.wDay);
datePart = (datePart + 1.5) / 7.0;
lpUdate->st.wDayOfWeek = (datePart - floor(datePart)) * 7;
if (lpUdate->st.wDayOfWeek == 0)
lpUdate->st.wDayOfWeek = 5;
else if (lpUdate->st.wDayOfWeek == 1)
lpUdate->st.wDayOfWeek = 6;
else
lpUdate->st.wDayOfWeek -= 2;
if (lpUdate->st.wMonth > 2 && IsLeapYear(lpUdate->st.wYear))
lpUdate->wDayOfYear = 1; /* After February, in a leap year */
else
lpUdate->wDayOfYear = 0;
lpUdate->wDayOfYear += cumulativeDays[lpUdate->st.wMonth];
lpUdate->wDayOfYear += lpUdate->st.wDay;
/* Time */
timePart *= 24.0;
lpUdate->st.wHour = timePart;
timePart -= lpUdate->st.wHour;
timePart *= 60.0;
lpUdate->st.wMinute = timePart;
timePart -= lpUdate->st.wMinute;
timePart *= 60.0;
lpUdate->st.wSecond = timePart;
timePart -= lpUdate->st.wSecond;
lpUdate->st.wMilliseconds = 0;
if (timePart > 0.5)
{
/* Round the milliseconds, adjusting the time/date forward if needed */
if (lpUdate->st.wSecond < 59)
lpUdate->st.wSecond++;
else
{
lpUdate->st.wSecond = 0;
if (lpUdate->st.wMinute < 59)
lpUdate->st.wMinute++;
else
{
lpUdate->st.wMinute = 0;
if (lpUdate->st.wHour < 23)
lpUdate->st.wHour++;
else
{
lpUdate->st.wHour = 0;
/* Roll over a whole day */
if (++lpUdate->st.wDay > 28)
VARIANT_RollUdate(lpUdate);
}
}
}
}
return S_OK;
}
#define GET_NUMBER_TEXT(fld,name) \
buff[0] = 0; \
if (!GetLocaleInfoW(lcid, lctype|fld, buff, 2)) \
WARN("buffer too small for " #fld "\n"); \
else \
if (buff[0]) lpChars->name = buff[0]; \
TRACE("lcid 0x%x, " #name "=%d '%c'\n", lcid, lpChars->name, lpChars->name)
/* Get the valid number characters for an lcid */
static void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -