/* Name : TIMEDATE.CPP Date : May 10th, 1991 Author : Kim Moser System : Borland C++ 3.0 Descrip: Low-level time and date functions */ #include #include #include #include "timedate.h" #define SecInMinuteR 60.0 #define SecInHourR (SecInMinuteR * 60.0) #define SecInDayR (SecInHourR * 24.0) // Class mmddyy: ========================================================= static mmddyy& getmmddyy(mmddyy& d); static mmddyy& getmmddyy(mmddyy& d) { #ifdef __TURBOC__ struct date turbodate; getdate(&turbodate); d.year = turbodate.da_year; d.month = turbodate.da_mon; d.day = turbodate.da_day; #else /* Microsoft C */ struct dosdate_t msdate; _dos_getdate(&msdate); d.year = msdate.year; d.month = msdate.month; d.day = msdate.day; #endif return (d); } mmddyy& mmddyy::now(void) { return (getmmddyy(*this)); } int mmddyy::isvalid(void) const { return ((month <= 12) && (month > 0) && (day <= m_daysinmonth(month, year)) && (day > 0)); } int mmddyy::compare(const mmddyy &d2) const { int i; i = d2.year - year; if (i < 0) return 1; if (i > 0) return -1; i = d2.month - month; if (i < 0) return 1; if (i > 0) return -1; i = d2.day - day; if (i < 0) return 1; if (i > 0) return -1; return 0; /* this == d2 */ } /* These local procedures are called by AddYear(), AddMonth(), AddDay(), AddHours(), AddMinutes(), AddSeconds(), and AddHundredths(): */ static void domonth(mmddyy* d); static void domonth(mmddyy* d) { int tmp; while (d->month > 12) { tmp = d->month / 12; d->year += tmp; d->month -= tmp*12; } } static void doday(mmddyy* d); static void doday(mmddyy* d) { int tmp; while (d->day > 31) { tmp = d->day / 31; d->month += tmp; d->day -= tmp*31; domonth(d); } } static void dohours(mmddyy* d, hhmmss* t); static void dohours(mmddyy* d, hhmmss* t) { int tmp; if (t->hours >= 24) { tmp = t->hours / 24; d->day += tmp; t->hours -= tmp*24; doday(d); } } static void dominutes(mmddyy* d, hhmmss* t); static void dominutes(mmddyy* d, hhmmss* t) { int tmp; if (t->minutes >= 60) { tmp = t->minutes / 60; t->hours += tmp; t->minutes -= tmp*60; dohours(d, t); } } static void doseconds(mmddyy* d, hhmmss* t); static void doseconds(mmddyy* d, hhmmss* t) { int tmp; if (t->seconds >= 60) { tmp = t->seconds / 60; t->minutes += tmp; t->seconds -= tmp*60; dominutes(d, t); } } static void dohundredths(mmddyy* d, hhmmss* t); static void dohundredths(mmddyy* d, hhmmss* t) { int tmp; if (t->hundredths >= 100) { tmp = t->hundredths / 100; t->seconds += tmp; t->hundredths -= tmp*100; doseconds(d, t); } } inline void mmddyy::adjustday(void) { if (day > m_daysinmonth(month, year)) { day = m_daysinmonth(month, year); } } /*************************************************************************/ mmddyy& mmddyy::addyear(int i) { year += i; // Nowhere to roll over to, but we might overflow return (*this); } mmddyy& mmddyy::addmonth(int i) { month += i; domonth(this); return (*this); } mmddyy& mmddyy::addday(int i) { day += i; doday(this); return (*this); } //------------------------------------------------------------------------ inline mmddyy& mmddyy::borrowyear(void) { year--; // Nowhere to borrow from, but we might underflow month += 12; return (*this); } inline mmddyy& mmddyy::borrowmonth(void) { if (month == 1) { borrowyear(); } month--; day += m_daysinmonth(month, year); return (*this); } mmddyy& mmddyy::subtractyear(int i) { year -= i; // Nowhere to borrow from, but we might underflow adjustday(); return (*this); } mmddyy& mmddyy::subtractmonth(int i) { if (i >= 12) { subtractyear(i / 12); i %= 12; } if (month <= i) { borrowyear(); } month -= i; return (*this); } mmddyy& mmddyy::subtractday(int i) { int dim; while (1) { dim = m_daysinmonth(month, year); if (i >= dim) { subtractmonth(1); i -= dim; } else { break; } } if (day <= i) { borrowmonth(); } day -= i; adjustday(); return (*this); } int mmddyy::weekday(void) const { int dow, y, m, c, dy; if (month > 2) { m = month - 2; y = year; } else { m = month + 10; y = year - 1; } c = y / 100; dy = y - (100 * c); dow = ((13 * m - 1) / 5) + day + dy + (dy / 4) + (c / 4) - c - c + 77; dow = dow - 7 * (dow / 7); return (dow); } mmddyy& now(mmddyy& d) { return (getmmddyy(d)); } // Class hhmmss: ========================================================= static hhmmss& gethhmmss(hhmmss& t); static hhmmss& gethhmmss(hhmmss& t) { #ifdef __TURBOC__ struct time turbotime; gettime(&turbotime); t.hours = turbotime.ti_hour; t.minutes = turbotime.ti_min; t.seconds = turbotime.ti_sec; t.hundredths = turbotime.ti_hund; #else /* Microsoft C */ struct dostime_t mstime; _dos_gettime(&mstime); t.hours = mstime.hour; t.minutes = mstime.minute; t.seconds = mstime.second; t.hundredths = mstime.hsecond; #endif return (t); } hhmmss& hhmmss::now(void) { return (gethhmmss(*this)); } int hhmmss::isvalid(void) { return ((hours < 24) && (minutes < 60) && (seconds < 60) && (hundredths < 100)); } int hhmmss::compare(hhmmss &t2) { int i; i = t2.hours - hours; if (i < 0) return 1; if (i > 0) return -1; i = t2.minutes - minutes; if (i < 0) return 1; if (i > 0) return -1; i = t2.seconds - seconds; if (i < 0) return 1; if (i > 0) return -1; i = t2.hundredths - hundredths; if (i < 0) return 1; if (i > 0) return -1; return 0; /* this == t2 */ } hhmmss& hhmmss::addhours(int i) { hours += i; dohours(NULL, this); return (*this); } hhmmss& hhmmss::addminutes(int i) { minutes += i; dominutes(NULL, this); return (*this); } hhmmss& hhmmss::addseconds(int i) { seconds += i; doseconds(NULL, this); return (*this); } hhmmss& hhmmss::addhundredths(int i) { hundredths += i; dohundredths(NULL, this); return (*this); } //------------------------------------------------------------------------ inline hhmmss& hhmmss::borrowhours(void) { // Nowhere to borrow days from, so we might underflow: hours--; minutes += 60; return (*this); } inline hhmmss& hhmmss::borrowminutes(void) { if (!minutes) { \ borrowhours(); } minutes--; seconds += 60; return (*this); } inline hhmmss& hhmmss::borrowseconds(void) { if (!seconds) { borrowminutes(); } seconds--; hundredths += 100; return (*this); } hhmmss& hhmmss::subtracthours(int i) { hours -= i; // Nowhere to borrow days from, but we might underflow return (*this); } hhmmss& hhmmss::subtractminutes(int i) { if (minutes < i) { borrowhours(); } minutes -= i; return (*this); } hhmmss& hhmmss::subtractseconds(int i) { if (seconds < i) { borrowminutes(); } seconds -= i; return (*this); } hhmmss& hhmmss::subtracthundredths(int i) { if (hundredths < i) { borrowseconds(); } hundredths -= i; return (*this); } hhmmss& now(hhmmss& t) { return (gethhmmss(t)); } // Class timedate: ======================================================= static timedate& gettimedate(timedate& td); static timedate& gettimedate(timedate& td) { td.mmddyy::now(); td.hhmmss::now(); return (td); } timedate& timedate::now(void) { getmmddyy(*this); gethhmmss(*this); return (*this); } timedate& now(timedate& td) { return (gettimedate(td)); } int timedate::isvalid(void) { return (mmddyy::isvalid() && hhmmss::isvalid()); } int timedate::compare(timedate& td2) { int r; r = mmddyy::compare(td2); return (r ? r : hhmmss::compare(td2)); } //------------------------------------------------------------------------- inline void timedate::adjustday(void) { mmddyy::adjustday(); } timedate& timedate::addyear(int i) { mmddyy::addyear(i); return (*this); } timedate& timedate::addmonth(int i) { mmddyy::addmonth(i); return (*this); } timedate& timedate::addday(int i) { mmddyy::addday(i); return (*this); } timedate& timedate::addhours(int i) { hours += i; dohours(this, this); return (*this); } timedate& timedate::addminutes(int i) { minutes += i; dominutes(this, this); return (*this); } timedate& timedate::addseconds(int i) { seconds += i; doseconds(this, this); return (*this); } timedate& timedate::addhundredths(int i) { hundredths += i; dohundredths(this, this); return (*this); } //------------------------------------------------------------------------ /* The following functions borrow one of the named unit and add its equivalent to the next lowest unit: */ inline timedate& timedate::borrowyear(void) { mmddyy::borrowyear(); return (*this); } inline timedate& timedate::borrowmonth(void) { mmddyy::borrowmonth(); return (*this); } inline timedate& timedate::borrowday(void) { if (day == 1) { borrowmonth(); } day--; hours += 24; adjustday(); return (*this); } inline timedate& timedate::borrowhours(void) { if (!hours) { borrowday(); } hhmmss::borrowhours(); return (*this); } inline timedate& timedate::borrowminutes(void) { hhmmss::borrowminutes(); return (*this); } inline timedate& timedate::borrowseconds(void) { hhmmss::borrowseconds(); return (*this); } //------------------------------------------------------------------------ timedate& timedate::subtractyear(int i) { mmddyy::subtractyear(i); return (*this); } timedate& timedate::subtractmonth(int i) { mmddyy::subtractmonth(i); return (*this); } timedate& timedate::subtractday(int i) { mmddyy::subtractday(i); return (*this); } timedate& timedate::subtracthours(int i) { if (hours < i) { borrowday(); } hhmmss::subtracthours(i); return (*this); } timedate& timedate::subtractminutes(int i) { hhmmss::subtractminutes(i); return (*this); } timedate& timedate::subtractseconds(int i) { hhmmss::subtractseconds(i); return (*this); } timedate& timedate::subtracthundredths(int i) { hhmmss::subtracthundredths(i); return (*this); } timedate& timedate::add(int year, int month, int day, int hours, int minutes, int seconds, int hundredths) { /* Before adding each unit, we check whether we'll be adding a non-zero amount so that we won't waste time calling a function for nothing: */ if (year) addyear(year); if (month) addmonth(month); if (day) addday(day); if (hours) addhours(hours); if (minutes) addminutes(minutes); if (seconds) addseconds(seconds); if (hundredths) addhundredths(hundredths); return (*this); } timedate& timedate::subtract(int year, int month, int day, int hours, int minutes, int seconds, int hundredths) { if (year) subtractyear(year); if (month) subtractmonth(month); if (day) subtractday(day); if (hours) subtracthours(hours); if (minutes) subtractminutes(minutes); if (seconds) subtractseconds(seconds); if (hundredths) subtracthundredths(hundredths); return (*this); } duration& timedate::operator -(timedate& td2) { static duration d; d.year = year; d.month = month; d.day = day; d.hours = hours; d.minutes = minutes; d.seconds = seconds; d.hundredths = hundredths; if (d.hundredths < td2.hundredths) d.borrowseconds(); d.hundredths = d.hundredths - td2.hundredths; if (d.seconds < td2.seconds) d.borrowminutes(); d.seconds = d.seconds - td2.seconds; if (d.minutes < td2.minutes) d.borrowhours(); d.minutes = d.minutes - td2.minutes; if (d.hours < td2.hours) d.borrowday(); d.hours = d.hours - td2.hours; if (d.day < td2.day) d.borrowmonth(); d.day = d.day - td2.day; if (d.month < td2.month) d.borrowyear(); d.month = d.month - td2.month; d.year = d.year - td2.year; /* Should never underflow if td1 was >= td2 to begin with */ return (d); } timedate& timedate::operator +(duration& d) { return ( add(d.year, d.month, d.day, d.hours, d.minutes, d.seconds, d.hundredths) ); } int timedate::weekday(void) { return (mmddyy::weekday()); } // Class duration: ======================================================= duration::operator double(void) // Convert duration to seconds { double r = 0.0; r += year * 366.0 * SecInDayR; r += month * 31.0 * SecInDayR; r += day * SecInDayR; r += hours * SecInHourR; r += minutes * SecInMinuteR; r += seconds; r += hundredths / 100.0; return (r); } //======================================================================== int isleapyear(int year) { return (m_isleapyear(year)); } int daysinmonth(int month, int year) { if (month >= 1 && month <= 12) { return (m_daysinmonth(month, year)); } else { #if 0 #ifndef NDEBUG writewarn("daysinmonth(): unknown month (%d).\n", month); #endif #endif return 0; } #if 0 switch(month) { case 9: case 4: case 6: case 11: return 30; /* "Thirty days hath September, April, June, and November... */ case 1: case 3: case 5: case 7: case 8: case 10: case 12: /* ...All the rest have 31... */ return 31; /* ...All the rest have 31... */ case 2: return (m_isleapyear(year) ? 29 : 28); /* ...Save February, which has 28, and 29 on leap years." */ default: #ifndef NDEBUG writewarn("daysinmonth(): unknown month (%d).\n", month); #endif return 0; } #endif } int daysinyear(int year) { return (m_isleapyear(year) ? 366 : 365); } /*************************************************************************/ //------------------------------------------------------------------------- #define JAN_DAYS 31 #define FEB_DAYS 28 #define MAR_DAYS 31 #define APR_DAYS 30 #define MAY_DAYS 31 #define JUN_DAYS 30 #define JUL_DAYS 31 #define AUG_DAYS 31 #define SEP_DAYS 30 #define OCT_DAYS 31 #define NOV_DAYS 30 #define DEC_DAYS 31 static int MONTH_DAYS[] = { JAN_DAYS, FEB_DAYS, MAR_DAYS, APR_DAYS, MAY_DAYS, JUN_DAYS, JUL_DAYS, AUG_DAYS, SEP_DAYS, OCT_DAYS, NOV_DAYS, DEC_DAYS }; inline int m_isleapyear(int year) { return (((!(year % 4)) && (year % 100)) || (!(year % 400))); } inline int m_daysinmonth(int month, int year) { return ((MONTH_DAYS[month-1]) + (((month == 2) && m_isleapyear(year)) ? 1 : 0)); } inline int m_daysinyear(int year) { return (m_isleapyear(year) ? 366 : 365); } /*************************************************************************/ main() { timedate td1, td2; duration d; td1.now(); td2 = td1; td2.addminutes(3); d = td2 - td1; cout << '\n'; cout << "td1= " << td1 << '\n'; cout << "td2= " << td2 << '\n'; cout << "----------------------------\n"; cout << " d= " << d << " (" << (double(d)) << " seconds)\n"; cout << "td1= " << (td1 + d) << '\n'; return (0); }