home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
PROG_C
/
DATECL.ZIP
/
DATECL.CPP
next >
Wrap
C/C++ Source or Header
|
1994-01-26
|
17KB
|
729 lines
/*
*┌──────────────────────────────────────────────────────────────────────
*│ File.........: DATECL.CPP
*│ Date.........: January 26, 1994
*│ Author.......: Ly Minh Tri, et al.
*│ Copyright....: None! Use freely.
*│ Version......: 4.9 Compile w/MSC++ 7.0 or Borland C++ 3.1
*│ Usage........: General purpose date conversion, arithmetic,
*│ : comparison, and formatting class
*│
*│ See DATECLS4.H for acknowledgements and compile/link notes.
*└──────────────────────────────────────────────────────────────────────
*/
#include "datecl.h"
#include "ctype.h"
int Date::DisplayFormat=Date::MDY;
unsigned int Date::startDST=((4<<8) + 1), Date::startSTD=((10<<8) + 31);
char Date::cbuf[Date::BUF_SIZE];
unsigned char Date::DisplayOptions='\0';
const char *dayname[] = {"Sunday","Monday","Tuesday","Wednesday",
"Thursday","Friday","Saturday"} ;
const char *mname[] = {"January","February","March","April","May",
"June","July","August","September","October","November","December"};
static int GauDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
////////////////////////////////////////////////////////////
// Constructors
////////////////////////////////////////////////////////////
Date::Date()
{
month = day = day_of_week = 0;
year = 0;
julian = 0;
}
Date::Date (long j) : julian(j)
{
julian_to_mdy ();
}
Date::Date (int m, int d, int y) : month((unsigned char)m), day((unsigned char)d), year(y)
{
mdy_to_julian ();
}
Date::Date (const char *dat)
{
#ifdef _MSC // Differentiate between Microsoft's
if (!_stricmp(dat, "TODAY")) // and Borland's compiler!
#else
if (!stricmp(dat, "TODAY"))
#endif
{
struct DOSDATE_T temp_date;
_dos_getdate(&temp_date);
month = temp_date.month;
day = temp_date.day;
year = temp_date.year;
}
else
{
char *tmp, *tmp2;
int nlen=strlen(dat), i, datetype;
tmp = new char[nlen+1];
//
// TML - We need to make a copy of 'dat' because strtok() modifies
// the content of its first parameter!!!
//
strcpy(tmp, dat);
//
// Possible date string formats are those that are generated by the
// Date class itself! The corresponding possible string lengths are
// also listed (with ranges from shortest to longest string for that
// format).
//
// MDY: 03/23/1993 => 6-10,13-17
// EUROPEAN: 23 March 1993 => 13, 20
// FULL,ABBR.: Tue, Mar 23, 1993 => 16-17, 23-24
// FULL: Tuesday, March 23, 1993 => 22-23, 29-30
//
// These dates may also have B.C.E. appended at the end, thus we have
// the second set of string lengths with 7 more characters!
//
if (isalpha(tmp[0]))
datetype = Date::FULL;
else if (nlen == 20)
datetype = Date::EUROPEAN;
else if (nlen == 13)
datetype = (isalpha(tmp[5]) ? Date::EUROPEAN : Date::MDY);
else
datetype = Date::MDY;
switch(datetype)
{
case Date::EUROPEAN:
day = (unsigned char)atoi(strtok(tmp," "));
tmp2 = strtok(NULL," ");
i = 0;
while (i < 12)
{
#ifdef _MSC
if (_stricmp(tmp2, mname[i++]) == 0)
#else
if (stricmp(tmp2, mname[i++]) == 0)
#endif
break;
}
month = (i <= 12) ? i : 0;
year = atoi(strtok(NULL," "));
break;
case Date::FULL:
strtok(tmp," "); // Skip the day info
tmp2 = strtok(NULL," "); // Get the month string
i = -1;
while (++i < 12)
{
if (toupper(tmp2[0]) == toupper(*(mname[i])) &&
toupper(tmp2[1]) == toupper(*(mname[i]+1)) &&
toupper(tmp2[2]) == toupper(*(mname[i]+2)))
break;
}
month = (i <= 12) ? ++i : 0;
day = atoi(strtok(NULL,","));
year = atoi(strtok(NULL," "));
break;
default:
month = (unsigned char)atoi(strtok(tmp,"/-"));
day = (unsigned char)atoi(strtok(NULL,"/-"));
year = atoi(strtok(NULL," "));
break;
}
//
// Convert B.C.E. year to proper value!
//
if (strtok(NULL, ".") != NULL)
year *= -1;
//
// Verify values!
//
if ((month < 1) || (month > 12) || (day < 1) || (day > (unsigned char) DaysInMonth()))
{
month = day = 0;
year = 0;
}
delete [] tmp;
}
mdy_to_julian ();
}
Date::Date (const DOSDATE_T &ds)
{
month = ds.month;
day = ds.day;
year = ds.year;
mdy_to_julian ();
}
Date::Date (const Date &dt)
{
month = dt.month;
day = dt.day;
year = dt.year;
mdy_to_julian ();
}
//////////////////////////////////////////////////////////////
// Conversion operations
//////////////////////////////////////////////////////////////
Date::operator char *( void )
{
formatDate();
return cbuf;
}
//////////////////////////////////////////////////////////////
// Date Arithmetic
//////////////////////////////////////////////////////////////
Date Date::operator + (long i)
{
return Date(julian + i);
}
Date Date::operator + (int i)
{
return Date(julian + (long)i);
}
Date Date::operator - (long i)
{
return Date(julian - i);
}
Date Date::operator - (int i)
{
return Date(julian - (long)i);
}
long Date::operator - (const Date &dt)
{
return ( julian - dt.julian );
}
const Date &Date::operator += (long i)
{
julian += i;
julian_to_mdy();
return *this;
}
const Date &Date::operator -= (long i)
{
julian -= i;
julian_to_mdy();
return *this;
}
Date Date::operator ++()
{
julian++;
julian_to_mdy();
return *this;
}
Date Date::operator ++(int)
{
Date temp=*this; // TML - Necessary to save current
// value of (*this) in order to
julian++; // simulate postfix operation!
julian_to_mdy();
return temp;
}
Date Date::operator --()
{
julian--;
julian_to_mdy();
return *this;
}
Date Date::operator --(int)
{
Date temp=*this; // TML - Necessary to save current
// value of (*this) in order to
julian--; // simulate postfix operation!
julian_to_mdy();
return temp;
}
//////////////////////////////////////////////////////////////
// Date comparison
//////////////////////////////////////////////////////////////
int Date::operator < (const Date &dt)
{
return ( julian < dt.julian );
}
int Date::operator <= (const Date &dt)
{
return ( (julian == dt.julian) || (julian < dt.julian) );
}
int Date::operator > (const Date &dt)
{
return ( julian > dt.julian );
}
int Date::operator >= (const Date &dt)
{
return ( (julian == dt.julian) || (julian > dt.julian) );
}
int Date::operator == (const Date &dt)
{
return ( julian == dt.julian );
}
int Date::operator != (const Date &dt)
{
return ( julian != dt.julian );
}
////////////////////////////////////////////////////////////////
// Ostream operations
////////////////////////////////////////////////////////////////
ostream &operator << (ostream &os, const Date &dt)
{
return os << dt.formatDate();
}
ostream &operator << (ostream &os, const DOSDATE_T &dt)
{
return os << (int)dt.month << "/" << (int)dt.day << "/" << dt.year;
}
//////////////////////////////////////////////////////////////
// Conversion routines
//////////////////////////////////////////////////////////////
void Date::julian_to_wday (void)
{
day_of_week = (unsigned char) ((julian + 2) % 7 + 1);
}
void Date::julian_to_mdy ()
{
long a,b,c,d,e,z,alpha;
z = julian+1;
// dealing with Gregorian calendar reform
if (z < 2299161L)
a = z;
else
{
alpha = (long) ((z-1867216.25) / 36524.25);
a = z + 1 + alpha - alpha/4;
}
b = ( a > 1721423 ? a + 1524 : a + 1158 );
c = (long) ((b - 122.1) / 365.25);
d = (long) (365.25 * c);
e = (long) ((b - d) / 30.6001);
day = (unsigned char)(b - d - (long)(30.6001 * e));
month = (unsigned char)((e < 13.5) ? e - 1 : e - 13);
year = (int)((month > 2.5 ) ? (c - 4716) : c - 4715);
julian_to_wday ();
}
void Date::mdy_to_julian (void)
{
int a,b=0;
int work_month=month, work_day=day, work_year=year;
// correct for negative year
if (work_year < 0)
work_year++;
if (work_month <= 2)
{
work_year--;
work_month +=12;
}
// deal with Gregorian calendar
if (work_year*10000. + work_month*100. + work_day >= 15821015.)
{
a = (int)(work_year/100.);
b = 2 - a + a/4;
}
julian = (long) (365.25*work_year) +
(long) (30.6001 * (work_month+1)) + work_day + 1720994L + b;
julian_to_wday ();
}
////////////////////////////////////////////////////////////////
// Format routine
////////////////////////////////////////////////////////////////
const char *Date::formatDate (int type) const
{
memset( cbuf, '\0', sizeof(cbuf) );
switch ( type )
{
case Date::DAY:
if ( (day_of_week < 1) || (day_of_week > 7) )
strcpy(cbuf,"invalid day");
else
strncpy( cbuf, dayname[day_of_week-1],
(DisplayOptions & Date::DATE_ABBR) ? ABBR_LENGTH : 9);
break;
case Date::MONTH:
if ( (month < 1) || (month > 12) )
strcpy(cbuf,"invalid month");
else
strncpy( cbuf, mname[month-1],
(DisplayOptions & Date::DATE_ABBR) ? ABBR_LENGTH : 9);
break;
case Date::FULL:
if ( (month < 1) || (month > 12) || (day_of_week < 1) ||
(day_of_week > 7) || (day < 1) )
{
strcpy(cbuf,"invalid date");
break;
}
strncpy( cbuf, dayname[day_of_week-1],
(DisplayOptions & Date::DATE_ABBR) ? ABBR_LENGTH : 9);
strcat( cbuf, ", ");
strncat( cbuf, mname[month-1],
(DisplayOptions & Date::DATE_ABBR) ? ABBR_LENGTH : 9);
sprintf( cbuf+strlen(cbuf), " %d, %d", day, abs(year) );
if (year < 0)
strcat(cbuf," B.C.E.");
break;
case Date::EUROPEAN:
if ( (month < 1) || (month > 12) || (day_of_week < 1) ||
(day_of_week > 7) || (day < 1) )
{
strcpy(cbuf,"invalid date");
break;
}
sprintf(cbuf,"%d ", day);
strncat(cbuf, mname[month-1],
(DisplayOptions & Date::DATE_ABBR) ? ABBR_LENGTH : 9);
sprintf( cbuf+strlen(cbuf), " %d", abs(year) );
if (year < 0)
strcat(cbuf," B.C.E.");
break;
case Date::MDY:
default:
if ( (month < 1) || (month > 12) || (day_of_week < 1) ||
(day_of_week > 7) || (day < 1) )
{
strcpy(cbuf,"invalid date");
break;
}
else
sprintf( cbuf+strlen(cbuf), "%1d/%1d/%02d", month, day,
(DisplayOptions & Date::NO_CENTURY) && (abs(year) > 1899)
? (abs(year) - (abs(year) / 100 * 100))
: (abs(year)) );
break;
}
return cbuf;
}
void Date::setFormat( int format )
{
DisplayFormat = format;
}
int Date::setOption( int option, int action )
{
//
// TML - Convert from switch statement to if statement
//
if (option & (Date::NO_CENTURY | Date::DATE_ABBR))
{
if ( action )
DisplayOptions |= option;
else
DisplayOptions &= ~option;
return 1;
}
else
return 0;
}
///////////////////////////////////////////////////////////////
// Miscellaneous Routines
///////////////////////////////////////////////////////////////
long Date::julDate( void ) const
{
return julian;
}
int Date::DOY( void ) const
{
Date temp( 1, 1, year );
return (int) (julian - temp.julian + 1);
}
int Date::isLeapYear( void ) const
{
return ( (year >= 1582) ?
(year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ):
(year % 4 == 0) );
}
int Date::isDST( void ) const
{
// Initialize start of DST and STD
Date tempDST( (startDST >> 8), ((startDST << 8) >> 8), year ) ;
Date tempSTD( (startSTD >> 8), ((startSTD << 8) >> 8), year ) ;
tempDST += -tempDST.NDOW() + 8 ; // DST begins first Sunday in April
tempSTD -= (tempSTD.NDOW() - 1) ; // STD begins last Sunday in October
return( julian >= tempDST.julian && julian < tempSTD.julian ) ;
}
int Date::setDST(int nMonth, int nDay) const
{
if (nMonth > 0 && nMonth < 13 && nDay > 0 && nDay < 32)
{
startDST = (nMonth << 8) + nDay;
return 1;
}
else
return 0;
}
int Date::setSTD(int nMonth, int nDay) const
{
if (nMonth > 0 && nMonth < 13 && nDay > 0 && nDay < 32)
{
startSTD = (nMonth << 8) + nDay;
return 1;
}
else
return 0;
}
DOSDATE_T Date::eom( void ) const
{
static DOSDATE_T eom_temp;
Date tempdate( (month % 12) + 1, 1, year);
if (month == 12)
tempdate.year++;
tempdate--;
eom_temp.year = tempdate.year;
eom_temp.month = tempdate.month;
eom_temp.day = tempdate.day;
return eom_temp;
}
DOSDATE_T Date::getDate( void ) const
{
static DOSDATE_T getDate_temp;
getDate_temp.year = year;
getDate_temp.month = month;
getDate_temp.day = day;
return getDate_temp;
}
//─────────────────────────────────────────────────
// Version 4.0 Extension to Public Interface - CDP
//─────────────────────────────────────────────────
PUBLIC const Date & Date::Set()
{
struct DOSDATE_T sDate;
_dos_getdate(&sDate);
month = sDate.month;
day = sDate.day;
year = sDate.year;
mdy_to_julian();
return *this;
}
PUBLIC const Date & Date::Set(int nMonth, int nDay, int nYear)
{
month = (unsigned char)nMonth;
year = nYear < 0 ? 9999 : nYear;
year = nYear > 9999 ? 0 : nYear;
day = (unsigned char)(nDay < DaysInMonth() ? nDay : DaysInMonth());
mdy_to_julian();
return *this;
}
PUBLIC const Date & Date::Set(long j)
{
julian = j;
julian_to_mdy();
return *this;
}
PUBLIC int Date::DaysInMonth()
{
return GauDays[month-1] + (month==2 && isLeapYear());
}
PUBLIC int Date::FirstDOM() const
{
return Date(month, 1, year).NDOW();
}
PUBLIC int Date::Day() const
{
return day;
}
PUBLIC int Date::NDOW() const
{
return day_of_week;
}
PUBLIC int Date::NYear4() const
{
return year;
}
PUBLIC int Date::NMonth() const
{
return month;
}
PUBLIC const Date & Date::AddWeeks(int nCount)
{
Set(julian + (long)nCount*7);
return *this;
}
PUBLIC const Date & Date::AddMonths(int nCount)
{
unsigned char nDays;
nCount += month; // Since month is of type unsigned char
// I choose to use nCount as the main
while (nCount < 1) // counter - TML
{
nCount += 12;
year--;
}
while (nCount > 12)
{
nCount -= 12;
year++;
}
month = (unsigned char) nCount;
nDays = (unsigned char) DaysInMonth();
if (day > nDays) // Bump up the month by one if day is
{ // greater than # of days in new month
month++; // and assigned the difference as the
day -= nDays; // day value for the new month! - TML
}
mdy_to_julian();
return *this;
}
PUBLIC const Date & Date::AddYears(int nCount)
{
year += nCount;
mdy_to_julian();
return *this;
}
PUBLIC int Date::WOM()
{
// Abs day includes the days from previous month that fills up
// the begin. of the week.
int nAbsDay = day + FirstDOM()-1;
return (nAbsDay-NDOW())/7 + 1;
}
PUBLIC int Date::WOY()
{
Date doTemp(1, 1, year);
return (int)(((julian - doTemp.julian+1)/7) + 1);
}
PUBLIC Date Date::BOM()
{
return(Date(month, 1, year));
}
PUBLIC Date Date::EOM()
{
return(Date(month+1, 1, year)-1L);
}
PUBLIC Date Date::BOY()
{
return(Date(1, 1, year));
}
PUBLIC Date Date::EOY()
{
return(Date(1, 1, year+1)-1L);
}
PUBLIC const char * Date::CMonth()
{
return(formatDate(MONTH));
}
PUBLIC const char * Date::CDOW()
{
return(formatDate(DAY));
}