Click here to Skip to main content
15,892,674 members
Articles / Desktop Programming / ATL

Non-MFC Date Routines in ATL

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
8 Sep 2000 58.3K   963   34  
Non-MFC Date Routines in an ATL Component.
// Date.cpp : implementation file
//
// IDate Implementation
//
// Written by Paul E. Bible <pbible@littlefishsoftware.com>
// Copyright (c) 2000. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name and all copyright 
// notices remains intact. If the source code in this file is used in 
// any  commercial application then a statement along the lines of 
// "Portions copyright (c) Paul E. Bible, 2000" must be included in
// the startup banner, "About" box -OR- printed documentation. An email 
// letting me know that you are using it would be nice as well. That's 
// not much to ask considering the amount of work that went into this.
// If even this small restriction is a problem send me an email.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// Expect bugs!
// 
// Please use and enjoy, and let me know of any bugs/mods/improvements 
// that you have found/implemented and I will fix/incorporate them into 
// this file. 
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DateLib.h"
#include "Date.h"
#include <stdio.h>

/////////////////////////////////////////////////////////////////////////////
// CDate Error Handling
//

STDMETHODIMP CDate::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IDate
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}


/////////////////////////////////////////////////////////////////////////////
// CDate Private Methods
//

BOOL CDate::IsLeapYear(const int &nYear)
{
	return ((nYear % 4 == 0 && nYear % 100 != 0) || (nYear % 400 == 0)) ? TRUE : FALSE;
}

void CDate::GetMonthString(const int &nMonth, TCHAR *pszMonth)
{
	switch(nMonth)
	{
		case 1:	_tcscpy(pszMonth, _T("Jan")); return;
		case 2:	_tcscpy(pszMonth, _T("Feb")); return;
		case 3:	_tcscpy(pszMonth, _T("Mar")); return;
		case 4:	_tcscpy(pszMonth, _T("Apr")); return;
		case 5:	_tcscpy(pszMonth, _T("May")); return;
		case 6:	_tcscpy(pszMonth, _T("Jun")); return;
		case 7:	_tcscpy(pszMonth, _T("Jul")); return;
		case 8:	_tcscpy(pszMonth, _T("Aug")); return;
		case 9:	_tcscpy(pszMonth, _T("Sep")); return;
		case 10: _tcscpy(pszMonth, _T("Oct")); return;
		case 11: _tcscpy(pszMonth, _T("Nov")); return;
		case 12: _tcscpy(pszMonth, _T("Dec")); return;
		default: _tcscpy(pszMonth, _T("Unk")); return;
	}
}


/////////////////////////////////////////////////////////////////////////////
// CDate Conversion Methods (Public)
//

STDMETHODIMP CDate::Now(DATE *pdtDate)
{
	SYSTEMTIME stDate;
	GetLocalTime(&stDate);
	DATE dtDate;
	if (SystemTimeToVariantTime(&stDate, &dtDate) == 0)
		return Error("Conversion Error - IDate::Now");
	*pdtDate = dtDate;
	return S_OK;
}

STDMETHODIMP CDate::OLE2Oracle(DATE dtDate, BSTR *pbstrDate)
{
	USES_CONVERSION;
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error - IDate::OLE2Oracle");
	
	int nMonth = static_cast<int>(stDate.wMonth);
	TCHAR szMonth[4];
	GetMonthString(nMonth, szMonth);

	TCHAR szDate[15];
	_stprintf(szDate, _T("%.2d-%s-%.4d"), static_cast<int>(stDate.wDay),
										  szMonth,
										  static_cast<int>(stDate.wYear));
	CComBSTR bstrNew = szDate;
	*pbstrDate = bstrNew.Detach();
	return S_OK;
}

STDMETHODIMP CDate::Int2Oracle(short nMonth, short nDay, short nYear, BSTR *pbstrDate)
{
	TCHAR szMonth[4];
	GetMonthString(nMonth, szMonth);

	TCHAR szDate[15];
	_stprintf(szDate, _T("%.2d-%s-%.4d"), nDay, szMonth, nYear);
	CComBSTR bstrNew = szDate;
	*pbstrDate = bstrNew.Detach();
	return S_OK;
}

STDMETHODIMP CDate::Int2OLE(short nMonth, short nDay, short nYear, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	stDate.wDay		= static_cast<WORD>(nDay);
	stDate.wMonth	= static_cast<WORD>(nMonth);
	stDate.wYear	= static_cast<WORD>(nYear);
	stDate.wHour	= 0;
	stDate.wMinute	= 0;
	stDate.wSecond	= 1;

	DATE dtDate;
	if (SystemTimeToVariantTime(&stDate, &dtDate) == 0)
		return Error("Conversion Error - IDate::Int2OLE");
	*pdtDate = dtDate;
	return S_OK;
}


