Files
Work/common/SDATE.CPP
2024-08-07 09:09:36 -04:00

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());
}