/** * Copyright Mikael Högdahl - triyana@users.sourceforge.net * * This source is distributed under the terms of the Q Public License version 1.0, * created by Trolltech (www.trolltech.com). */ #include "MHUtil.h" #include "MHDate.h" #include "MHPrice.h" #include #include /** * Copy constructor. * @param MHDate& - The object to copy fields from */ MHDate::MHDate (MHDate &Right) { aTm.tm_sec = Right.aTm.tm_sec; aTm.tm_min = Right.aTm.tm_min; aTm.tm_hour = Right.aTm.tm_hour; aTm.tm_mday = Right.aTm.tm_mday; aTm.tm_mon = Right.aTm.tm_mon; aTm.tm_year = Right.aTm.tm_year; aTm.tm_wday = Right.aTm.tm_wday; aTm.tm_yday = Right.aTm.tm_yday; aTm.tm_isdst = Right.aTm.tm_isdst; aSecs = Right.aSecs; aDate = 0; } /** * Overloaded = * @param const MHDate& - The object to copy fields from */ MHDate& MHDate::operator=(const MHDate& Right) { aTm.tm_sec = Right.aTm.tm_sec; aTm.tm_min = Right.aTm.tm_min; aTm.tm_hour = Right.aTm.tm_hour; aTm.tm_mday = Right.aTm.tm_mday; aTm.tm_mon = Right.aTm.tm_mon; aTm.tm_year = Right.aTm.tm_year; aTm.tm_wday = Right.aTm.tm_wday; aTm.tm_yday = Right.aTm.tm_yday; aTm.tm_isdst = Right.aTm.tm_isdst; aSecs = Right.aSecs; aDate = Right.aDate; return *this; } /** * Static method. Convert seconds to string format like HH:MM:DD. * @param int - Number of seconds * @param string& - String with date */ void MHDate::ConvertSecsToTime (int Secs, MHString& s) { char Buff [50]; double h = Secs / 3600; int hh = (int) h; double m = (Secs - (h * 3600)) / 60; int mm = (int) m; int ss = (int) (double(Secs) - (h * 3600) - (mm * 60)); sprintf (Buff, "%02d:%02d:%02d", hh, mm, ss); s = Buff; } /** * Make an list of dates between max/min date. * @param const char* - Start date of time serie * @param const char* - Stop date of time serie * @param int - Type of time serie, can be WEEKDAY, FRIDAY, SUNDAY, MONTH, SUNDAY, ALL * @param MHVector* - List with dates to pass * @param MHVector* - The list with timeserie, objects are MHString * @param int - String type */ void MHDate::CreateTimeSerie (const char* startDate, const char* stopDate, int timeType, MHVector* in, MHVector* out, int stringType) { int currMonth = -1; MHDate current (startDate); MHDate stop (stopDate); MHString s; MHPrice p; while (current <= stop) { current.Get ((FORMAT)stringType, s); p.SetDate (s()); if (in == 0 || in->Find (&p, 0, 0, 0) == 0) { switch (timeType) { case ALL: out->Push (new MHString(s)); current.AddDays(1); break; case WEEKDAY: if (current.GetWeekday() >= MONDAY && current.GetWeekday() <= FRIDAY) out->Push (new MHString(s)); current.AddDays(1); break; case SUNDAY: if (current.GetWeekday() == SUNDAY) { out->Push (new MHString(s)); current.AddDays(7); } else current.AddDays(1); break; case WEEK: out->Push (new MHString(s)); current.AddDays(7); break; case FRIDAY: if (current.GetWeekday() == FRIDAY) { out->Push (new MHString(s)); current.AddDays(7); } else current.AddDays(1); break; case MONTH: if (current.GetMonth() != currMonth) { out->Push (new MHString(s)); currMonth = current.GetMonth (); } current.AddDays(1); break; default: current.AddDays(1); } } else current.AddDays(1); } } /** * Create a formated string. * @param FORMAT - One of MHDate::TYPES * @param string& - The formated string */ const char* MHDate::Get (FORMAT nDateType) { Get (nDateType, aDate); return aDate.Get(); } /** * Create a formated string. * @param FORMAT - One of MHDate::TYPES * @param string& - The formated string */ void MHDate::Get (FORMAT nDateType, MHString& s) { char Buff[30]; switch (nDateType) { case DATE: strftime (Buff, MAX_STRING_LEN, "%y%m%d", &aTm); break; case DATE_: strftime (Buff, MAX_STRING_LEN, "%y-%m-%d", &aTm); break; case FULL_DATE: strftime (Buff, MAX_STRING_LEN, "%Y-%m-%d %H:%M:%S", &aTm); break; case LONG_DATE: strftime (Buff, MAX_STRING_LEN, "%Y%m%d", &aTm); break; case LONG_DATE_: strftime (Buff, MAX_STRING_LEN, "%Y-%m-%d", &aTm); break; case SHORT_DATE: strftime (Buff, MAX_STRING_LEN, "%y%m", &aTm); break; case SHORT_DATE_: strftime (Buff, MAX_STRING_LEN, "%y-%m", &aTm); break; case SHORT_DATE_NO_YEAR: strftime (Buff, MAX_STRING_LEN, "%m%d", &aTm); break; case SHORT_DATE_NO_YEAR_: strftime (Buff, MAX_STRING_LEN, "%m-%d", &aTm); break; case TIME: strftime (Buff, MAX_STRING_LEN, "%H:%M:%S", &aTm); break; case SHORT_TIME: strftime (Buff, MAX_STRING_LEN, "%H:%M", &aTm); break; case YEAR: strftime (Buff, MAX_STRING_LEN, "%Y", &aTm); break; case WEEK_IN_YEAR: strftime (Buff, MAX_STRING_LEN, "%W", &aTm); break; case DAY_IN_YEAR: strftime (Buff, MAX_STRING_LEN, "%j", &aTm); break; case LOCAL_DATE_AND_TIME: strftime (Buff, MAX_STRING_LEN, "%c", &aTm); break; case LOCAL_DATE: strftime (Buff, MAX_STRING_LEN, "%x", &aTm); break; case LOCAL_TIME: strftime (Buff, MAX_STRING_LEN, "%X", &aTm); break; case NAME_OF_DAY: strftime (Buff, MAX_STRING_LEN, "%A", &aTm); break; case ABBR_OF_DAY: strftime (Buff, MAX_STRING_LEN, "%a", &aTm); break; case NAME_OF_MONTH: strftime (Buff, MAX_STRING_LEN, "%B", &aTm); break; case ABBR_OF_MONTH: strftime (Buff, MAX_STRING_LEN, "%b", &aTm); break; default: strftime (Buff, MAX_STRING_LEN, "%y%m%d", &aTm); } s = Buff; } /** * Goto a weekday in current week. * @return int - Day number in week, MONDAY - SUNDAY */ int MHDate::GetWeekday () { switch (aTm.tm_wday) { case 0: return SUNDAY; case 1: return MONDAY; case 2: return TUESDAY; case 3: return WENDSDAY; case 4: return THURSDAY; case 5: return FRIDAY; case 6: return SATURDAY; default: return 0; } } /** * Goto a weekday in current week * @param int - Name of weekday, MONDAY-SUNDAY */ void MHDate::GotoWeekday (int nWeekday) { if (GetWeekday() < nWeekday) { while (GetWeekday() < nWeekday) AddDays (1); } else if (GetWeekday() > nWeekday) { while (GetWeekday() > nWeekday) AddDays (-1); } } /** * Goto next weekday. * @param int - Name of weekday, MONDAY-SUNDAY * @return bool - true if leap year */ void MHDate::GotoNextWeekday (int nWeekday) { AddDays(1); while (GetWeekday() != nWeekday) { AddDays(1); } } /** * Check if year is leap year. * Copyright (c) 1995, 1996 Branislav L. Slantchev, 73023.262@compuserve.com * @param int - Year */ bool MHDate::IsLeapYear (int year) { if (year % 4) return false; // if not divisible by 4, not leap if (year < 1582 ) return true; // before this year, all were leap if (year % 100) return true; // by 4, but not by 100 is leap if (year % 400) return false; // not by 100 and not by 400 not leap return true; } /** * Convert YYYYMMDD string YYYY-MM-DD string * @param const char* - In date * @param const char* - Out date */ void MHDate::LongToVeryLong (const char* in, char* out) { MHString in2 = in; if (in2.Size() == 8) { MHString s1 = in2.Left(4); MHString s2 = in2.Mid(4, 2); MHString s3 = in2.Right(2); snprintf (out, 11, "%s-%s-%s", s1(), s2(), s3()); } } /** * Return number of years between two dates * @param const char* - Start date * @param const char* - Stop date */ double MHDate::NoYears (const char* d1, const char* d2) { MHDate start (d1); MHDate stop (d2); double secs_start = start.GetSecs(); double secs_stop = stop.GetSecs(); return fabs((secs_stop - secs_start) / double(SECSYEAR)); } /** * Parse a date string and return an iso type string * @param MHString* - String * @return MHString* - String with 8 digit date */ MHString* MHDate::ParseString (MHString* string) { MHString* date = new MHString (); MHVector dates; string->Split ('/', &dates); if (dates.Size() == 3) { MHString* sye = (MHString*) dates[2]; MHString* smo = (MHString*) dates[0]; MHString* sday = (MHString*) dates[1]; char tmp[11]; snprintf (tmp, 10, "%4d%02d%02d", sye->ToInt(), smo->ToInt(), sday->ToInt()); *date = tmp; } else { dates.Erase (); string->Split ('-', &dates); if (dates.Size() == 3) { MHString* sye = (MHString*) dates[2]; MHString* smo = (MHString*) dates[1]; MHString* sday = (MHString*) dates[0]; int mo = 0; char tmp[11]; if (*smo == "Jan") mo = 1; else if (*smo == "Feb") mo = 2; else if (*smo == "Mar") mo = 3; else if (*smo == "Apr") mo = 4; else if (*smo == "May") mo = 5; else if (*smo == "Jun") mo = 6; else if (*smo == "Jul") mo = 7; else if (*smo == "Aug") mo = 8; else if (*smo == "Sep") mo = 9; else if (*smo == "Oct") mo = 10; else if (*smo == "Nov") mo = 11; else if (*smo == "Dec") mo = 12; snprintf (tmp, 10, "%4d%02d%02d", (sye->ToInt() < 30) ? sye->ToInt() + 2000 : sye->ToInt() + 1900, mo, sday->ToInt()); *date = tmp; } } dates.Erase (); return date; } /** * Set date/time. * @param int - Number of seconds since 1970 */ void MHDate::Set (int nSecs) { struct tm *t; if (nSecs != 0) aSecs = nSecs; else time (&aSecs); t = localtime (&aSecs); if (t) { aTm.tm_sec = t->tm_sec; aTm.tm_min = t->tm_min; aTm.tm_hour = t->tm_hour; aTm.tm_mday = t->tm_mday; aTm.tm_mon = t->tm_mon; aTm.tm_year = t->tm_year; aTm.tm_wday = t->tm_wday; aTm.tm_yday = t->tm_yday; aTm.tm_isdst = t->tm_isdst; } } /** * Set new date. * @param const string& - Date in the form of "YYYYMMDD" */ void MHDate::Set (const char* s) { if (s && strlen (s) == 8) { MHString s2 = s; MHString y = s2.Left(4); MHString m = s2.Mid(4, 2); MHString d = s2.Right(2); Set (y.ToInt(), m.ToInt(), d.ToInt()); } } /** * Set new date/time * @param int - Year * @param int - Month * @param int - Day in month * @param int - Hour, can be omitted * @param int - Min, can be omitted * @param int - Sec, can be omitted */ void MHDate::Set (int year, int month, int date, int hour, int min, int sec) { aTm.tm_sec = sec; aTm.tm_min = min; aTm.tm_hour = hour; aTm.tm_mday = date; aTm.tm_mon = --month; if (year > 1899) aTm.tm_year = year - 1900; else aTm.tm_year = year; aTm.tm_wday = 0; aTm.tm_yday = 0; aTm.tm_isdst = 0; aSecs = mktime (&aTm); } /** * */ bool MHDate::ValidDate (const char* date) { if (!date || !*date) return false; else if (strlen (date) != 8) return false; int i = atoi (date); if (i < 19700101 || i > 20291231) return false; return true; }