An ATL replacement for COleDateTime
Posted
by Mark A. Richman
on April 11th, 1999
Use this in place of COleDateTime when using ATL. No MFC required.
Header file:
// DateTime.h: interface for the CDateTime class. // ////////////////////////////////////////////////////////////////////// #ifndef AFX_DATETIME_H__A3E968D9_455B_11D2_9288_00E02921E6D0__INCLUDED_ #define AFX_DATETIME_H__A3E968D9_455B_11D2_9288_00E02921E6D0__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include#include #include class CDateTime; class CDateTimeSpan; //////////////////////////////////////////////////////////////////////////// // CDateTime class helpers #define AFX_OLE_DATETIME_ERROR (-1) //////////////////////////////////////////////////////////////////////////// // CDateTime class class CDateTime { // Constructors public: static CDateTime PASCAL GetCurrentTime(); CDateTime(); CDateTime(const CDateTime& dateSrc); CDateTime(const VARIANT& varSrc); CDateTime(DATE dtSrc); CDateTime(time_t& timeSrc); CDateTime(const SYSTEMTIME& systimeSrc); CDateTime(const FILETIME& filetimeSrc); CDateTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec); CDateTime(WORD wDosDate, WORD wDosTime); // Attributes public: enum DateTimeStatus { valid = 0, invalid = 1, // Invalid date (out of range, etc.) null = 2, // Literally has no value }; DATE m_dt; DateTimeStatus m_status; void SetStatus(DateTimeStatus status) { m_status=status;} DateTimeStatus GetStatus() const { return m_status;} int GetYear() const; int GetMonth() const; // month of year (1 = Jan) int GetDay() const; // day of month (0-31) int GetHour() const; // hour in day (0-23) int GetMinute() const; // minute in hour (0-59) int GetSecond() const; // second in minute (0-59) int GetDayOfWeek() const; // 1=Sun, 2=Mon, ..., 7=Sat int GetDayOfYear() const; // days since start of year, Jan 1 = 1 // Operations public: const CDateTime& operator=(const CDateTime& dateSrc); const CDateTime& operator=(const VARIANT& varSrc); const CDateTime& operator=(DATE dtSrc); const CDateTime& operator=(const time_t& timeSrc); const CDateTime& operator=(const SYSTEMTIME& systimeSrc); const CDateTime& operator=(const FILETIME& filetimeSrc); BOOL operator==(const CDateTime& date) const; BOOL operator!=(const CDateTime& date) const; BOOL operator<(const CDateTime& date) const; BOOL operator>(const CDateTime& date) const; BOOL operator<=(const CDateTime& date) const; BOOL operator>=(const CDateTime& date) const; // DateTime math CDateTime operator+(const CDateTimeSpan& dateSpan) const; CDateTime operator-(const CDateTimeSpan& dateSpan) const; const CDateTime& operator+=(const CDateTimeSpan dateSpan); const CDateTime& operator-=(const CDateTimeSpan dateSpan); // DateTimeSpan math CDateTimeSpan operator-(const CDateTime& date) const; operator DATE() const; int SetDateTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec); int SetDate(int nYear, int nMonth, int nDay); int SetTime(int nHour, int nMin, int nSec); BOOL ParseDateTime(LPCTSTR lpszDate, DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT); // formatting _bstr_t Format(DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT) const; _bstr_t Format(LPCTSTR lpszFormat) const; //CComString Format(UINT nFormatID) const; // Implementation protected: void CheckRange(); friend CDateTimeSpan; }; //////////////////////////////////////////////////////////////////////////// // CDateTimeSpan class class CDateTimeSpan { // Constructors public: CDateTimeSpan(); CDateTimeSpan(double dblSpanSrc); CDateTimeSpan(const CDateTimeSpan& dateSpanSrc); CDateTimeSpan(long lDays, int nHours, int nMins, int nSecs); // Attributes public: enum DateTimeSpanStatus { valid = 0, invalid = 1, // Invalid span (out of range, etc.) null = 2, // Literally has no value }; double m_span; DateTimeSpanStatus m_status; void SetStatus(DateTimeSpanStatus status) { m_status=status;} DateTimeSpanStatus GetStatus() const { return m_status;} double GetTotalDays() const; // span in days (about -3.65e6 to 3.65e6) double GetTotalHours() const; // span in hours (about -8.77e7 to 8.77e6) double GetTotalMinutes() const; // span in minutes (about -5.26e9 to 5.26e9) double GetTotalSeconds() const; // span in seconds (about -3.16e11 to 3.16e11) long GetDays() const; // component days in span long GetHours() const; // component hours in span (-23 to 23) long GetMinutes() const; // component minutes in span (-59 to 59) long GetSeconds() const; // component seconds in span (-59 to 59) // Operations public: const CDateTimeSpan& operator=(double dblSpanSrc); const CDateTimeSpan& operator=(const CDateTimeSpan& dateSpanSrc); BOOL operator==(const CDateTimeSpan& dateSpan) const; BOOL operator!=(const CDateTimeSpan& dateSpan) const; BOOL operator<(const CDateTimeSpan& dateSpan) const; BOOL operator>(const CDateTimeSpan& dateSpan) const; BOOL operator<=(const CDateTimeSpan& dateSpan) const; BOOL operator>=(const CDateTimeSpan& dateSpan) const; // DateTimeSpan math CDateTimeSpan operator+(const CDateTimeSpan& dateSpan) const; CDateTimeSpan operator-(const CDateTimeSpan& dateSpan) const; const CDateTimeSpan& operator+=(const CDateTimeSpan dateSpan); const CDateTimeSpan& operator-=(const CDateTimeSpan dateSpan); CDateTimeSpan operator-() const; operator double() const; void SetDateTimeSpan(long lDays, int nHours, int nMins, int nSecs); // formatting _bstr_t Format(LPCTSTR pFormat) const; //CComString Format(UINT nID) const; // Implementation public: void CheckRange(); friend CDateTime; }; #endif // AFX_DATETIME_H__A3E968D9_455B_11D2_9288_00E02921E6D0__INCLUDED_
Source file:
// DateTime.cpp: implementation of the CDateTime class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DateTime.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#endif
////////////////////////////////////////////////////////////////////////////
// CDateTime class HELPER definitions
// Verifies will fail if the needed buffer size is too large
#define MAX_TIME_BUFFER_SIZE 128 // matches that in
timecore.cpp
#define MIN_DATE (-657434L) // about year 100
#define MAX_DATE 2958465L // about year 9999
// Half a second, expressed in days
#define HALF_SECOND (1.0/172800.0)
// One-based array of days in year at month start
static int rgMonthDays[13] =
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
static BOOL OleDateFromTm(WORD wYear, WORD wMonth, WORD wDay,
WORD wHour, WORD wMinute, WORD wSecond, DATE& dtDest);
static BOOL TmFromOleDate(DATE dtSrc, struct tm& tmDest);
static void TmConvertToStandardFormat(struct tm& tmSrc);
static double DoubleFromDate(DATE dt);
static DATE DateFromDouble(double dbl);
////////////////////////////////////////////////////////////////////////////
// CDateTime class
CDateTime::CDateTime()
{
m_dt=0;
SetStatus(invalid);
}
CDateTime::CDateTime(const CDateTime& dateSrc)
{
m_status=dateSrc.m_status;
m_dt=dateSrc.m_dt;
}
CDateTime::CDateTime(const VARIANT& varSrc)
{
if (varSrc.vt != VT_DATE)
{
_variant_t varTemp(varSrc);
varTemp.ChangeType(VT_DATE);
m_dt = varTemp.date;
}
else
{
m_dt = varSrc.date;
SetStatus(valid);
}
}
CDateTime::CDateTime(DATE dtSrc)
{
m_dt = dtSrc;
SetStatus(valid);
}
CDateTime::CDateTime(time_t& timeSrc)
{
// Convert time_t to struct tm
tm *ptm = localtime(&timeSrc);
if (ptm != NULL)
{
m_status = OleDateFromTm((WORD)(ptm->tm_year + 1900),
(WORD)(ptm->tm_mon + 1), (WORD)ptm->tm_mday,
(WORD)ptm->tm_hour, (WORD)ptm->tm_min,
(WORD)ptm->tm_sec, m_dt) ? valid : invalid;
}
else
{
// Local time must have failed (timsSrc before 1/1/70 12am)
m_dt=0;
SetStatus(invalid);
}
}
CDateTime::CDateTime(const SYSTEMTIME& systimeSrc)
{
m_status = OleDateFromTm(systimeSrc.wYear, systimeSrc.wMonth,
systimeSrc.wDay, systimeSrc.wHour, systimeSrc.wMinute,
systimeSrc.wSecond, m_dt) ? valid : invalid;
}
CDateTime::CDateTime(const FILETIME& filetimeSrc)
{
// Assume UTC FILETIME, so convert to LOCALTIME
FILETIME filetimeLocal;
if (!FileTimeToLocalFileTime( &filetimeSrc, &filetimeLocal))
{
m_status = invalid;
}
else
{
// Take advantage of SYSTEMTIME -> FILETIME conversion
SYSTEMTIME systime;
m_status = FileTimeToSystemTime(&filetimeLocal, &systime) ?
valid : invalid;
// At this point systime should always be valid, but...
if (GetStatus() == valid)
{
m_status = OleDateFromTm(systime.wYear, systime.wMonth,
systime.wDay, systime.wHour, systime.wMinute,
systime.wSecond, m_dt) ? valid : invalid;
}
}
}
/////
CDateTime PASCAL CDateTime::GetCurrentTime()
{
return CDateTime(::time(NULL));
}
int CDateTime::GetYear() const
{
struct tm tmTemp;
if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
return tmTemp.tm_year;
else
return AFX_OLE_DATETIME_ERROR;
}
int CDateTime::GetMonth() const
{
struct tm tmTemp;
if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
return tmTemp.tm_mon;
else
return AFX_OLE_DATETIME_ERROR;
}
int CDateTime::GetDay() const
{
struct tm tmTemp;
if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
return tmTemp.tm_mday;
else
return AFX_OLE_DATETIME_ERROR;
}
int CDateTime::GetHour() const
{
struct tm tmTemp;
if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
return tmTemp.tm_hour;
else
return AFX_OLE_DATETIME_ERROR;
}
int CDateTime::GetMinute() const
{
struct tm tmTemp;
if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
return tmTemp.tm_min;
else
return AFX_OLE_DATETIME_ERROR;
}
int CDateTime::GetSecond() const
{
struct tm tmTemp;
if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
return tmTemp.tm_sec;
else
return AFX_OLE_DATETIME_ERROR;
}
int CDateTime::GetDayOfWeek() const
{
struct tm tmTemp;
if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
return tmTemp.tm_wday;
else
return AFX_OLE_DATETIME_ERROR;
}
int CDateTime::GetDayOfYear() const
{
struct tm tmTemp;
if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
return tmTemp.tm_yday;
else
return AFX_OLE_DATETIME_ERROR;
}
const CDateTime& CDateTime::operator=(const VARIANT& varSrc)
{
if (varSrc.vt != VT_DATE)
{
_variant_t varTemp(varSrc);
varTemp.ChangeType(VT_DATE);
m_dt = varTemp.date;
}
else
{
m_dt = varSrc.date;
SetStatus(valid);
}
return *this;
}
const CDateTime& CDateTime::operator=(DATE dtSrc)
{
m_dt = dtSrc;
SetStatus(valid);
return *this;
}
const CDateTime& CDateTime::operator=(const time_t& timeSrc)
{
// Convert time_t to struct tm
tm *ptm = localtime(&timeSrc);
if (ptm != NULL)
{
m_status = OleDateFromTm((WORD)(ptm->tm_year + 1900),
(WORD)(ptm->tm_mon + 1), (WORD)ptm->tm_mday,
(WORD)ptm->tm_hour, (WORD)ptm->tm_min,
(WORD)ptm->tm_sec, m_dt) ? valid : invalid;
}
else
{
// Local time must have failed (timsSrc before 1/1/70 12am)
}
return *this;
}
const CDateTime& CDateTime::operator=(const SYSTEMTIME& systimeSrc)
{
m_status = OleDateFromTm(systimeSrc.wYear, systimeSrc.wMonth,
systimeSrc.wDay, systimeSrc.wHour, systimeSrc.wMinute,
systimeSrc.wSecond, m_dt) ? valid : invalid;
return *this;
}
const CDateTime& CDateTime::operator=(const FILETIME& filetimeSrc)
{
// Assume UTC FILETIME, so convert to LOCALTIME
FILETIME filetimeLocal;
if (!FileTimeToLocalFileTime( &filetimeSrc, &filetimeLocal))
{
m_status = invalid;
}
else
{
// Take advantage of SYSTEMTIME -> FILETIME conversion
SYSTEMTIME systime;
m_status = FileTimeToSystemTime(&filetimeLocal, &systime) ?
valid : invalid;
// At this point systime should always be valid, but...
if (GetStatus() == valid)
{
m_status = OleDateFromTm(systime.wYear, systime.wMonth,
systime.wDay, systime.wHour, systime.wMinute,
systime.wSecond, m_dt) ? valid : invalid;
}
}
return *this;
}
BOOL CDateTime::operator<(const CDateTime& date) const
{
//ASSERT(GetStatus() == valid);
//ASSERT(date.GetStatus() == valid);
// Handle negative dates
return DoubleFromDate(m_dt) < DoubleFromDate(date.m_dt);
}
BOOL CDateTime::operator>(const CDateTime& date) const
{ //ASSERT(GetStatus() == valid);
//ASSERT(date.GetStatus() == valid);
// Handle negative dates
return DoubleFromDate(m_dt) > DoubleFromDate(date.m_dt);
}
BOOL CDateTime::operator<=(const CDateTime& date) const
{
//ASSERT(GetStatus() == valid);
//ASSERT(date.GetStatus() == valid);
// Handle negative dates
return DoubleFromDate(m_dt) <= DoubleFromDate(date.m_dt);
}
BOOL CDateTime::operator>=(const CDateTime& date) const
{
//ASSERT(GetStatus() == valid);
//ASSERT(date.GetStatus() == valid);
// Handle negative dates
return DoubleFromDate(m_dt) >= DoubleFromDate(date.m_dt);
}
CDateTime CDateTime::operator+(const CDateTimeSpan& dateSpan) const
{
CDateTime dateResult; // Initializes m_status to valid
// If either operand NULL, result NULL
if (GetStatus() == null || dateSpan.GetStatus() == null)
{
dateResult.SetStatus(null);
return dateResult;
}
// If either operand invalid, result invalid
if (GetStatus() == invalid || dateSpan.GetStatus() == invalid)
{
dateResult.SetStatus(invalid);
return dateResult;
}
// Compute the actual date difference by adding underlying dates
dateResult = DateFromDouble(DoubleFromDate(m_dt) + dateSpan.m_span);
// Validate within range
dateResult.CheckRange();
return dateResult;
}
CDateTime CDateTime::operator-(const CDateTimeSpan& dateSpan) const
{
CDateTime dateResult; // Initializes m_status to valid
// If either operand NULL, result NULL
if (GetStatus() == null || dateSpan.GetStatus() == null)
{
dateResult.SetStatus(null);
return dateResult;
}
// If either operand invalid, result invalid
if (GetStatus() == invalid || dateSpan.GetStatus() == invalid)
{
dateResult.SetStatus(invalid);
return dateResult;
}
// Compute the actual date difference by subtracting underlying dates
dateResult = DateFromDouble(DoubleFromDate(m_dt) - dateSpan.m_span);
// Validate within range
dateResult.CheckRange();
return dateResult;
}
CDateTimeSpan CDateTime::operator-(const CDateTime& date) const
{
CDateTimeSpan spanResult;
// If either operand NULL, result NULL
if (GetStatus() == null || date.GetStatus() == null)
{
spanResult.SetStatus(CDateTimeSpan::null);
return spanResult;
}
// If either operand invalid, result invalid
if (GetStatus() == invalid || date.GetStatus() == invalid)
{
spanResult.SetStatus(CDateTimeSpan::invalid);
return spanResult;
}
// Return result (span can't be invalid, so don't check range)
return DoubleFromDate(m_dt) - DoubleFromDate(date.m_dt);
}
int CDateTime::SetDateTime(int nYear, int nMonth, int nDay,
int nHour, int nMin, int nSec)
{
return m_status = OleDateFromTm((WORD)nYear, (WORD)nMonth,
(WORD)nDay, (WORD)nHour, (WORD)nMin, (WORD)nSec, m_dt) ?
valid : invalid;
}
BOOL CDateTime::ParseDateTime(LPCTSTR lpszDate, DWORD dwFlags, LCID
lcid)
{
USES_CONVERSION;
//CString strDate = lpszDate;
SCODE sc;
if (FAILED(sc = VarDateFromStr((LPOLESTR)T2COLE(lpszDate), lcid,
dwFlags, &m_dt)))
{
if (sc == DISP_E_TYPEMISMATCH)
{
// Can't convert string to date, set 0 and invalidate
m_dt = 0;
SetStatus(invalid);
return FALSE;
}
else if (sc == DISP_E_OVERFLOW)
{
// Can't convert string to date, set -1 and invalidate
m_dt = -1;
SetStatus(invalid);
return FALSE;
}
else
{
// TRACE0("\nCDateTime VarDateFromStr call failed.\n\t");
// if (sc == E_OUTOFMEMORY)
// AfxThrowMemoryException();
// else
// AfxThrowOleException(sc);
m_dt=0;
SetStatus(invalid);
return FALSE;
}
}
SetStatus(valid);
return TRUE;
}
_bstr_t CDateTime::Format(DWORD dwFlags, LCID lcid) const
{
USES_CONVERSION;
_bstr_t strDate;
// If null, return empty string
if (GetStatus() == null)
return strDate;
// If invalid, return DateTime resource string
if (GetStatus() == invalid)
{
// VERIFY(strDate.LoadString(AFX_IDS_INVALID_DATETIME));
return strDate;
}
_variant_t var;
// Don't need to trap error. Should not fail due to type mismatch
VarBstrFromDate(m_dt, lcid, dwFlags, &V_BSTR(&var));
var.vt = VT_BSTR;
return V_BSTR(&var);
}
_bstr_t CDateTime::Format(LPCTSTR pFormat) const
{
_bstr_t strDate;
struct tm tmTemp;
// If null, return empty string
if (GetStatus() == null)
return strDate;
// If invalid, return DateTime resource string
if (GetStatus() == invalid || !TmFromOleDate(m_dt, tmTemp))
{
// VERIFY(strDate.LoadString(AFX_IDS_INVALID_DATETIME));
return strDate;
}
// Convert tm from afx internal format to standard format
TmConvertToStandardFormat(tmTemp);
// Fill in the buffer, disregard return value as it's not necessary
LPTSTR lpszTemp = new TCHAR[MAX_TIME_BUFFER_SIZE];
_tcsftime(lpszTemp, MAX_TIME_BUFFER_SIZE , pFormat, &tmTemp);
strDate=lpszTemp;
delete [] lpszTemp;
return strDate;
}
/*
CComString CDateTime::Format(UINT nFormatID) const
{
CComString strFormat;
strFormat.LoadString(nFormatID);
return Format(strFormat);
}
*/
void CDateTime::CheckRange()
{
if (m_dt > MAX_DATE || m_dt < MIN_DATE) // about year 100 to about 9999
SetStatus(invalid);
}
////////////////////////////////////////////////////////////////////////////
// CDateTimeSpan class helpers
#define MAX_DAYS_IN_SPAN 3615897L
////////////////////////////////////////////////////////////////////////////
// CDateTimeSpan class
CDateTimeSpan::CDateTimeSpan()
{
m_span=0;
SetStatus(invalid);
}
CDateTimeSpan::CDateTimeSpan(double dblSpanSrc)
{
m_span = dblSpanSrc;
SetStatus(valid);
}
CDateTimeSpan::CDateTimeSpan(const CDateTimeSpan& dateSpanSrc)
{
m_span = dateSpanSrc.m_span;
m_status = dateSpanSrc.m_status;
}
long CDateTimeSpan::GetHours() const
{
// ASSERT(GetStatus() == valid);
double dblTemp;
// Truncate days and scale up
dblTemp = modf(m_span, &dblTemp);
return (long)(dblTemp * 24);
}
long CDateTimeSpan::GetMinutes() const
{
// ASSERT(GetStatus() == valid);
double dblTemp;
// Truncate hours and scale up
dblTemp = modf(m_span * 24, &dblTemp);
return (long)(dblTemp * 60);
}
long CDateTimeSpan::GetSeconds() const
{
// ASSERT(GetStatus() == valid);
double dblTemp;
// Truncate minutes and scale up
dblTemp = modf(m_span * 24 * 60, &dblTemp);
return (long)(dblTemp * 60);
}
const CDateTimeSpan& CDateTimeSpan::operator=(double dblSpanSrc)
{
m_span = dblSpanSrc;
SetStatus(valid);
return *this;
}
const CDateTimeSpan& CDateTimeSpan::operator=(const CDateTimeSpan&
dateSpanSrc)
{
m_span = dateSpanSrc.m_span;
m_status = dateSpanSrc.m_status;
return *this;
}
CDateTimeSpan CDateTimeSpan::operator+(const CDateTimeSpan& dateSpan)
const
{
CDateTimeSpan dateSpanTemp;
// If either operand Null, result Null
if (GetStatus() == null || dateSpan.GetStatus() == null)
{
dateSpanTemp.SetStatus(null);
return dateSpanTemp;
}
// If either operand Invalid, result Invalid
if (GetStatus() == invalid || dateSpan.GetStatus() == invalid)
{
dateSpanTemp.SetStatus(invalid);
return dateSpanTemp;
}
// Add spans and validate within legal range
dateSpanTemp.m_span = m_span + dateSpan.m_span;
dateSpanTemp.CheckRange();
return dateSpanTemp;
}
CDateTimeSpan CDateTimeSpan::operator-(const CDateTimeSpan& dateSpan)
const
{
CDateTimeSpan dateSpanTemp;
// If either operand Null, result Null
if (GetStatus() == null || dateSpan.GetStatus() == null)
{
dateSpanTemp.SetStatus(null);
return dateSpanTemp;
}
// If either operand Invalid, result Invalid
if (GetStatus() == invalid || dateSpan.GetStatus() == invalid)
{
dateSpanTemp.SetStatus(invalid);
return dateSpanTemp;
}
// Subtract spans and validate within legal range
dateSpanTemp.m_span = m_span - dateSpan.m_span;
dateSpanTemp.CheckRange();
return dateSpanTemp;
}
void CDateTimeSpan::SetDateTimeSpan(
long lDays, int nHours, int nMins, int nSecs)
{
// Set date span by breaking into fractional days (all input ranges
valid)
m_span = lDays + ((double)nHours)/24 + ((double)nMins)/(24*60) +
((double)nSecs)/(24*60*60);
SetStatus(valid);
}
_bstr_t CDateTimeSpan::Format(LPCTSTR pFormat) const
{
_bstr_t strSpan;
struct tm tmTemp;
// If null, return empty string
if (GetStatus() == null)
return strSpan;
// If invalid, return DateTimeSpan resource string
if (GetStatus() == invalid || !TmFromOleDate(m_span, tmTemp))
{
//VERIFY(strSpan.LoadString(AFX_IDS_INVALID_DATETIMESPAN));
return strSpan;
}
// Convert tm from afx internal format to standard format
TmConvertToStandardFormat(tmTemp);
// Fill in the buffer, disregard return value as it's not necessary
LPTSTR lpszTemp = new TCHAR[MAX_TIME_BUFFER_SIZE];
_tcsftime(lpszTemp, MAX_TIME_BUFFER_SIZE, pFormat, &tmTemp);
strSpan=lpszTemp;
delete [] lpszTemp;
return strSpan;
}
/*
CComString CDateTimeSpan::Format(UINT nFormatID) const
{
CComString strFormat;
strFormat.LoadString(nFormatID);
return Format(strFormat);
}
*/
void CDateTimeSpan::CheckRange()
{
if(m_span < -MAX_DAYS_IN_SPAN || m_span > MAX_DAYS_IN_SPAN)
SetStatus(invalid);
}
////////////////////////////////////////////////////////////////////////////
// CDateTime class HELPERS - implementation
BOOL OleDateFromTm(WORD wYear, WORD wMonth, WORD wDay,
WORD wHour, WORD wMinute, WORD wSecond, DATE& dtDest)
{
// Validate year and month (ignore day of week and milliseconds)
if (wYear > 9999 || wMonth < 1 || wMonth > 12)
return FALSE;
// Check for leap year and set the number of days in the month
BOOL bLeapYear = ((wYear & 3) == 0) &&
((wYear % 100) != 0 || (wYear % 400) == 0);
int nDaysInMonth =
rgMonthDays[wMonth] - rgMonthDays[wMonth-1] +
((bLeapYear && wDay == 29 && wMonth == 2) ? 1 : 0);
// Finish validating the date
if (wDay < 1 || wDay > nDaysInMonth ||
wHour > 23 || wMinute > 59 ||
wSecond > 59)
{
return FALSE;
}
// Cache the date in days and time in fractional days
long nDate;
double dblTime;
//It is a valid date; make Jan 1, 1AD be 1
nDate = wYear*365L + wYear/4 - wYear/100 + wYear/400 +
rgMonthDays[wMonth-1] + wDay;
// If leap year and it's before March, subtract 1:
if (wMonth <= 2 && bLeapYear)
--nDate;
// Offset so that 12/30/1899 is 0
nDate -= 693959L;
dblTime = (((long)wHour * 3600L) + // hrs in seconds
((long)wMinute * 60L) + // mins in seconds
((long)wSecond)) / 86400.;
dtDest = (double) nDate + ((nDate >= 0) ? dblTime : -dblTime);
return TRUE;
}
BOOL TmFromOleDate(DATE dtSrc, struct tm& tmDest)
{
// The legal range does not actually span year 0 to 9999.
if (dtSrc > MAX_DATE || dtSrc < MIN_DATE) // about year 100 to about
9999
return FALSE;
long nDays; // Number of days since Dec. 30, 1899
long nDaysAbsolute; // Number of days since 1/1/0
long nSecsInDay; // Time in seconds since midnight
long nMinutesInDay; // Minutes in day
long n400Years; // Number of 400 year increments since 1/1/0
long n400Century; // Century within 400 year block (0,1,2 or 3)
long n4Years; // Number of 4 year increments since 1/1/0
long n4Day; // Day within 4 year block
// (0 is 1/1/yr1, 1460 is 12/31/yr4)
long n4Yr; // Year within 4 year block (0,1,2 or 3)
BOOL bLeap4 = TRUE; // TRUE if 4 year block includes leap year
double dblDate = dtSrc; // tempory serial date
// If a valid date, then this conversion should not overflow
nDays = (long)dblDate;
// Round to the second
dblDate += ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND);
nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to
12/30/1899
dblDate = fabs(dblDate);
nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.);
// Calculate the day of week (sun=1, mon=2...)
// -1 because 1/1/0 is Sat. +1 because we want 1-based
tmDest.tm_wday = (int)((nDaysAbsolute - 1) % 7L) + 1;
// Leap years every 4 yrs except centuries not multiples of 400.
n400Years = (long)(nDaysAbsolute / 146097L);
// Set nDaysAbsolute to day within 400-year block
nDaysAbsolute %= 146097L;
// -1 because first century has extra day
n400Century = (long)((nDaysAbsolute - 1) / 36524L);
// Non-leap century
if (n400Century != 0)
{
// Set nDaysAbsolute to day within century
nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;
// +1 because 1st 4 year increment has 1460 days
n4Years = (long)((nDaysAbsolute + 1) / 1461L);
if (n4Years != 0)
n4Day = (long)((nDaysAbsolute + 1) % 1461L);
else
{
bLeap4 = FALSE;
n4Day = (long)nDaysAbsolute;
}
}
else
{
// Leap century - not special case!
n4Years = (long)(nDaysAbsolute / 1461L);
n4Day = (long)(nDaysAbsolute % 1461L);
}
if (bLeap4)
{
// -1 because first year has 366 days
n4Yr = (n4Day - 1) / 365;
if (n4Yr != 0)
n4Day = (n4Day - 1) % 365;
}
else
{
n4Yr = n4Day / 365;
n4Day %= 365;
}
// n4Day is now 0-based day of year. Save 1-based day of year, year
number
tmDest.tm_yday = (int)n4Day + 1;
tmDest.tm_year = n400Years * 400 + n400Century * 100 + n4Years * 4 +
n4Yr;
// Handle leap year: before, on, and after Feb. 29.
if (n4Yr == 0 && bLeap4)
{
// Leap Year
if (n4Day == 59)
{
/* Feb. 29 */
tmDest.tm_mon = 2;
tmDest.tm_mday = 29;
goto DoTime;
}
// Pretend it's not a leap year for month/day comp.
if (n4Day >= 60)
--n4Day;
}
// Make n4DaY a 1-based day of non-leap year and compute
// month/day for everything but Feb. 29.
++n4Day;
// Month number always >= n/32, so save some loop time */
for (tmDest.tm_mon = (n4Day >> 5) + 1;
n4Day > rgMonthDays[tmDest.tm_mon]; tmDest.tm_mon++);
tmDest.tm_mday = (int)(n4Day - rgMonthDays[tmDest.tm_mon-1]);
DoTime:
if (nSecsInDay == 0)
tmDest.tm_hour = tmDest.tm_min = tmDest.tm_sec = 0;
else
{
tmDest.tm_sec = (int)nSecsInDay % 60L;
nMinutesInDay = nSecsInDay / 60L;
tmDest.tm_min = (int)nMinutesInDay % 60;
tmDest.tm_hour = (int)nMinutesInDay / 60;
}
return TRUE;
}
void TmConvertToStandardFormat(struct tm& tmSrc)
{
// Convert afx internal tm to format expected by runtimes (_tcsftime,
etc)
tmSrc.tm_year -= 1900; // year is based on 1900
tmSrc.tm_mon -= 1; // month of year is 0-based
tmSrc.tm_wday -= 1; // day of week is 0-based
tmSrc.tm_yday -= 1; // day of year is 0-based
}
double DoubleFromDate(DATE dt)
{
// No problem if positive
if (dt >= 0)
return dt;
// If negative, must convert since negative dates not continuous
// (examples: -1.25 to -.75, -1.50 to -.50, -1.75 to -.25)
double temp = ceil(dt);
return temp - (dt - temp);
}
DATE DateFromDouble(double dbl)
{
// No problem if positive
if (dbl >= 0)
return dbl;
// If negative, must convert since negative dates not continuous
// (examples: -.75 to -1.25, -.50 to -1.50, -.25 to -1.75)
double temp = floor(dbl); // dbl is now whole part
return temp + (temp - dbl);
}