/////////////////////////////////////////////////////////////////////////////
// CDate Calculation Methods (Public)
//

STDMETHODIMP CDate::GetLastDay(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetLastDay");
	int nMonth  = static_cast<int>(stDate.wMonth);
	int nYear	= static_cast<int>(stDate.wYear);
	int nDay	= 0;

	// Calculate the last day of the month
	switch (nMonth)
	{
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			nDay = 31;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			nDay = 30;
			break;
		case 2:
			if (IsLeapYear(nYear))
				nDay = 29;
			else
				nDay = 28;
			break;
	}

	// Update SYSTEMTIME variable
	stDate.wDay = static_cast<WORD>(nDay);
	stDate.wHour = 0;
	stDate.wMinute = 0;
	stDate.wSecond = 0;
	stDate.wMilliseconds = 1;

	// Calc and assign new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (2) - IDate::GetLastDay");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetFirstDay(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetFirstDay");
	stDate.wDay = static_cast<WORD>(1);
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (2) - IDate::GetFirstDay");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetPreviousDay(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetPreviousDay");
	
	// Adjust day (and month/year)
	if (stDate.wDay == 1)
	{
		stDate.wMonth--;
		if (stDate.wMonth < 1)
		{
			stDate.wMonth = 12;
			stDate.wYear--;
		}

		// Get the last day of the previous month
		DATE dtCheck;
		if (FAILED(Int2OLE(static_cast<short>(stDate.wMonth), 1, static_cast<short>(stDate.wYear), &dtCheck)))
			return Error("Int2OLE failed in IDate::GetPreviousDay");
		DATE dtLast;
		if (FAILED(GetLastDay(dtCheck, &dtLast)))
			return Error("GetLastDay failed in IDate::GetPreviousDay");
		SYSTEMTIME stCheck;
		if (FALSE == VariantTimeToSystemTime(dtLast, &stCheck))
			return Error("Conversion Error (2) - IDate::GetPreviousDay");
		stDate.wDay = stCheck.wDay;
	}
	else
		stDate.wDay--;

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (3) - IDate::GetPreviousDay");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetPreviousWeek(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetPreviousWeek");
	
	// Adjust day (and month/year)
	if (stDate.wDay <= 7)
	{
		int nDiff = 7 - static_cast<int>(stDate.wDay);

		stDate.wMonth--;
		if (stDate.wMonth < 1)
		{
			stDate.wMonth = 12;
			stDate.wYear--;
		}

		// Check for month-end exceeded
		DATE dtCheck;
		if (FAILED(Int2OLE(static_cast<short>(stDate.wMonth), 1, static_cast<short>(stDate.wYear), &dtCheck)))
			return Error("Int2OLE failed in IDate::GetPreviousWeek");
		DATE dtLast;
		if (FAILED(GetLastDay(dtCheck, &dtLast)))
			return Error("GetLastDay failed in IDate::GetPreviousWeek");
		SYSTEMTIME stCheck;
		if (FALSE == VariantTimeToSystemTime(dtLast, &stCheck))
			return Error("Conversion Error (2) - IDate::GetPreviousWeek");
		stDate.wDay = stCheck.wDay - nDiff;
	}
	else
		stDate.wDay = stDate.wDay - 7;

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (3) - IDate::GetPreviousDay");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetPreviousMonth(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetPreviousMonth");
	
	// Adjust month (and year)
	if (stDate.wMonth == 1)
	{
		stDate.wMonth = 12;
		stDate.wYear--;
	}
	else
		stDate.wMonth--;

	// Check for month-end exceeded
	DATE dtCheck;
	if (FAILED(Int2OLE(static_cast<short>(stDate.wMonth), 1, static_cast<short>(stDate.wYear), &dtCheck)))
		return Error("Int2OLE failed in IDate::GetPreviousMonth");
	DATE dtLast;
	if (FAILED(GetLastDay(dtCheck, &dtLast)))
		return Error("GetLastDay failed in IDate::GetPreviousMonth");
	SYSTEMTIME stCheck;
	if (FALSE == VariantTimeToSystemTime(dtLast, &stCheck))
		return Error("Conversion Error (2) - IDate::GetPreviousMonth");
	if (stDate.wDay > stCheck.wDay)
		stDate.wDay = stCheck.wDay;

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (3) - IDate::GetPreviousMonth");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetPreviousYear(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetPreviousYear");
	
	// Adjust the year
	stDate.wYear--;

	// Check for month-end exceeded
	DATE dtCheck;
	if (FAILED(Int2OLE(static_cast<short>(stDate.wMonth), 1, static_cast<short>(stDate.wYear), &dtCheck)))
		return Error("Int2OLE failed in IDate::GetPreviousYear");
	DATE dtLast;
	if (FAILED(GetLastDay(dtCheck, &dtLast)))
		return Error("GetLastDay failed in IDate::GetPreviousYear");
	SYSTEMTIME stCheck;
	if (FALSE == VariantTimeToSystemTime(dtLast, &stCheck))
		return Error("Conversion Error (2) - IDate::GetPreviousYear");
	if (stDate.wDay > stCheck.wDay)
		stDate.wDay = stCheck.wDay;

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (3) - IDate::GetPreviousYear");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetNextMonth(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetNextMonth");
	
	// Adjust month (and year)
	if (stDate.wMonth == 12)
	{
		stDate.wMonth = 1;
		stDate.wYear++;
	}
	else
		stDate.wMonth++;

	// Check for month-end exceeded
	DATE dtCheck;
	if (FAILED(Int2OLE(static_cast<short>(stDate.wMonth), 1, static_cast<short>(stDate.wYear), &dtCheck)))
		return Error("Int2OLE failed in IDate::GetNextMonth");
	DATE dtLast;
	if (FAILED(GetLastDay(dtCheck, &dtLast)))
		return Error("GetLastDay failed in IDate::GetNextMonth");
	SYSTEMTIME stCheck;
	if (FALSE == VariantTimeToSystemTime(dtLast, &stCheck))
		return Error("Conversion Error (2) - IDate::GetNextMonth");
	if (stDate.wDay > stCheck.wDay)
		stDate.wDay = stCheck.wDay;

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (3) - IDate::GetNextMonth");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetNextDay(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetNextDay");
	DATE dtLastDay;
	if (FAILED(GetLastDay(dtDate, &dtLastDay)))
		return Error("GetLastDay failed in IDate::GetNextDay");

	// Increment the day
	stDate.wDay++;
	SYSTEMTIME stLastDay;
	if (FALSE == VariantTimeToSystemTime(dtLastDay, &stLastDay))
		return Error("Conversion Error (2) - IDate::GetNextDay");

	// Check if past month-end
	if (stDate.wDay > stLastDay.wDay)
	{
		stDate.wDay = 1;
		stDate.wMonth++;
		if (stDate.wMonth == 13)
		{
			stDate.wMonth = 1;
			stDate.wYear++;
		}
	}

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (3) - IDate::GetNextDay");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetNextYear(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetNextYear");
	
	// Adjust year
	stDate.wYear++;

	// Check for leap year and adjust day (if necessary)
	if (!IsLeapYear(static_cast<int>(stDate.wYear)))
	{
		if ((stDate.wMonth == 2) && (stDate.wDay == 29))
			stDate.wDay--;
	}

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (2) - IDate::GetNextYear");
	*pdtDate = dtNew;
	return S_OK;
}

