1027 lines
26 KiB
C++
1027 lines
26 KiB
C++
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
#include <common/sdate.hpp>
|
|
#include <common/string.hpp>
|
|
|
|
SDate::SDate(void)
|
|
{
|
|
initArray();
|
|
getTodaysDate();
|
|
}
|
|
|
|
SDate::SDate(const CompatibleDate &someDate)
|
|
{
|
|
initArray();
|
|
CompatibleDate::Month=someDate.Month;
|
|
CompatibleDate::Day=someDate.Day;
|
|
CompatibleDate::Year=someDate.Year;
|
|
}
|
|
|
|
SDate::SDate(long someLongDate)
|
|
{
|
|
initArray();
|
|
*this=someLongDate;
|
|
}
|
|
|
|
SDate::SDate(unsigned char month,unsigned char day,unsigned year)
|
|
{
|
|
initArray();
|
|
CompatibleDate::Month=month;
|
|
CompatibleDate::Day=day;
|
|
CompatibleDate::Year=year;
|
|
}
|
|
|
|
SDate::SDate(const SDate &someDate)
|
|
{
|
|
initArray();
|
|
CompatibleDate::Month=someDate.CompatibleDate::Month;
|
|
CompatibleDate::Day=someDate.CompatibleDate::Day;
|
|
CompatibleDate::Year=someDate.CompatibleDate::Year;
|
|
}
|
|
|
|
SDate::SDate(Options dateOptions)
|
|
{
|
|
initArray();
|
|
switch(dateOptions)
|
|
{
|
|
case TodaysDate :
|
|
getTodaysDate();
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
|
|
SDate::~SDate()
|
|
{
|
|
}
|
|
|
|
void SDate::getTodaysDate(void)
|
|
{
|
|
struct tm *lpTime;
|
|
time_t currTime;
|
|
|
|
::time(&currTime);
|
|
lpTime=::localtime(&currTime);
|
|
CompatibleDate::Month=lpTime->tm_mon+1;
|
|
CompatibleDate::Day=lpTime->tm_mday;
|
|
CompatibleDate::Year=lpTime->tm_year+1900;
|
|
}
|
|
|
|
SDate &SDate::operator=(const CompatibleDate &someDate)
|
|
{
|
|
CompatibleDate::Month=(unsigned)someDate.Month;
|
|
CompatibleDate::Day=(unsigned)someDate.Day;
|
|
CompatibleDate::Year=(unsigned)someDate.Year;
|
|
return *this;
|
|
}
|
|
|
|
SDate &SDate::operator=(long someLongDate)
|
|
{
|
|
CompatibleDate::Year=(unsigned)(someLongDate/10000L);
|
|
CompatibleDate::Month=(unsigned)((someLongDate/100L)-((long)CompatibleDate::Year*100L));
|
|
CompatibleDate::Day=(unsigned)(someLongDate-(((long)CompatibleDate::Year*10000L)+((long)CompatibleDate::Month*100L)));
|
|
return *this;
|
|
}
|
|
|
|
int SDate::operator<(const CompatibleDate &someDate)const
|
|
{
|
|
if (CompatibleDate::Year<someDate.Year) return TRUE;
|
|
if (CompatibleDate::Year>someDate.Year) return FALSE;
|
|
if (CompatibleDate::Month<someDate.Month) return TRUE;
|
|
if (CompatibleDate::Month>someDate.Month) return FALSE;
|
|
return(CompatibleDate::Day<someDate.Day);
|
|
}
|
|
|
|
int SDate::operator>(const CompatibleDate &someDate)const
|
|
{
|
|
if (CompatibleDate::Year>someDate.Year) return TRUE;
|
|
if (CompatibleDate::Year<someDate.Year) return FALSE;
|
|
if (CompatibleDate::Month>someDate.Month) return TRUE;
|
|
if (CompatibleDate::Month<someDate.Month) return FALSE;
|
|
return(CompatibleDate::Day>someDate.Day);
|
|
}
|
|
|
|
int SDate::operator==(const CompatibleDate &someDate)const
|
|
{
|
|
return (CompatibleDate::Month==someDate.Month &&
|
|
CompatibleDate::Day==someDate.Day &&
|
|
CompatibleDate::Year==someDate.Year
|
|
);
|
|
}
|
|
|
|
int SDate::operator<=(const CompatibleDate &someDate)const
|
|
{
|
|
if(!(operator<(someDate)))return operator==(someDate);
|
|
return TRUE;
|
|
}
|
|
|
|
int SDate::month(void)const
|
|
{
|
|
return CompatibleDate::Month;
|
|
}
|
|
|
|
void SDate::month(int newMonth)
|
|
{
|
|
CompatibleDate::Month=newMonth;
|
|
}
|
|
|
|
int SDate::day(void)const
|
|
{
|
|
return CompatibleDate::Day;
|
|
}
|
|
|
|
void SDate::day(int newDay)
|
|
{
|
|
CompatibleDate::Day=newDay;
|
|
}
|
|
|
|
int SDate::year(void)const
|
|
{
|
|
return CompatibleDate::Year;
|
|
}
|
|
|
|
void SDate::year(int newYear)
|
|
{
|
|
CompatibleDate::Year=newYear;
|
|
}
|
|
|
|
long SDate::makeLong(void)const
|
|
{
|
|
return 10000L*CompatibleDate::Year + 100L*CompatibleDate::Month + CompatibleDate::Day;
|
|
}
|
|
|
|
String SDate::makeString(void)const
|
|
{
|
|
String tempString;
|
|
|
|
tempString.reserve(String::MaxString);
|
|
::sprintf((LPSTR)tempString,"%02d/%02d/%04d",
|
|
CompatibleDate::Month,
|
|
CompatibleDate::Day,
|
|
CompatibleDate::Year);
|
|
return tempString;
|
|
}
|
|
|
|
SDate SDate::monthYearStringToDate(char *str,short default_day)
|
|
{
|
|
SDate null_date;
|
|
SDate return_date;
|
|
SDate cur_date;
|
|
short n_items;
|
|
short first_num;
|
|
short second_num;
|
|
short third_num;
|
|
short first_two_digits;
|
|
short second_two_digits;
|
|
short last_two_digits;
|
|
short first_four_digits;
|
|
short last_four_digits;
|
|
char s[256];
|
|
char s2[80];
|
|
char first[32];
|
|
char second[32];
|
|
char third[32];
|
|
char *ps;
|
|
char *ps2;
|
|
unsigned short ndays[sizeof(mDayArray)/sizeof(WORD)];
|
|
|
|
::memcpy(ndays,mDayArray,sizeof ndays);
|
|
cur_date=SDate(SDate::TodaysDate);
|
|
::memset(&null_date,0,sizeof(null_date));
|
|
::memset(first,0,sizeof(first));
|
|
::memset(second,0,sizeof(second));
|
|
::memset(third,0,sizeof(third));
|
|
if(!str)return null_date;
|
|
|
|
if(::strlen(str)>255)::strncpy(s,str,255);
|
|
else ::strcpy(s,str);
|
|
::strupr(s);
|
|
for(ps=s,ps2=s2;*ps!='\0';++ps)
|
|
{
|
|
if(!isalnum(*ps))
|
|
{
|
|
*ps=' ';
|
|
if(ps2==s2)continue;
|
|
}
|
|
if(ps2>s2)
|
|
{
|
|
if(isdigit(*(ps2-1))&&isalpha(*ps)||isalpha(*(ps2-1)) && isdigit(*ps))
|
|
{
|
|
*ps2=' ';
|
|
++ps2;
|
|
}
|
|
else
|
|
if(*(ps2-1)==' '&&*ps==' ')continue;
|
|
}
|
|
*ps2=*ps;
|
|
++ps2;
|
|
}
|
|
*ps2='\0'; /* Terminating null */
|
|
strcpy(s,s2);
|
|
n_items=::sscanf(s," %s %s %s",first,second,third);
|
|
if(n_items<=0)return null_date;
|
|
if(1==n_items)
|
|
{
|
|
long single_num;
|
|
if(isalpha(first[0])) /* Not a numeric value */
|
|
{
|
|
return_date.Month=stringToMonth(first);
|
|
if(0==return_date.Month)return null_date;
|
|
return_date.Year=cur_date.Year;
|
|
if(0==default_day)
|
|
{
|
|
if(2==return_date.Month&&((short)return_date.Year%4))ndays[2]=28;
|
|
default_day=ndays[return_date.Month];
|
|
}
|
|
else
|
|
if(default_day<1||default_day>ndays[return_date.Month])return null_date;
|
|
return_date.Day=default_day;
|
|
return return_date;
|
|
}
|
|
single_num=::atol(first);
|
|
if(single_num>1000||(first[0]=='0'&&single_num>=100))
|
|
{
|
|
if (single_num>100000)
|
|
{
|
|
first_two_digits=(first[0]-'0')*10+(first[1]-'0');
|
|
second_two_digits=(first[2]-'0')*10+(first[3]-'0');
|
|
last_two_digits=single_num%100;
|
|
}
|
|
else
|
|
if(single_num>10000)
|
|
{
|
|
first_four_digits=single_num/10;
|
|
last_four_digits=single_num%10000;
|
|
if(last_four_digits>=1960&&last_four_digits<=2060)
|
|
{
|
|
return_date.Year=last_four_digits;
|
|
return_date.Month=single_num/10000;
|
|
if(0==default_day)
|
|
{
|
|
if(2==return_date.Month&&((short)return_date.Year%4))ndays[2]=28;
|
|
default_day=ndays[return_date.Month];
|
|
}
|
|
return_date.Day=default_day;
|
|
n_items=0;
|
|
}
|
|
else
|
|
if(first_four_digits>=1960&&first_four_digits<=2060&&(single_num%10)!=0)
|
|
{
|
|
return_date.Year=first_four_digits;
|
|
return_date.Month=single_num%10;
|
|
if(0==default_day)
|
|
{
|
|
if(return_date.Month==2&&((short)return_date.Year%4))ndays[2]=28;
|
|
default_day=ndays[return_date.Month];
|
|
}
|
|
return_date.Day=default_day;
|
|
n_items=0;
|
|
}
|
|
else
|
|
{
|
|
first_two_digits=(first[0]-'0')*10+(first[1]-'0');
|
|
last_two_digits=single_num%100;
|
|
second_num=single_num/100;
|
|
if((second_num % 100) <= 31 && (second_num / 100) != 0)
|
|
{
|
|
sprintf(second, "%d", second_num / 100); /* Month or day string */
|
|
sprintf(third, "%d", second_num % 100); /* Day or month string */
|
|
return_date=stringToMonthDay(second,third);
|
|
return_date.Year = last_two_digits;
|
|
n_items = 0;
|
|
}
|
|
else
|
|
if ((second_num % 10) > 0 || (second_num / 10) <= 31)
|
|
{ /* Split it differently */
|
|
sprintf(second, "%d", second_num / 10);
|
|
sprintf(third, "%d", second_num % 10);
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = last_two_digits;
|
|
n_items = 0;
|
|
}
|
|
else /* Assume first 2 digits are the year */
|
|
{
|
|
second_num = single_num % 1000; /* Assume first 2 digits are yr */
|
|
if ((second_num % 100) <= 31 && (second_num / 100) != 0)
|
|
{
|
|
sprintf(second, "%d", second_num / 100); /* Month or day string */
|
|
sprintf(third, "%d", second_num % 100); /* Day or month string */
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = first_two_digits;
|
|
n_items = 0;
|
|
}
|
|
else
|
|
if ((second_num % 10) > 0 || (second_num / 10) <= 31)
|
|
{ /* Split it differently */
|
|
sprintf(second, "%d", second_num / 10);
|
|
sprintf(third, "%d", second_num % 10);
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = first_two_digits;
|
|
n_items = 0;
|
|
}
|
|
else /* Nothing works */
|
|
{
|
|
sprintf(second, "%d", second_num / 100); /* Month or day string */
|
|
sprintf(third, "%d", second_num % 100); /* Day or month string */
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = last_two_digits;
|
|
n_items = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else /* Only 4 digits */
|
|
{
|
|
first_two_digits = (first[0] - '0') * 10 + (first[1] - '0');
|
|
last_two_digits = single_num % 100;
|
|
|
|
if ((last_two_digits < 1 || last_two_digits > 12) &&
|
|
first_two_digits >= 1 && first_two_digits <= 12)
|
|
{ /* Definitely MMYY */
|
|
return_date.Year = last_two_digits;
|
|
return_date.Month = first_two_digits;
|
|
if (default_day == 0)
|
|
{
|
|
if (return_date.Month == 2 && ((short)return_date.Year % 4))
|
|
ndays[2] = 28; /* Not a leap year */
|
|
default_day = ndays[return_date.Month];
|
|
}
|
|
return_date.Day = default_day;
|
|
n_items = 0;
|
|
}
|
|
else
|
|
if ((first_two_digits < 1 || first_two_digits > 12) &&
|
|
last_two_digits >= 1 && last_two_digits <= 12)
|
|
{ /* Definitely YYMM */
|
|
return_date.Year = last_two_digits;
|
|
return_date.Month = last_two_digits;
|
|
if (default_day == 0)
|
|
{
|
|
if (return_date.Month == 2 && ((short)return_date.Year % 4))
|
|
ndays[2] = 28; /* Not a leap year */
|
|
default_day = ndays[return_date.Month];
|
|
}
|
|
return_date.Day = default_day;
|
|
n_items = 0;
|
|
}
|
|
else
|
|
if (first_two_digits >= 1 && first_two_digits <= 12)
|
|
{ /* Qualifies as MMYY */
|
|
return_date.Year = last_two_digits;
|
|
return_date.Month = first_two_digits;
|
|
if (default_day == 0)
|
|
{
|
|
if (return_date.Month == 2 && ((short)return_date.Year % 4))
|
|
ndays[2] = 28; /* Not a leap year */
|
|
default_day = ndays[return_date.Month];
|
|
}
|
|
return_date.Day = default_day;
|
|
n_items = 0;
|
|
}
|
|
else /* Might be month/day/year combination */
|
|
{
|
|
if (first[0] == '0' || first[1] == '0')
|
|
{ /* First two digits are most likely the year */
|
|
second_two_digits = first[2] - '0';
|
|
last_two_digits = first[3] - '0';
|
|
}
|
|
else
|
|
if (first[2] == '0' || first[3] == '0')
|
|
{ /* Last two digits are most likely the year */
|
|
first_two_digits = first[0] - '0';
|
|
second_two_digits = first[1] - '0';
|
|
}
|
|
else
|
|
if ((last_two_digits < 30 || last_two_digits > 80) &&
|
|
first_two_digits >= 30 && first_two_digits <= 80)
|
|
{ /* Last two digits are most likely the year */
|
|
first_two_digits = first[0] - '0';
|
|
second_two_digits = first[1] - '0';
|
|
}
|
|
else
|
|
if ((first_two_digits < 30 || first_two_digits > 80) &&
|
|
last_two_digits >= 30 && last_two_digits <= 80)
|
|
{ /* First two digits are most likely the year */
|
|
second_two_digits = first[2] - '0';
|
|
last_two_digits = first[3] - '0';
|
|
}
|
|
else /* Really don't know; assume last two digits are year */
|
|
{ /* Last two digits are most likely the year */
|
|
first_two_digits = first[0] - '0';
|
|
second_two_digits = first[1] - '0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (n_items == 1)
|
|
if (last_two_digits == 0 || last_two_digits > 31)
|
|
{ /* Last two digits are definitely the year */
|
|
if (single_num > 1000000) /* It is a 4-digit year */
|
|
second_num = single_num / 10000;
|
|
else /* It is a 2-digit year */
|
|
second_num = single_num / 100;
|
|
|
|
sprintf(second, "%d", second_num / 100); /* Month or day string */
|
|
sprintf(third, "%d", second_num % 100); /* Day or month string */
|
|
if ((second_num % 100) > 31 || (second_num / 100) == 0)
|
|
{ /* Split it differently */
|
|
sprintf(second, "%d", second_num / 10);
|
|
sprintf(third, "%d", second_num % 10);
|
|
}
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = last_two_digits;
|
|
n_items = 0;
|
|
}
|
|
else
|
|
if (first_two_digits == 0 || first_two_digits > 31)
|
|
{ /* First 2 digits are the year */
|
|
second_num = atoi(&first[2]);
|
|
sprintf(second, "%d", second_num / 100);
|
|
sprintf(third, "%d", second_num % 100);
|
|
if ((second_num % 100) > 31 || (second_num / 100) == 0)
|
|
{ /* Split it differently */
|
|
sprintf(second, "%d", second_num / 10);
|
|
sprintf(third, "%d", second_num % 10);
|
|
}
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = first_two_digits;
|
|
n_items = 0;
|
|
}
|
|
else
|
|
if (second_two_digits == 0 || second_two_digits > 31)
|
|
{ /* Second 2 digits are the year, assume 4-digit year was given */
|
|
second_num = atoi(&first[4]);
|
|
sprintf(second, "%d", second_num / 100);
|
|
sprintf(third, "%d", second_num % 100);
|
|
if ((second_num % 100) > 31 || (second_num / 100) == 0)
|
|
{ /* Split it differently */
|
|
sprintf(second, "%d", second_num / 10);
|
|
sprintf(third, "%d", second_num % 10);
|
|
}
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = first_two_digits * 100 + second_two_digits;
|
|
n_items = 0;
|
|
}
|
|
else /* Can't tell from looking for 2-digit years; try 4-digit yrs */
|
|
{
|
|
short first_four_digits, last_four_digits;
|
|
|
|
strncpy(second, first, 4);
|
|
second[4] = '\0';
|
|
first_four_digits = atoi(second);
|
|
last_four_digits = single_num % 10000;
|
|
|
|
if (last_four_digits >= 1960 && last_four_digits <= 2060)
|
|
{ /* Last 4 digits are definitely the year */
|
|
second_num = single_num / 10000;
|
|
sprintf(second, "%d", second_num / 100);
|
|
sprintf(third, "%d", second_num % 100);
|
|
if ((second_num % 100) > 31 || (second_num / 100) == 0)
|
|
{ /* Split it differently */
|
|
sprintf(second, "%d", second_num / 10);
|
|
sprintf(third, "%d", second_num % 10);
|
|
}
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = last_four_digits;
|
|
n_items = 0;
|
|
}
|
|
else /* Give up; assume YYMMDD format */
|
|
if (first_four_digits >= 1960 && first_four_digits <= 2060)
|
|
{ /* First 4 digits are definitely the year */
|
|
second_num = atoi(&first[4]);
|
|
sprintf(second, "%d", second_num / 100);
|
|
sprintf(third, "%d", second_num % 100);
|
|
if ((second_num % 100) > 31 || (second_num / 100) == 0)
|
|
{ /* Split it differently */
|
|
sprintf(second, "%d", second_num / 10);
|
|
sprintf(third, "%d", second_num % 10);
|
|
}
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = first_four_digits;
|
|
n_items = 0;
|
|
}
|
|
else
|
|
{
|
|
sprintf(first, "%d", first_two_digits);
|
|
sprintf(second, "%d", second_two_digits);
|
|
sprintf(third, "%d", last_two_digits);
|
|
n_items = 3;
|
|
}
|
|
}
|
|
}
|
|
else /* 3 or fewer digits */
|
|
{
|
|
return null_date; /* Does not qualify as month/year */
|
|
}
|
|
}
|
|
|
|
switch (n_items)
|
|
{
|
|
case 0: /* This means we already parsed the date */
|
|
break;
|
|
case 1: /* Only 1 item scanned, assume it is a month */
|
|
return_date.Month = atoi(first);
|
|
if (return_date.Month >= 1 && return_date.Month <= 12)
|
|
{
|
|
return_date.Year = cur_date.Year;
|
|
if (default_day == 0)
|
|
{
|
|
if (return_date.Month == 2 && ((short)return_date.Year % 4))
|
|
ndays[2] = 28; /* Not a leap year */
|
|
default_day = ndays[return_date.Month];
|
|
}
|
|
return_date.Day = default_day;
|
|
}
|
|
else /* Not a valid month number; an error */
|
|
return null_date;
|
|
break;
|
|
|
|
case 2: /* 2 items scanned, assume month and year */
|
|
{
|
|
short n_days;
|
|
|
|
return_date=stringToMonthYear(first, second);
|
|
|
|
if (*(long *)&return_date) /* It was month/year */
|
|
{
|
|
if (default_day == 0)
|
|
{
|
|
if (return_date.Month == 2 && ((short)return_date.Year % 4))
|
|
ndays[2] = 28; /* Not a leap year */
|
|
if (return_date.Month >= 1 && return_date.Month <= 12)
|
|
default_day = ndays[return_date.Month];
|
|
}
|
|
return_date.Day = default_day;
|
|
}
|
|
else /* Not month/year */
|
|
{
|
|
return_date = stringToMonthDay(first, second);
|
|
return_date.Year = cur_date.Year;
|
|
n_days = daysBetweenActual(cur_date, return_date);
|
|
if (n_days < -182) /* More than 6 months back */
|
|
++return_date.Year; /* Assume it's next year */
|
|
else
|
|
if (n_days > 182) /* More than 6 months in the future */
|
|
--return_date.Year; /* Assume it's last year */
|
|
}
|
|
break;
|
|
}
|
|
case 3: /* 3 items scanned, assume month, day, and year */
|
|
first_num = atoi(first);
|
|
second_num = atoi(second);
|
|
third_num = atoi(third);
|
|
if (first_num > 31) /* First item is a year */
|
|
{
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = first_num;
|
|
}
|
|
else
|
|
if (third_num > 31) /* Third item is a year */
|
|
{
|
|
return_date = stringToMonthDay(first, second);
|
|
return_date.Year = third_num;
|
|
}
|
|
else
|
|
if (second_num > 31) /* Second item might be a year? */
|
|
{
|
|
return_date = stringToMonthDay(first, third);
|
|
return_date.Year = second_num;
|
|
}
|
|
else
|
|
if (isalpha(first[0])) /* First item is a month */
|
|
{ /* Assume second is day, third is year */
|
|
return_date = stringToMonthDay(first, second);
|
|
return_date.Year = third_num;
|
|
}
|
|
else
|
|
if (isalpha(second[0])) /* Second item is a month */
|
|
{ /* Assume first is day, third is year */
|
|
return_date = stringToMonthDay(first, second);
|
|
return_date.Year = third_num;
|
|
}
|
|
else
|
|
if (isalpha(third[0])) /* Third item might be a month? */
|
|
{ /* Assume first is year, second is day */
|
|
return_date = stringToMonthDay(second, third);
|
|
return_date.Year = first_num;
|
|
}
|
|
else /* Assume month, day, year */
|
|
{
|
|
return_date = stringToMonthDay(first, second);
|
|
return_date.Year = third_num;
|
|
}
|
|
break;
|
|
} /* End of switch */
|
|
|
|
if (return_date.Month < 1 || return_date.Month > 12)
|
|
return null_date; /* Month is out of range */
|
|
|
|
if (return_date.Day < 1 || return_date.Day > ndays[return_date.Month])
|
|
{ /* Day of month is out of range */
|
|
if (default_day == 0)
|
|
{
|
|
if (return_date.Month == 2 && ((short)return_date.Year % 4))
|
|
ndays[2] = 28; /* Not a leap year */
|
|
default_day = ndays[return_date.Month];
|
|
}
|
|
return_date.Day = default_day;
|
|
}
|
|
|
|
if (((short)return_date.Year % 4) != 0) /* Not a leap year */
|
|
ndays[2] = 28;
|
|
|
|
if (return_date.Year > 1900)
|
|
return return_date; /* A valid date */
|
|
|
|
if (return_date.Year >= 100) /* Lotus format date for 21st century */
|
|
{
|
|
return_date.Year = 2000 + ((short)return_date.Year % 100);
|
|
return return_date;
|
|
}
|
|
|
|
if (return_date.Year > 60)
|
|
return_date.Year += 1900;
|
|
else
|
|
return_date.Year += 2000;
|
|
|
|
return return_date;
|
|
|
|
}
|
|
|
|
short SDate::stringToMonth(char *szMonth)const /* Converts string to month number */
|
|
{
|
|
String strMonth(szMonth);
|
|
char *str;
|
|
|
|
if(strMonth.isNull())return FALSE;
|
|
strMonth.upper();
|
|
str=(char*)strMonth;
|
|
switch (str[0]) /* Look at first character to determine month */
|
|
{
|
|
case 'F': /* February */
|
|
return 2;
|
|
case 'S': /* September */
|
|
return 9;
|
|
case 'O': /* October */
|
|
return 10;
|
|
case 'N': /* November */
|
|
return 11;
|
|
case 'D': /* December */
|
|
return 12;
|
|
case 'J': /* January, June, or July */
|
|
switch (str[1]) /* Look at second character */
|
|
{
|
|
case 'A': /* January */
|
|
return 1;
|
|
case 'U': /* June or July */
|
|
switch (str[2]) /* Look at third character */
|
|
{
|
|
case 'N': /* June */
|
|
return 6;
|
|
case 'L': /* July */
|
|
return 7;
|
|
} /* End of switch (str[2]) */
|
|
break;
|
|
case 'E': /* June */
|
|
return 6;
|
|
case 'L': /* July */
|
|
return 7;
|
|
} /* End of switch (str[1]) */
|
|
|
|
return 0; /* Cannot determine what month this is */
|
|
|
|
case 'M': /* March or May */
|
|
switch (str[1]) /* Look at second character */
|
|
{
|
|
case 'A': /* March or May */
|
|
switch (str[2]) /* Look at third character */
|
|
{
|
|
case 'R': /* March */
|
|
return 3;
|
|
case 'Y': /* May */
|
|
return 5;
|
|
} /* End of switch (str[2]) */
|
|
return 0; /* Cannot determine the month */
|
|
case 'R': /* March */
|
|
return 3;
|
|
case 'Y':
|
|
return 5;
|
|
} /* End of switch (str[1]) */
|
|
|
|
return 0; /* Cannot determine what month this is */
|
|
|
|
case 'A': /* April or August */
|
|
switch (str[1]) /* Look at second character */
|
|
{
|
|
case 'P': /* April */
|
|
case 'R':
|
|
return 4;
|
|
case 'U': /* August */
|
|
case 'G':
|
|
return 8;
|
|
} /* End of switch (str[1]) */
|
|
|
|
return 0; /* Cannot determine what month this is */
|
|
|
|
default:
|
|
return 0; /* Cannot determine what month this is */
|
|
}
|
|
}
|
|
|
|
SDate SDate::stringToMonthDay(char *first, char *second)
|
|
{
|
|
SDate return_date;
|
|
short first_num;
|
|
short second_num;
|
|
|
|
::memset(&return_date,0,sizeof(return_date));
|
|
if(isalpha(first[0]))
|
|
{
|
|
return_date.month(stringToMonth(first));
|
|
return_date.day(::atoi(second));
|
|
return return_date;
|
|
}
|
|
if (isalpha(second[0])) /* Second item is a month */
|
|
{
|
|
return_date.month(stringToMonth(second));
|
|
return_date.day(::atoi(first));
|
|
return return_date;
|
|
}
|
|
first_num=::atoi(first);
|
|
second_num=::atoi(second);
|
|
if(first_num>12)
|
|
{
|
|
return_date.day(first_num);
|
|
return_date.month(second_num);
|
|
return return_date;
|
|
}
|
|
if(second_num>12)
|
|
{
|
|
return_date.day(second_num);
|
|
return_date.month(first_num);
|
|
return return_date;
|
|
}
|
|
return_date.month(first_num);
|
|
return_date.day(second_num);
|
|
return return_date;
|
|
}
|
|
|
|
SDate SDate::stringToMonthYear(char *first, char *second)
|
|
{
|
|
SDate return_date;
|
|
short first_num, second_num;
|
|
|
|
::memset(&return_date, 0, sizeof return_date);
|
|
if(isalpha(first[0])) /* First item is a month */
|
|
{
|
|
return_date.month(stringToMonth(first));
|
|
return_date.year(::atoi(second));
|
|
return return_date;
|
|
}
|
|
if(isalpha(second[0])) /* Second item is a month */
|
|
{
|
|
return_date.month(stringToMonth(second));
|
|
return_date.year(::atoi(first));
|
|
return return_date;
|
|
}
|
|
first_num=::atoi(first);
|
|
second_num=::atoi(second);
|
|
if((second_num<1||second_num>12)&&first_num>=1&&first_num<=12)
|
|
{
|
|
return_date.year(second_num);
|
|
return_date.month(first_num);
|
|
return return_date;
|
|
}
|
|
else
|
|
if((first_num<1||first_num>12)&&second_num>=1&&second_num<=12)
|
|
{
|
|
return_date.year(first_num);
|
|
return_date.month(second_num);
|
|
return return_date;
|
|
}
|
|
else
|
|
if(first_num>=1&&first_num<=12)
|
|
{
|
|
return_date.year(second_num);
|
|
return_date.month(first_num);
|
|
return return_date;
|
|
}
|
|
return_date.year(first_num);
|
|
return_date.month(second_num);
|
|
return return_date;
|
|
}
|
|
|
|
short SDate::daysBetweenActual(SDate toDate)const
|
|
{
|
|
return daysBetweenActual(*this,toDate);
|
|
}
|
|
|
|
short SDate::daysBetweenActual(SDate fromDate,SDate toDate)const
|
|
{
|
|
short fromCount;
|
|
short fromDay;
|
|
short fromMonth;
|
|
short fromYear;
|
|
short fromQuad;
|
|
short toCount;
|
|
short toDay;
|
|
short toMonth;
|
|
short toYear;
|
|
short toQuad;
|
|
short daysTo[13];
|
|
|
|
daysTo[0]=0;
|
|
daysTo[1]=0;
|
|
daysTo[2]=31;
|
|
daysTo[3]=59;
|
|
daysTo[4]=90;
|
|
daysTo[5]=120;
|
|
daysTo[6]=151;
|
|
daysTo[7]=181;
|
|
daysTo[8]=212;
|
|
daysTo[9]=243;
|
|
daysTo[10]=273;
|
|
daysTo[11]=304;
|
|
daysTo[12]=334;
|
|
|
|
if(fromDate.makeLong()<19010101||
|
|
fromDate.makeLong()>20991231||
|
|
toDate.makeLong()<19010101||
|
|
toDate.makeLong()>20991231)return FALSE;
|
|
fromDay=fromDate.day();
|
|
fromMonth=fromDate.month();
|
|
fromYear=((short)fromDate.year()-1)%4;
|
|
fromQuad=((short)fromDate.year()-1)/4;
|
|
fromCount=fromDay+daysTo[fromMonth]+fromYear*365+fromQuad*((4*365)+1);
|
|
if(3==fromYear&&fromMonth>2)++fromCount;
|
|
toDay=toDate.day();
|
|
toMonth=toDate.month();
|
|
toYear=((short)toDate.year()-1)%4;
|
|
toQuad=((short)toDate.year()-1)/4;
|
|
toCount=toDay+daysTo[toMonth]+toYear*365+toQuad*((4*365)+1);
|
|
if(3==toYear&&toMonth>2)++toCount;
|
|
return toCount-fromCount;
|
|
}
|
|
|
|
SDate SDate::daysAdd360(short dayCount)
|
|
{
|
|
long days;
|
|
WORD thirtyOne;
|
|
SDate toDate;
|
|
|
|
if(!year()&&!day()&&!month())return *this;
|
|
if(!dayCount)return *this;
|
|
thirtyOne=(31==day());
|
|
if(thirtyOne)day(30);
|
|
if(2==month()&&day()>27)
|
|
{
|
|
int daysInMonth=!(year%4)&&(year%100)||!(year%400)?28:29;
|
|
if(day()>=daysInMonth)day(30);
|
|
}
|
|
days=360*(long)year()+30*(long)month()+(long)day()+dayCount-391;
|
|
toDate.day((short)(days%30)+1);
|
|
toDate.month((short)(days/30)%12+1);
|
|
toDate.year((short)(days/360)+1);
|
|
if(!(dayCount%30)&&thirtyOne)
|
|
{
|
|
switch(toDate.month())
|
|
{
|
|
case 1 :
|
|
case 3 :
|
|
case 5 :
|
|
case 7 :
|
|
case 8 :
|
|
case 10 :
|
|
case 12 :
|
|
toDate.day(toDate.day()+1);
|
|
break;
|
|
}
|
|
}
|
|
return toDate;
|
|
}
|
|
|
|
SDate SDate::daysAddActual(short actualDays)const
|
|
{
|
|
return daysAddActual(*this,actualDays);
|
|
}
|
|
|
|
SDate SDate::daysAddActual(SDate fromDate,short actualDays)const
|
|
{
|
|
short day;
|
|
short month;
|
|
short year;
|
|
short daysInMonth;
|
|
short days360;
|
|
short dayCount;
|
|
SDate date360;
|
|
SDate returnDate;
|
|
|
|
if(!fromDate.day()&&!fromDate.month()&&!fromDate.year())return fromDate;
|
|
days360=((float)actualDays*360.00/365.24)+.5;
|
|
|
|
// date360=fromDate.daysAdd360(days360);
|
|
date360=SDate(fromDate).daysAdd360(days360);
|
|
|
|
dayCount=actualDays-daysBetweenActual(fromDate,date360);
|
|
day=date360.day();
|
|
month=date360.month();
|
|
year=date360.year();
|
|
if(dayCount>=0)
|
|
{
|
|
while(dayCount>0)
|
|
{
|
|
switch(month)
|
|
{
|
|
case 2 :
|
|
if(!(year%4)&&(year%100)||!(year%400))daysInMonth=29;
|
|
else daysInMonth=28;
|
|
break;
|
|
case 4 :
|
|
case 6 :
|
|
case 9 :
|
|
case 11 :
|
|
daysInMonth=30;
|
|
break;
|
|
case 1:
|
|
case 3:
|
|
case 5:
|
|
case 7:
|
|
case 8:
|
|
case 10:
|
|
case 12:
|
|
daysInMonth=31;
|
|
break;
|
|
}
|
|
if(dayCount<=(daysInMonth-day)){day+=dayCount;dayCount=0;}
|
|
else
|
|
{
|
|
dayCount-=daysInMonth-day+1;
|
|
month=(month%12)+1;
|
|
day=1;
|
|
if(1==month)++year;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while(dayCount<0)
|
|
{
|
|
if(abs(dayCount)<day)
|
|
{
|
|
day+=dayCount;
|
|
dayCount=0;
|
|
}
|
|
else
|
|
{
|
|
dayCount+=day;
|
|
--month;
|
|
if(0==month)
|
|
{
|
|
month=12;
|
|
--year;
|
|
}
|
|
switch(month)
|
|
{
|
|
case 2 :
|
|
if(!(year%4)&&(year%100)||!(year%400))day=29;
|
|
else day=28;
|
|
break;
|
|
case 4:
|
|
case 6:
|
|
case 9:
|
|
case 11:
|
|
day=30;
|
|
break;
|
|
case 1:
|
|
case 3:
|
|
case 5:
|
|
case 7:
|
|
case 8:
|
|
case 10:
|
|
case 12:
|
|
day=31;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
returnDate.year(year);
|
|
returnDate.month(month);
|
|
returnDate.day(day);
|
|
return returnDate;
|
|
}
|
|
|
|
short SDate::daysBetween360(SDate fromDate,SDate toDate)const
|
|
{
|
|
if(fromDate.day()>=30)
|
|
{
|
|
if(toDate.day()>=30)return (short)(360*((long)toDate.year()-(long)fromDate.year())+30*((long)toDate.month()-(long)fromDate.month()));
|
|
fromDate.day(30);
|
|
}
|
|
return (short)(360*((long)toDate.year()-(long)fromDate.year())+30*((long)toDate.month()-(long)fromDate.month())+(long)toDate.day()-(long)fromDate.day());
|
|
}
|
|
|
|
|