Comments
Included in VS.Net
Posted by Legacy on 07/07/2003 12:00amOriginally posted by: twaltari
COleDateTime is included in ATL since Visual Studio .Net. #include <atlcomtime.h>
ReplyQuestion
Posted by Legacy on 10/07/2002 12:00amOriginally posted by: Sangoi
Whats the use of implemating such huge code... instead of using ready made COleDateTime?
ReplyWhat is implemented differently in this class
Posted by Legacy on 07/10/2001 12:00amOriginally posted by: Chan Jo
Hi
I looked at the class CDateTime. Except for few minor
Replychanges, I think class was identical to COleDateTime.
Is this correct?
implementation for GetTotalSeconds, GetTotalMinutes, GetTotalHours, GetTotalDays????
Posted by Legacy on 05/09/2001 12:00amOriginally posted by: Christian Cheney
I went to link my library only to find out that there is no implementation for these functions????
ReplyWhere is the SetTime and SetDate implementation?
Posted by Legacy on 10/12/2000 12:00amOriginally posted by: Sean Jorden
.
Reply#include statements in header have no filenames
Posted by Legacy on 04/03/2000 12:00amOriginally posted by: James Edgell
3 #include statements in the header have no filenames listed after them.
Looks like:
#include
#include
Reply#include
DateTime.cpp
Posted by Legacy on 04/15/1999 12:00amOriginally posted by: Roger L. Mcelfresh
I tried to compile this using VC 6.0 and got 102 errors because the tab code was not "09" but was "0A0". Was wondering if this was developed on some other compile?
Reply