STDMETHODIMP CDate::GetNextWeek(DATE dtDate, DATE *pdtDate)
{
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error (1) - IDate::GetNextWeek");
	DATE dtLastDay;
	if (FAILED(GetLastDay(dtDate, &dtLastDay)))
		return Error("GetLastDay failed in IDate::GetNextWeek");

	// Increment the day by 7
	stDate.wDay = stDate.wDay + 7;
	SYSTEMTIME stLastDay;
	if (FALSE == VariantTimeToSystemTime(dtLastDay, &stLastDay))
		return Error("Conversion Error (2) - IDate::GetNextWeek");

	// Check if past month-end
	if (stDate.wDay > stLastDay.wDay)
	{
		WORD wDiff = stDate.wDay - stLastDay.wDay;

		stDate.wDay = wDiff;
		stDate.wMonth++;
		if (stDate.wMonth == 13)
		{
			stDate.wMonth = 1;
			stDate.wYear++;
		}
	}

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error (3) - IDate::GetNextWeek");
	*pdtDate = dtNew;
	return S_OK;
}


/////////////////////////////////////////////////////////////////////////////
// CDate Parsing Methods (Public)
//

STDMETHODIMP CDate::ParseOracle2OLE(BSTR bstrDate, DATE *pdtDate)
{
	USES_CONVERSION;

	// Extract the string
	const TCHAR* pszDate = OLE2T(bstrDate);
	int nLength = _tcslen(pszDate);
	TCHAR* pszResult;
	pszResult = new TCHAR[15];

	// Extract the month
	TCHAR *pDest1;
	pDest1 = _tcsstr(pszDate, _T("/"));
	if (pDest1 == NULL)
		return E_FAIL;
	int nPos1 = pDest1 - pszDate + 1;
	memset(pszResult, '\0', 15 * sizeof(TCHAR));
	_tcsncpy(pszResult, &pszDate[0], nPos1-1);
	int nMonth = _ttoi(pszResult);
	
	// Extract the day
	TCHAR *pDest2;
	pDest2 = _tcsstr(&pszDate[nPos1], _T("/"));
	if (pDest2 == NULL)
		return E_FAIL;
	int nPos2 = pDest2 - pszDate;
	memset(pszResult, '\0', 15 * sizeof(TCHAR));
	_tcsncpy(pszResult, &pszDate[nPos1], nPos2-nPos1);
	int nDay = _ttoi(pszResult);

	// Extract the year
	memset(pszResult, '\0', 15 * sizeof(TCHAR));
	_tcsncpy(pszResult, pDest2+1, nLength - nPos2);
	int nYear = _ttoi(pszResult);
	if (nYear < 1900)
	{
		if (nYear > 50)
			nYear += 1900;
		else
			nYear += 2000;
	}

	// Build the DATE
	SYSTEMTIME stDate;
	GetSystemTime(&stDate);
	stDate.wDay		= static_cast<WORD>(nDay);	
	stDate.wMonth	= static_cast<WORD>(nMonth);	
	stDate.wYear	= static_cast<WORD>(nYear);	

	// Assign the new date
	DATE dtNew;
	if (SystemTimeToVariantTime(&stDate, &dtNew) == 0)
		return Error("Conversion Error - IDate::ParseOracle2OLE");
	*pdtDate = dtNew;

	// Cleanup
	delete [] pszResult;
	return S_OK;
}

