windows-nt/Source/XPSP1/NT/admin/wmi/wbem/common/utillib/wbemtime.cpp
2020-09-26 16:20:57 +08:00

1241 lines
30 KiB
C++

//***************************************************************************
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
// wbemtime.cpp
//
// Purpose: Defines the WBEMTime and WBEMTimeSpan objects which are
// similar to the MFC CTime and CTimeSpan objects. The WBEM versions
// are capable of storing down to the nsec and also have functions for
// Creating from and getting BSTRs.
//
// Note; The current implementation of WBEMTime does not support dates
// before 1/1/1601;
//
// WBEMTime::m_uTime is stored in GMT as 100 nsecs since 1/1/1601
//
//***************************************************************************
#include "precomp.h"
#include <stdio.h>
#pragma warning( disable : 4290 )
#ifdef UTILLIB
#include <assertbreak.h>
#else
#define ASSERT_BREAK(a)
#endif //UTILLIB
#include <WbemTime.h>
#include <comdef.h>
// These are here rather than wbemtime.h so we don't have to doc/support
#define DECPOS 14
#define SGNPOS 21
#define DMTFLEN 25
#define DEPRECATED 0
#define INVALID_TIME_FORMAT 0
#define INVALID_TIME_ARITHMETIC 0
#define BAD_TIMEZONE 0
// ****************************************************************
// Static functions and variables. These can't be called/referenced
// outside of wbemtime.cpp
static WBEMTime g_Jan1970((time_t)0);
//***************************************************************************
//
// StructtmToSystemTime
//
// Description: General utility for converting between the two common
// data structures.
//
// Return values: TRUE if OK;
//
//***************************************************************************
static BOOL StructtmToSystemTime(const struct tm *ptm, SYSTEMTIME * pst)
{
if (pst && ptm)
{
pst->wYear = ptm->tm_year + 1900;
pst->wMonth = ptm->tm_mon + 1;
pst->wDay = (WORD)ptm->tm_mday;
pst->wHour = (WORD)ptm->tm_hour;
pst->wMinute = (WORD)ptm->tm_min;
pst->wSecond = (WORD)ptm->tm_sec;
pst->wDayOfWeek = (WORD)ptm->tm_wday;
pst->wMilliseconds = 0;
return TRUE;
}
return FALSE;
}
static BOOL SystemTimeToStructtm(const SYSTEMTIME *pst, struct tm *ptm)
{
if (pst && ptm && pst->wYear >= 1900)
{
ptm->tm_year = pst->wYear - 1900;
ptm->tm_mon = pst->wMonth - 1;
ptm->tm_mday = pst->wDay;
ptm->tm_hour = pst->wHour;
ptm->tm_min = pst->wMinute;
ptm->tm_sec = pst->wSecond;
ptm->tm_wday = pst->wDayOfWeek;
ptm->tm_isdst = 0; // Since we are working in gmt...
return TRUE;
}
return FALSE;
}
//***************************************************************************
//
// FileTimeToui64
// ui64ToFileTime
//
// Description: Conversion routines for going between FILETIME structures
// and __int64.
//
//***************************************************************************
static void FileTimeToui64(const FILETIME *pft, ULONGLONG *p64)
{
*p64 = pft->dwHighDateTime;
*p64 = *p64 << 32;
*p64 |= pft->dwLowDateTime;
}
static void ui64ToFileTime(const ULONGLONG *p64,FILETIME *pft)
{
unsigned __int64 uTemp = *p64;
pft->dwLowDateTime = (DWORD)uTemp;
uTemp = uTemp >> 32;
pft->dwHighDateTime = (DWORD)uTemp;
}
static int CompareSYSTEMTIME(const SYSTEMTIME *pst1, const SYSTEMTIME *pst2)
{
FILETIME ft1, ft2;
SystemTimeToFileTime(pst1, &ft1);
SystemTimeToFileTime(pst2, &ft2);
return CompareFileTime(&ft1, &ft2);
}
// This function is used to convert the relative values that come
// back from GetTimeZoneInformation into an actual date for the year
// in question. The system time structure that is passed in is updated
// to contain the absolute values.
static void DayInMonthToAbsolute(SYSTEMTIME *pst, const WORD wYear)
{
const static int _lpdays[] = {
-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
const static int _days[] = {
-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364
};
SHORT shYearDay;
// If this is not 0, this is not a relative date
if (pst->wYear == 0)
{
// Was that year a leap year?
BOOL bLeap = ( (( wYear % 400) == 0) || ((( wYear % 4) == 0) && (( wYear % 100) != 0)));
// Figure out the day of the year for the first day of the month in question
if (bLeap)
shYearDay = 1 + _lpdays[pst->wMonth - 1];
else
shYearDay = 1 + _days[pst->wMonth - 1];
// Now, figure out how many leap days there have been since 1/1/1601
WORD yc = wYear - 1601;
WORD y4 = (yc) / 4;
WORD y100 = (yc) / 100;
WORD y400 = (yc) / 400;
// This will tell us the day of the week for the first day of the month in question.
// The '1 +' reflects the fact that 1/1/1601 was a monday (figures). You might ask,
// 'why do we care what day of the week this is?' Well, I'll tell you. The way
// daylight savings time is defined is with things like 'the last sunday of the month
// of october.' Kinda helps to know what day that is.
SHORT monthdow = (1 + (yc * 365 + y4 + y400 - y100) + shYearDay) % 7;
if ( monthdow < pst->wDayOfWeek )
shYearDay += (pst->wDayOfWeek - monthdow) + (pst->wDay - 1) * 7;
else
shYearDay += (pst->wDayOfWeek - monthdow) + pst->wDay * 7;
/*
* May have to adjust the calculation above if week == 5 (meaning
* the last instance of the day in the month). Check if yearday falls
* beyond month and adjust accordingly.
*/
if ( (pst->wDay == 5) &&
(shYearDay > (bLeap ? _lpdays[pst->wMonth] :
_days[pst->wMonth])) )
{
shYearDay -= 7;
}
// Now update the structure.
pst->wYear = wYear;
pst->wDay = shYearDay - (bLeap ? _lpdays[pst->wMonth - 1] :
_days[pst->wMonth - 1]);
}
}
// **************************************************************************
// These are static to WBEMTIME, which means they CAN be called from outside
// wbemtime
LONG WBEMTime::GetLocalOffsetForDate(const time_t &t)
{
FILETIME ft;
ULONGLONG ull = Int32x32To64(t, 10000000) + 116444736000000000;
ui64ToFileTime(&ull, &ft);
return GetLocalOffsetForDate(&ft);
}
LONG WBEMTime::GetLocalOffsetForDate(const struct tm *ptmin)
{
SYSTEMTIME st;
StructtmToSystemTime(ptmin, &st);
return GetLocalOffsetForDate(&st);
}
LONG WBEMTime::GetLocalOffsetForDate(const FILETIME *pft)
{
SYSTEMTIME st;
FileTimeToSystemTime(pft, &st);
return GetLocalOffsetForDate(&st);
}
LONG WBEMTime::GetLocalOffsetForDate(const SYSTEMTIME *pst)
{
TIME_ZONE_INFORMATION tzTime;
DWORD dwRes = GetTimeZoneInformation(&tzTime);
LONG lRes = 0xffffffff;
switch (dwRes)
{
case TIME_ZONE_ID_UNKNOWN:
{
// Read tz, but no dst defined in this zone
lRes = tzTime.Bias * -1;
break;
}
case TIME_ZONE_ID_STANDARD:
case TIME_ZONE_ID_DAYLIGHT:
{
// Convert the relative dates to absolute dates
DayInMonthToAbsolute(&tzTime.DaylightDate, pst->wYear);
DayInMonthToAbsolute(&tzTime.StandardDate, pst->wYear);
if ( CompareSYSTEMTIME(&tzTime.DaylightDate, &tzTime.StandardDate) < 0 )
{
/*
* Northern hemisphere ordering
*/
if ( CompareSYSTEMTIME(pst, &tzTime.DaylightDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.StandardDate) > 0)
{
lRes = tzTime.Bias * -1;
}
else
{
lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
}
}
else
{
/*
* Southern hemisphere ordering
*/
if ( CompareSYSTEMTIME(pst, &tzTime.StandardDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.DaylightDate) > 0)
{
lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
}
else
{
lRes = tzTime.Bias * -1;
}
}
break;
}
case TIME_ZONE_ID_INVALID:
default:
{
// Can't read the timezone info
ASSERT_BREAK(BAD_TIMEZONE);
break;
}
}
return lRes;
}
///////////////////////////////////////////////////////////////////////////
// WBEMTime - This class holds time values.
//***************************************************************************
//
// WBEMTime::operator=(BSTR bstrWbemFormat)
//
// Description: Assignment operator which is also used by the constructor.
// The string must have the format:
// YYYYMMDDHHSS.123456789 So 3:04 am, 1/1/96 would be 199601010304.0
//
// or the format yyyymmddhhmmss.mmmmmmsuuu.
//
// Note that the fractional part can be between 1 and nine digits.
//
// Return: WBEMTime object.
//
//***************************************************************************
const WBEMTime & WBEMTime::operator=(const BSTR bstrWbemFormat)
{
Clear(); // set when properly assigned
if((NULL == bstrWbemFormat) ||
bstrWbemFormat[DECPOS] != L'.'
)
{
ASSERT_BREAK(INVALID_TIME_FORMAT);
return *this;
}
if ( (wcslen(bstrWbemFormat) == DMTFLEN) &&
(bstrWbemFormat[SGNPOS] == L'+' || bstrWbemFormat[SGNPOS] == L'-') )
{
SetDMTF(bstrWbemFormat);
}
else
{
ASSERT_BREAK(INVALID_TIME_FORMAT);
}
return *this;
}
//***************************************************************************
//
// WBEMTime::operator=(const SYSTEMTIME)
//
// Description: Assignment operator which is also used by the constructor.
// This takes a standard WIN32 SYSTEMTIME stucture.
//
// Return: WBEMTime object.
//
//***************************************************************************
const WBEMTime & WBEMTime::operator=(const SYSTEMTIME & st)
{
Clear(); // set when properly assigned
FILETIME t_ft;
if ( SystemTimeToFileTime(&st, &t_ft) )
{
// now assign using a FILETIME.
*this = t_ft;
}
else
{
ASSERT_BREAK(INVALID_TIME_FORMAT);
}
return *this;
}
//***************************************************************************
//
// WBEMTime::operator=(const FILETIME)
//
// Description: Assignment operator which is also used by the constructor.
// This takes a standard WIN32 FILETIME stucture.
//
// Return: WBEMTime object.
//
//***************************************************************************
const WBEMTime & WBEMTime::operator=(const FILETIME & ft)
{
FileTimeToui64(&ft, &m_uTime);
return *this;
}
//***************************************************************************
//
// WBEMTime::operator=(struct tm tmin)
//
// Description: Assignment operator which is also used by the constructor.
// This takes a standard c runtine struct tm stucture.
//
// Return: WBEMTime object.
//
//***************************************************************************
const WBEMTime & WBEMTime::operator=(const struct tm &a_tmin)
{
Clear(); // set when properly assigned
SYSTEMTIME systemTime;
if (StructtmToSystemTime(&a_tmin, &systemTime))
{
*this = systemTime;
}
return *this;
}
//***************************************************************************
//
// WBEMTime::operator=(struct time_t t)
//
// Description: Assignment operator which is also used by the constructor.
// This takes a standard c runtine time_t stucture.
//
// Return: WBEMTime object.
//
//***************************************************************************
const WBEMTime & WBEMTime::operator=(const time_t & t)
{
if (t >= 0)
{
m_uTime = Int32x32To64(t, 10000000) + 116444736000000000;
}
else
{
Clear();
}
return *this;
}
//***************************************************************************
//
// WBEMTime::operator+(const WBEMTime &uAdd)
//
// Description: dummy function for adding two WBEMTime. It doesnt really
// make sense to add two date, but this is here for Tomas's template.
//
// Return: WBEMTime object.
//
//***************************************************************************
WBEMTime WBEMTime::operator+(const WBEMTimeSpan &uAdd) const
{
WBEMTime ret;
if (IsOk() && uAdd.IsOk())
{
ret.m_uTime = m_uTime + uAdd.m_Time;
}
else
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return ret;
}
const WBEMTime &WBEMTime::operator+=( const WBEMTimeSpan &ts )
{
if (IsOk() && ts.IsOk())
{
m_uTime += ts.m_Time ;
}
else
{
Clear();
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return *this ;
}
//***************************************************************************
//
// WBEMTime::operator-(const WBEMTime & sub)
//
// Description: returns a WBEMTimeSpan object as the difference between
// two WBEMTime objects.
//
// Return: WBEMTimeSpan object.
//
//***************************************************************************
WBEMTimeSpan WBEMTime::operator-(const WBEMTime & sub)
{
WBEMTimeSpan ret;
if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_uTime))
{
ret.m_Time = m_uTime-sub.m_uTime;
}
else
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return ret;
}
WBEMTime WBEMTime::operator-(const WBEMTimeSpan & sub) const
{
WBEMTime ret;
if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_Time))
{
ret.m_uTime = m_uTime - sub.m_Time;
}
else
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return ret;
}
const WBEMTime &WBEMTime::operator-=(const WBEMTimeSpan & sub)
{
if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_Time))
{
m_uTime -= sub.m_Time;
}
else
{
Clear();
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return *this;
}
//***************************************************************************
//
// WBEMTime::GetBSTR(void)
//
// This function used to CLAIM to do this:
//
// WRONG Description: Converts the time which is stored as the number of
// nano seconds since 1970 into a bstr with this format.
// YYYYMMDDHHSS.123456789 So 3:04 am, 1/1/96 would be 199601010304.000000000
//
// What it really did was return some bastardized form of a dmtf string. Now
// it returns a dmtf string in gmt form (which is what the docs claim).
//
// Return: BSTR representation of time, or NULL if error. Note that the
// caller should free up this string!
//
//***************************************************************************
BSTR WBEMTime::GetBSTR(void) const
{
return GetDMTF(false) ;
}
//***************************************************************************
//
// WBEMTime::GetDMTFNonNtfs(void)
//
//***************************************************************************
BSTR WBEMTime::GetDMTFNonNtfs(void) const
{
FILETIME t_ft1, t_ft2;
BSTR t_Date = NULL;
if (GetFILETIME(&t_ft1) && FileTimeToLocalFileTime(&t_ft1, &t_ft2))
{
t_Date = WBEMTime(t_ft2).GetDMTF();
if (t_Date != NULL)
{
t_Date[21] = L'+';
t_Date[22] = L'*';
t_Date[23] = L'*';
t_Date[24] = L'*';
}
}
return t_Date;
}
//***************************************************************************
//
// WBEMTime::time_t(time_t * ptm)
//
// Return: TRUE if OK.
//
//***************************************************************************
BOOL WBEMTime::Gettime_t(time_t * ptm) const
{
if( (!IsOk()) || (ptm == NULL) || (*this < g_Jan1970))
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
return FALSE;
}
if (g_Jan1970 != *this)
{
LONGLONG t_tmp = ( (m_uTime - g_Jan1970.m_uTime) / 10000000);
if (t_tmp <= (LONGLONG)0xffffffff)
{
*ptm = (time_t)t_tmp;
}
else
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
return FALSE;
}
}
else
{
*ptm = 0;
}
return TRUE;
}
//***************************************************************************
//
// WBEMTime::GetStructtm(struct tm * ptm)
//
// Return: TRUE if OK.
//
//***************************************************************************
BOOL WBEMTime::GetStructtm(struct tm * ptm) const
{
SYSTEMTIME systemTime;
return (GetSYSTEMTIME(&systemTime) && SystemTimeToStructtm(&systemTime, ptm));
}
//***************************************************************************
//
// WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst)
//
// Return: TRUE if OK.
//
//***************************************************************************
BOOL WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst) const
{
if ((pst == NULL) || (!IsOk()))
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
return FALSE;
}
FILETIME t_ft;
if (GetFILETIME(&t_ft))
{
if (!FileTimeToSystemTime(&t_ft, pst))
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
return FALSE;
}
}
else
{
return FALSE;
}
return TRUE;
}
//***************************************************************************
//
// WBEMTime::GetFILETIME(FILETIME * pst)
//
// Return: TRUE if OK.
//
//***************************************************************************
BOOL WBEMTime::GetFILETIME(FILETIME * pft) const
{
if ((pft == NULL) || (!IsOk()))
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
return FALSE;
}
ui64ToFileTime(&m_uTime, pft);
return TRUE;
}
//***************************************************************************
//
// CWbemTime::SetDMTF(BSTR wszText)
//
// Description: Sets the time value to the DMTF string datetime value
// passed as the parameter
//
// Return: TRUE if OK.
//
//***************************************************************************
BOOL WBEMTime::SetDMTF( const BSTR a_wszText )
{
wchar_t t_DefaultBuffer[] = {L"16010101000000.000000+000"} ;
wchar_t t_DateBuffer[ DMTFLEN + 1 ] ;
t_DateBuffer[ DMTFLEN ] = NULL ;
bstr_t t_bstrDate( a_wszText ) ;
// wildcard cleanup and validation
// ===============================
if( DMTFLEN != t_bstrDate.length() )
{
ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
return FALSE ;
}
wchar_t *t_pwBuffer = (wchar_t*)t_bstrDate ;
for( int t_i = 0; t_i < DMTFLEN; t_i++ )
{
switch( t_pwBuffer[ t_i ] )
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
// stepping on separator or sign
if( DECPOS == t_i || SGNPOS == t_i )
{
ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
return FALSE ;
}
t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
break ;
}
case '*':
{
// stepping on separator or sign
if( DECPOS == t_i || SGNPOS == t_i )
{
ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
return FALSE ;
}
else
{
// replace with default stamp
t_DateBuffer[ t_i ] = t_DefaultBuffer[ t_i ] ;
}
break ;
}
case '.':
{
if( DECPOS != t_i )
{
ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
return FALSE ;
}
t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
break ;
}
case '+':
case '-':
{
if( SGNPOS != t_i )
{
ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
return FALSE ;
}
t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
break ;
}
default:
{
ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
return FALSE ;
}
}
}
// Parse it
// ========
int nYear, nMonth, nDay, nHour, nMinute, nSecond, nMicro, nOffset;
WCHAR wchSep;
int nRes = swscanf (
(LPCWSTR)&t_DateBuffer,
L"%4d%2d%2d%2d%2d%2d.%6d%c%3d",
&nYear,
&nMonth,
&nDay,
&nHour,
&nMinute,
&nSecond,
&nMicro,
&wchSep,
&nOffset
);
if ( ( 9 != nRes ) || ( 1601 > nYear) )
{
ASSERT_BREAK(INVALID_TIME_FORMAT);
return FALSE;
}
// Convert it to SYSTEMTIME
// ========================
SYSTEMTIME st;
st.wYear = (WORD)nYear;
st.wMonth = (WORD)nMonth;
st.wDay = (WORD)nDay;
st.wHour = (WORD)nHour;
st.wMinute = (WORD)nMinute;
st.wSecond = (WORD)nSecond;
st.wMilliseconds = nMicro / 1000;
st.wDayOfWeek = 0;
*this = st;
// NOW we adjust for the offset
// ============================
if ( IsOk() )
{
int nSign = (wchSep == L'+') ? 1 : -1 ;
m_uTime -= (LONGLONG)nSign * (LONGLONG)nOffset * 60 * 10000000;
}
else
{
ASSERT_BREAK( INVALID_TIME_ARITHMETIC ) ;
return FALSE ;
}
return TRUE;
}
//***************************************************************************
//
// BSTR WBEMTime::GetDMTF(void)
//
// Description: Gets the time in DMTF string datetime format. User must call
// SysFreeString with the result. If bLocal is true, then the time is given
// in the local timezone, else the time is given in GMT.
//
// Return: NULL if not OK.
//
//***************************************************************************
BSTR WBEMTime::GetDMTF(BOOL bLocal) const
{
if (!IsOk())
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
return NULL;
}
SYSTEMTIME t_Systime;
wchar_t chsign = L'-';
int offset = 0;
// If the date to be converted is within 12 hours of
// 1/1/1601, return the greenwich time
ULONGLONG t_ConversionZone = 12L * 60L * 60L ;
t_ConversionZone = t_ConversionZone * 10000000L ;
if ( !bLocal || ( m_uTime < t_ConversionZone ) )
{
if(!GetSYSTEMTIME(&t_Systime))
{
return NULL;
}
}
else
{
if (GetSYSTEMTIME(&t_Systime))
{
offset = GetLocalOffsetForDate(&t_Systime);
WBEMTime wt;
if (offset >= 0)
{
chsign = '+';
wt = *this + WBEMTimeSpan(0, 0, offset, 0);
}
else
{
offset *= -1;
wt = *this - WBEMTimeSpan(0, 0, offset, 0);
}
wt.GetSYSTEMTIME(&t_Systime);
}
else
{
return NULL;
}
}
LONGLONG tmpMicros = m_uTime%10000000;
LONG micros = (LONG)(tmpMicros / 10);
BSTR t_String = SysAllocStringLen(NULL, DMTFLEN + 1);
if ( ! t_String )
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
swprintf(
t_String,
L"%04.4d%02.2d%02.2d%02.2d%02.2d%02.2d.%06.6d%c%03.3ld",
t_Systime.wYear,
t_Systime.wMonth,
t_Systime.wDay,
t_Systime.wHour,
t_Systime.wMinute,
t_Systime.wSecond,
micros,
chsign,
offset
);
return t_String ;
}
///////////////////////////////////////////////////////////////////////////
// WBEMTimeSpan - This class holds timespan values. The data is stored
// in 100 nanosecond units (like FILETIME).
//***************************************************************************
//
// WBEMTimeSpan::WBEMTimeSpan(int iDays, int iHours, int iMinutes, int iSeconds,
// int iMSec, int iUSec, int iNSec)
//
// Description: Constructor.
//
//***************************************************************************
WBEMTimeSpan::WBEMTimeSpan(int iDays, int iHours, int iMinutes, int iSeconds,
int iMSec, int iUSec, int iNSec)
{
m_Time = 0; //todo, check values!!!
m_Time += iSeconds;
m_Time += iMinutes * 60;
m_Time += iHours * 60 * 60;
m_Time += iDays * 24 * 60 * 60;
m_Time *= 10000000;
m_Time += iNSec / 100; // Nanoseconds
m_Time += iUSec*10; // Microseconds
m_Time += iMSec*10000; // Milliseconds
}
WBEMTimeSpan::WBEMTimeSpan ( const FILETIME &ft )
{
ASSERT_BREAK(DEPRECATED);
*this = ft ;
}
WBEMTimeSpan::WBEMTimeSpan ( const time_t & t )
{
ASSERT_BREAK(DEPRECATED);
*this = t ;
} ;
//***************************************************************************
//
// WBEMTimeSpan::operator=(const BSTR bstrWbemFormat)
//
// Return: WBEMTimeSpan object.
//
//***************************************************************************
const WBEMTimeSpan & WBEMTimeSpan::operator=(const BSTR bstrWbemFormat)
{
Clear();
// all characters should be digits except for one which
// must be a period
if ((bstrWbemFormat == NULL) || (bstrWbemFormat[DECPOS] != L'.') ||
(wcslen(bstrWbemFormat) != DMTFLEN) || (bstrWbemFormat[SGNPOS] != L':') )
{
ASSERT_BREAK(INVALID_TIME_FORMAT);
return *this;
}
int nDays, nHours, nMinutes, nSeconds, nMicros, nOffset;
WCHAR wchSep;
int nRes = swscanf (
bstrWbemFormat,
L"%8d%2d%2d%2d.%6d%c%3d",
&nDays,
&nHours,
&nMinutes,
&nSeconds,
&nMicros,
&wchSep,
&nOffset
);
if ( (nRes != 7) || ( nOffset != 0) )
{
ASSERT_BREAK(INVALID_TIME_FORMAT);
return *this;
}
*this = WBEMTimeSpan(nDays, nHours, nMinutes, nSeconds, 0, nMicros, 0);
return *this;
}
//***************************************************************************
//
// WBEMTimeSpan::operator=(const FILETIME &)
// WBEMTimeSpan::operator=(const time_t &)
//
// Description: Assignment operator which is also used by the constructor.
//
// Return: WBEMTimeSpan object.
//
//***************************************************************************
const WBEMTimeSpan & WBEMTimeSpan::operator=(const FILETIME &ft)
{
ASSERT_BREAK(DEPRECATED);
ULONGLONG uTemp;
FileTimeToui64(&ft, &uTemp);
m_Time = uTemp;
return *this;
}
const WBEMTimeSpan & WBEMTimeSpan::operator=(const time_t & t)
{
ASSERT_BREAK(DEPRECATED);
ULONGLONG uTemp = 0;
uTemp = t;
if (t >= 0)
{
m_Time = uTemp * 10000000;
}
else
{
Clear();
}
return *this;
}
//***************************************************************************
//
// WBEMTimeSpan::operator +(const WBEMTimeSpan &uAdd)
//
// Description: function for adding two WBEMTimeSpan objects.
//
// Return: WBEMTimeSpan object.
//
//***************************************************************************
WBEMTimeSpan WBEMTimeSpan::operator+(const WBEMTimeSpan &uAdd) const
{
WBEMTimeSpan ret;
if (IsOk() && uAdd.IsOk())
{
ret.m_Time = m_Time + uAdd.m_Time;
}
else
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return ret;
}
const WBEMTimeSpan &WBEMTimeSpan::operator+= ( const WBEMTimeSpan &uAdd )
{
if (IsOk() && uAdd.IsOk())
{
m_Time += uAdd.m_Time ;
}
else
{
Clear();
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return *this ;
}
//***************************************************************************
//
// WBEMTimeSpan::operator -(const WBEMTimeSpan &uAdd)
//
// Description: function for adding two WBEMTimeSpan objects.
//
// Return: WBEMTimeSpan object.
//
//***************************************************************************
WBEMTimeSpan WBEMTimeSpan::operator-(const WBEMTimeSpan &uSub) const
{
WBEMTimeSpan ret;
if (IsOk() && uSub.IsOk() && (m_Time >= uSub.m_Time))
{
ret.m_Time = m_Time - uSub.m_Time;
}
else
{
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return ret;
}
const WBEMTimeSpan &WBEMTimeSpan::operator-= ( const WBEMTimeSpan &uSub )
{
if (IsOk() && uSub.IsOk() && (m_Time >= uSub.m_Time))
{
m_Time -= uSub.m_Time;
}
else
{
Clear();
ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
}
return *this;
}
//***************************************************************************
//
// WBEMTimeSpan::GetBSTR(void)
//
// Description: Converts the time which is stored as the number of
// 100 nano second units into a dmtf formatted string
// ddddddddhhmmss.mmmmmm:000
//
// Return: BSTR representation of time, or NULL if error. Note that the
// caller should free up this string!
//
//***************************************************************************
BSTR WBEMTimeSpan::GetBSTR(void) const
{
if(!IsOk())
{
return NULL;
}
ULONGLONG Time = m_Time;
// The /10 is to convert from 100ns to microseconds
long iMicro = (long)((Time % 10000000) / 10);
Time /= 10000000;
int iSec = (int)(Time % 60);
Time /= 60;
int iMin = (int)(Time % 60);
Time /= 60;
int iHour = (int)(Time % 24);
Time /= 24;
BSTR t_String = SysAllocStringLen(NULL, DMTFLEN + 1);
if ( ! t_String )
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
swprintf(t_String, L"%08I64i%02d%02d%02d.%06ld:000",
Time, iHour, iMin, iSec, iMicro);
return t_String ;
}
//***************************************************************************
//
// WBEMTimeSpan::Gettime_t(void)
// WBEMTimeSpan::GetFILETIME(void)
//
// Description: Converts the time span which is stored as the number of
// nano seconds into common stuctures.
//
// Return: TRUE if OK.
//
//***************************************************************************
BOOL WBEMTimeSpan::Gettime_t(time_t * ptime_t) const
{
ASSERT_BREAK(DEPRECATED);
if(!IsOk())
{
return FALSE;
}
*ptime_t = (DWORD)(m_Time / 10000000);
return TRUE;
}
BOOL WBEMTimeSpan::GetFILETIME(FILETIME * pst) const
{
ASSERT_BREAK(DEPRECATED);
if(!IsOk())
{
return FALSE;
}
ULONGLONG uTemp;
uTemp = m_Time;
ui64ToFileTime(&uTemp,pst);
return TRUE;
}