2025-04-27 07:49:33 -04:00

310 lines
6.8 KiB
C++

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name :
DateTime.cxx
Abstract:
Date parsing routines thanx to JohnL (01/24/95)
--*/
#include "precomp.hxx"
# if !defined(dllexp)
# define dllexp __declspec( dllexport)
# endif
/************************************************************
* Data
************************************************************/
static const WCHAR* s_rgchDays[] = {
TEXT("Sun"), TEXT("Mon"), TEXT("Tue"), TEXT("Wed"),
TEXT("Thu"), TEXT("Fri"), TEXT("Sat")
};
static const WCHAR* s_rgchMonths[] = {
TEXT("Jan"), TEXT("Feb"), TEXT("Mar"), TEXT("Apr"),
TEXT("May"), TEXT("Jun"), TEXT("Jul"), TEXT("Aug"),
TEXT("Sep"), TEXT("Oct"), TEXT("Nov"), TEXT("Dec")
};
// Custom hash table for make_month() for mapping "Apr" to 4
static const CHAR MonthIndexTable[64] = {
-1,'A', 2, 12, -1, -1, -1, 8, // A to G
-1, -1, -1, -1, 7, -1,'N', -1, // F to O
9, -1,'R', -1, 10, -1, 11, -1, // P to W
-1, 5, -1, -1, -1, -1, -1, -1, // X to Z
-1,'A', 2, 12, -1, -1, -1, 8, // a to g
-1, -1, -1, -1, 7, -1,'N', -1, // f to o
9, -1,'R', -1, 10, -1, 11, -1, // p to w
-1, 5, -1, -1, -1, -1, -1, -1 // x to z
};
static const BYTE TensDigit[10] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 };
/************************************************************
* Functions
************************************************************/
WORD
iis_2atoi(
PWCHAR s
)
/*++
Converts a 2 character string to integer
Arguments:
s String to convert
Returns:
numeric equivalent, 0 on failure.
--*/
{
DWORD tens = s[0] - L'0';
DWORD ones = s[1] - L'0';
if ( (tens <= 9) && (ones <= 9) ) {
return((WORD)(TensDigit[tens] + ones));
}
return(0);
}
WORD
make_month(
PWCHAR s
)
{
UCHAR monthIndex;
UCHAR c;
LPCTSTR monthString;
//
// use the third character as the index
//
c = ((CHAR) s[2] - 0x40) & 0x3F;
monthIndex = MonthIndexTable[c];
if ( monthIndex < 13 ) {
goto verify;
}
//
// ok, we need to look at the second character
//
if ( monthIndex == 'N' ) {
//
// we got an N which we need to resolve further
//
//
// if s[1] is 'u' then Jun, if 'a' then Jan
//
if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) {
monthIndex = 1;
} else {
monthIndex = 6;
}
} else if ( monthIndex == 'R' ) {
//
// if s[1] is 'a' then March, if 'p' then April
//
if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) {
monthIndex = 3;
} else {
monthIndex = 4;
}
} else {
goto error_exit;
}
verify:
monthString = s_rgchMonths[monthIndex-1];
if ( (s[0] == monthString[0]) &&
(s[1] == monthString[1]) &&
(s[2] == monthString[2]) ) {
return(monthIndex);
} else if ( (toupper(s[0]) == monthString[0]) &&
(tolower(s[1]) == monthString[1]) &&
(tolower(s[2]) == monthString[2]) ) {
return monthIndex;
}
error_exit:
return(0);
} // make_month
BOOL
NtSystemTimeToLargeInteger(
IN const SYSTEMTIME * pst,
OUT LARGE_INTEGER * pli
)
{
FILETIME ft;
//
// Convert to file time
//
if ( !SystemTimeToFileTime( pst, &ft ) ) {
return(FALSE);
}
//
// Convert file time to large integer
//
pli->LowPart = ft.dwLowDateTime;
pli->HighPart = ft.dwHighDateTime;
return(TRUE);
}
dllexp
BOOL
StringTimeToFileTime(
IN const WCHAR * pszTime,
OUT __int64 * pliTime
)
/*++
Converts a string representation of a GMT time (three different
varieties) to an NT representation of a file time.
We handle the following variations:
Sun, 06 Nov 1994 08:49:37 GMT (RFC 822 updated by RFC 1123)
Sunday, 06-Nov-94 08:49:37 GMT (RFC 850)
Sun Nov 6 08:49:37 1994 (ANSI C's asctime() format
Arguments:
pszTime String representation of time field
pliTime large integer containing the time in NT format.
Returns:
TRUE on success and FALSE on failure.
History:
Johnl 24-Jan-1995 Modified from WWW library
--*/
{
WCHAR * s;
SYSTEMTIME st;
LARGE_INTEGER liTime;
if (pszTime == NULL) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
st.wMilliseconds = 0;
if ((s = wcschr(pszTime, ','))) {
DWORD len;
//
// Thursday, 10-Jun-93 01:29:59 GMT
// or: Thu, 10 Jan 1993 01:29:59 GMT */
//
s++;
while (*s && *s==' ') s++;
len = wcslen(s);
if (len < 18) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if ( *(s+2) == '-' ) { /* First format */
st.wDay = (WORD) _wtoi(s);
st.wMonth = (WORD) make_month(s+3);
st.wYear = (WORD) _wtoi(s+7);
st.wHour = (WORD) _wtoi(s+10);
st.wMinute = (WORD) _wtoi(s+13);
st.wSecond = (WORD) _wtoi(s+16);
} else { /* Second format */
if (len < 20) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
st.wDay = iis_2atoi(s);
st.wMonth = make_month(s+3);
st.wYear = iis_2atoi(s+7) * 100 + iis_2atoi(s+9);
st.wHour = iis_2atoi(s+12);
st.wMinute = iis_2atoi(s+15);
st.wSecond = iis_2atoi(s+18);
}
} else { /* Try the other format: Wed Jun 9 01:29:59 1993 GMT */
s = (WCHAR *) pszTime;
while (*s && *s==' ') s++;
if ((int)wcslen(s) < 24) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
st.wDay = (WORD) _wtoi(s+8);
st.wMonth = (WORD) make_month(s+4);
st.wYear = (WORD) _wtoi(s+20);
st.wHour = (WORD) _wtoi(s+11);
st.wMinute = (WORD) _wtoi(s+14);
st.wSecond = (WORD) _wtoi(s+17);
}
//
// Adjust for dates with only two digits
//
if ( st.wYear < 1000 ) {
if ( st.wYear < 50 ) {
st.wYear += 2000;
} else {
st.wYear += 1900;
}
}
if ( !NtSystemTimeToLargeInteger( &st, &liTime )) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
*pliTime = liTime.QuadPart;
return(TRUE);
}