STDMETHODIMP CDate::ParseOracle2String(BSTR bstrDate, BSTR *pbstrDate)
{
	DATE dtNewDate;
	if (FAILED(ParseOracle2OLE(bstrDate, &dtNewDate)))
		return Error("ParseOracle2OLE failed in IDate::ParseOracle2String");
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtNewDate, &stDate))
		return Error("Conversion Error - IDate::ParseOracle2String");

	TCHAR* pszDate;
	pszDate = new TCHAR[15];
	memset(pszDate, '\0', 15 * sizeof(TCHAR));
	_stprintf(pszDate, _T("%.2d/%.2d/%.4d"), static_cast<int>(stDate.wMonth),
											 static_cast<int>(stDate.wDay),
											 static_cast<int>(stDate.wYear));

	// Assign the new date
	CComBSTR bstrNew = pszDate;
	*pbstrDate = bstrNew.Detach();

	// Cleanup
	delete [] pszDate;
	return S_OK;
}

STDMETHODIMP CDate::ParseOracle2Oracle(BSTR bstrDate, BSTR *pbstrDate)
{
	DATE dtNewDate;
	if (FAILED(ParseOracle2OLE(bstrDate, &dtNewDate)))
		return Error("ParseOracle2OLE failed in IDate::ParseOracle2Oracle");
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtNewDate, &stDate))
		return Error("Conversion Error - IDate::ParseOracle2Oracle");
	CComBSTR bstrNew;
	if (FAILED(Int2Oracle(static_cast<int>(stDate.wMonth), static_cast<int>(stDate.wDay), 
			   static_cast<int>(stDate.wYear), &bstrNew)))
		return Error("Int2Oracle failed in IDate::ParseOracle2Oracle");
	*pbstrDate = bstrNew.Detach();
	return S_OK;
}

STDMETHODIMP CDate::OLE2String(DATE dtDate, BSTR *pbstrDate)
{
	USES_CONVERSION;
	SYSTEMTIME stDate;
	if (FALSE == VariantTimeToSystemTime(dtDate, &stDate))
		return Error("Conversion Error - IDate::OLE2String");
	
	TCHAR* pszDate;
	pszDate = new TCHAR[15];
	memset(pszDate, '\0', 15 * sizeof(TCHAR));
	_stprintf(pszDate, _T("%.2d/%.2d/%.4d"), static_cast<int>(stDate.wMonth),
									 	     static_cast<int>(stDate.wDay),
										     static_cast<int>(stDate.wYear));

	// Assign the new date
	CComBSTR bstrNew = pszDate;
	*pbstrDate = bstrNew.Detach();

	// Cleanup
	delete [] pszDate;
	return S_OK;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United States United States
Eat, Sleep, Code, Bike. That about sums it up!!

Comments and Discussions