Why does my dateclass class gives the wrong date?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Alex T
    New Member
    • Oct 2010
    • 29

    Why does my dateclass class gives the wrong date?

    I have made a date program. I need it to do three things now:

    1. Return the previous dates, (0, 1, 2, 3... Days ago)
    2. Skip the weekends.
    3. Skip these holidays:

    New Year's Day (Jan 1)
    MLKJ Day (Jan 18)
    Pres. Day (Feb 15)
    Good Friday (Apr 2)
    Memorial Day (May 31)
    Indep. Day (Jul 5 observed)
    Labor Day (Sep 6)
    Thanksgiving Day (Nov 25)
    Christmas (Dec 24 observed)

    This is my code, it gives problems:

    Code:
    #include "dateclass.h"
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	dateclass current;
    	cout << current.decrement(0);
    
    	return 0;
    }
    Code:
    #include "numdate.h"
    #include "numvalue.h"
    
    using namespace std;
    
    class dateclass
    {
    private:
    	ushort day;
    	ushort newday;
    	ushort month;
    	ushort year;
    	string curdate;
    	string srchdate;
    	string weekday;
    	string datestring;
    	time_t rawtime;
    public:
    	
    	void reset(){
    		time(&rawtime);
    		datestring = ctime(&rawtime);
    		curdate.clear();
    		datestring.clear();
    	}
    	
    	dateclass() //date constructor 
    	{
    		time(&rawtime);
    		datestring = ctime(&rawtime);
    
    		curdate = datestring;
    		curdate.erase(0,4); //remove day prefix
    		curdate.erase(7,9); //remove time
    		curdate.insert(6, ",", 1); //insert comma
    
    		numvalue current(curdate);
    		
    		month = current.getmonth();
    		day = current.getday();
    		year = current.getyear();
    
    		weekday = datestring.substr(0,3);
    	};
    
    	const string& getcurdate()
    	{
    		srchdate = curdate;
    		if (day < 10) //change "0x" to "x" in date
    			srchdate = curdate.erase(4,1);
    		return srchdate;
    	};
    
    	string decrement(ushort decrement)
    	{
    		exclusion weekdays(weekday);
    		decrement = weekdays.decrement(decrement);
    			
    		numdate numeric (month, day, year);
    		numeric.decrement(decrement);
    
    		srchdate = numeric.revert();
    		numvalue search(srchdate);
    		newday = search.getday();
    
    		if (newday < 10)
    			srchdate = srchdate.erase(4,1);
    
    		return srchdate;
    	};
    };
    Code:
    #include "exclusion.h"
    
    using namespace std;
    const ushort Feb = 31;
    
    enum holidays { NewYear = 1, MartinLuther = 18, Washington = 46, GoodFriday = 92, MemorialDay = 151,\
    	IndependenceDay = 187, LaborDay = 249, ThanksgivingDay = 329, Christmas = 358 };
    
    class numdate
    {
    private:
    	ushort m_month;
    	ushort d_day;
    	ushort y_year;
    	ushort t_month;
    	ushort t_day;
    	ushort t_year;
    
    	int raw;
    	ushort num_days;
    	
    	ushort Mar;
    	ushort Apr;
    	ushort May;
    	ushort Jun;
    	ushort Jul;
    	ushort Aug;
    	ushort Sep;
    	ushort Oct;
    	ushort Nov;
    	ushort Dec;
    public:
    	numdate(int month, int day, int year) : m_month(month), d_day(day), y_year(year)
    	{
    		t_month = 0; //reset temporary
    		t_day = 0;
    		t_year = 0;
    	}
    	
    	ushort ret_month() {return m_month;};
    	ushort ret_day() {return d_day;};
    	ushort ret_year() {return y_year;};
    
    	void decrement(ushort decrement)
    	{
    		if (y_year % 4 == 0)
    			{Mar = 60; Apr = 91; May = 121; Jun = 152; Jul = 182;
    			Aug = 213; Sep = 244; Oct = 274; Nov = 305; Dec = 335;}
    		else
    			{Mar = 59; Apr = 90; May = 120; Jun = 151; Jul = 181;
    			Aug = 212; Sep = 243; Oct = 273; Nov = 304; Dec = 334;}
    
    		switch(m_month)
    		{
    		case 1: break;
    		case 2:	num_days = d_day + Feb; break;
    		case 3: num_days = d_day + Mar; break;
    		case 4: num_days = d_day + Apr; break;
    		case 5: num_days = d_day + May; break;
    		case 6: num_days = d_day + Jun; break;
    		case 7: num_days = d_day + Jul; break;
    		case 8: num_days = d_day + Aug; break;
    		case 9: num_days = d_day + Sep; break;
    		case 10: num_days = d_day + Oct; break;
    		case 11: num_days = d_day + Nov; break;
    		case 12: num_days = d_day + Dec; break;
    		}
    
    		t_year = y_year;
    		
    		while (num_days < decrement)
    		{
    			t_year = t_year - 1;
    			if (t_year % 4 == 0) {num_days += 366;}
    			else {num_days += 365;}
    		}
    			
    		raw = num_days - decrement;
    		t_day = raw;
    
    		if (raw <= NewYear && num_days >= NewYear)
    			t_day--;
    		if (raw <= MartinLuther && num_days >= MartinLuther)
    			t_day -= 3;
    		if (raw <= Washington && num_days >= Washington)
    			t_day -= 3;
    		if (raw <= GoodFriday && num_days >= GoodFriday)
    			t_day--;
    		if (raw <= MemorialDay && num_days >= MemorialDay)
    			t_day -= 3;
    		if (raw <= IndependenceDay && num_days > IndependenceDay)
    			t_day -= 3;
    		if (raw <= LaborDay && num_days >= LaborDay)
    			t_day -= 3;
    		if (raw <= ThanksgivingDay && num_days >= ThanksgivingDay)
    			t_day--;
    		if (raw <= Christmas && num_days >= Christmas)
    			t_day--;
    
    		if (t_day <= 0)
    		{
    			t_year = t_year - 1;
    			if (t_year % 4 == 0) {t_day += 366;}
    			else {t_day += 365;}
    		}
    
    		if (t_day > Dec) {t_day = t_day - Dec; t_month = 12;}
    		else if (t_day > Nov) {t_day = t_day - Nov; t_month = 11;}
    		else if (t_day > Oct) {t_day = t_day - Oct; t_month = 10;}
    		else if (t_day > Sep) {t_day = t_day - Sep; t_month = 9;}
    		else if (t_day > Aug) {t_day = t_day - Aug; t_month = 8;}
    		else if (t_day > Jul) {t_day = t_day - Jul; t_month = 7;}
    		else if (t_day > Jun) {t_day = t_day - Jun; t_month = 6;}
    		else if (t_day > May) {t_day = t_day - May; t_month = 5;}
    		else if (t_day > Apr) {t_day = t_day - Apr; t_month = 4;}
    		else if (t_day > Mar) {t_day = t_day - Mar; t_month = 3;}
    		else if (t_day > Feb) {t_day = t_day - Feb; t_month = 2;}
    		else {t_month = 1;}
    
    	};
    
    	string revert()
    	{
    		string vdate;
    		
    		switch (t_month)
    		{
    		case 1: vdate += "Jan "; break;
    		case 2: vdate += "Feb "; break;
    		case 3: vdate += "Mar "; break;
    		case 4: vdate += "Apr "; break;
    		case 5: vdate += "May "; break;
    		case 6: vdate += "Jun "; break;
    		case 7: vdate += "Jul "; break;
    		case 8: vdate += "Aug "; break;
    		case 9: vdate += "Sep "; break;
    		case 10: vdate += "Oct "; break;
    		case 11: vdate += "Nov "; break;
    		case 12: vdate += "Dec "; break;
    		}
    
    		vdate += ((char) ((t_day / 10) + 48));
    		vdate += ((char) ((t_day % 10) + 48));
    
    		vdate += ", ";
    
    		vdate += ((char) ((t_year / 1000) + 48));
    		vdate += ((char) (((t_year % 1000) / 100) + 48));
    		vdate += ((char) ((((t_year % 1000) % 100) / 10) + 48));
    		vdate += ((char) ((((t_year % 1000) % 100) % 10) + 48));
    
    		return vdate;
    	};
    };
    Code:
    #include <time.h>
    #include <string>
    
    typedef unsigned short ushort;
    using namespace std;
    
    class exclusion
    {
    private:
    	string weekday;
    	int num;
    	ushort countdown;
    	ushort remainder;
    	ushort weekend;
    
    public:
    	exclusion(string weekday)
    	{
    		if(weekday == "Sat") num = 0;
    		else if(weekday == "Sun") num = 1;
    		else if(weekday == "Mon") num = 2;
    		else if(weekday == "Tue") num = 3;
    		else if(weekday == "Wed") num = 4;
    		else if(weekday == "Thu") num = 5;
    		else num = 6;
    
    		if (num == 1)
    			weekend = 1;
    		else if (num > 1)
    			weekend = 2;
    		else
    			weekend = 0;
    	};
    
    	ushort decrement(ushort countdown)
    	{
    		remainder = countdown;
    		if (countdown < num)
    			return remainder;
    		remainder += weekend;
    		countdown -= num;
    		remainder += 2 * (countdown / 7);
    		countdown -= 7 * (countdown / 7);
    		remainder += countdown / 6;
    		return remainder;
    	};
    };
    Code:
    #include <string>
    
    typedef unsigned short ushort;
    using namespace std;
    
    class numvalue
    {
    private:
    	ushort day;
    	ushort month;
    	ushort year;
    	char number;
    	string str_month;
    	string date;
    
    public:
    	numvalue(string input) : date(input){};
    	
    	ushort getmonth()
     	{
    		str_month = date.substr(0,3); //get first 3 chars
    		
    		if (str_month == "Jan") month = 1; //get month values
    		else if (str_month == "Feb") month = 2;
    		else if (str_month == "Mar") month = 3;
    		else if (str_month == "Apr") month = 4;
    		else if (str_month == "May") month = 5;
    		else if (str_month == "Jun") month = 6;
    		else if (str_month == "Jul") month = 7;
    		else if (str_month == "Aug") month = 8;
    		else if (str_month == "Sep") month = 9;
    		else if (str_month == "Oct") month = 10;
    		else if (str_month == "Nov") month = 11;
    		else month = 12;
    
    		return month;
    	};
    
    	ushort getday()
    	{
    		number = date.at(5);
    		day = (int) number - 48;
    		number = date.at(4);
    		day += 10 * ((int) number - 48);
    
    		return day;
    	};
    
    	ushort getyear()
    	{
    		number = date.at(11);
    		year = (int) number - 48;
    		number = date.at(10);
    		year += 10 * ((int) number - 48);
    		number = date.at(9);
    		year += 100 * ((int) number - 48);
    		number = date.at(8);
    		year += 1000 * ((int) number - 48);
    
    		return year;
    	};
    };
    When I try to get today's date, it returns Nov 24, 2010.
    (today is Nov. 25). When I try to get the day 4 days back, I get Nov 20, 2010, (a saturday, I am trying to exclude weekends and holidays). Can anyone help please?
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    I am wondering why at line 30 of dateclass.h you have not just called either std::gmtime or std::localtime from the header <ctime> to convert your time_t variable to a structure containing all the various components?

    Comment

    • Alex T
      New Member
      • Oct 2010
      • 29

      #3
      Never mind about that. I did it how I did it. However, it does not seem to work.

      Comment

      • whodgson
        Contributor
        • Jan 2007
        • 542

        #4
        Being rude won`t get you far.

        Comment

        • Alex T
          New Member
          • Oct 2010
          • 29

          #5
          I wasn't being rude. I am just saying, those functions seem to do the same thing. I really don't care about the time, I just need the date.

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #6
            You have made the whole thing overly complex by trying to work in days months and years. It you worked in seconds past the epoch and just converted to days months and years for output all your calculations would be simpler.

            You use the numerical value 48 where you should be using the character constant '0' and have thus introduced a portability issue.

            The logic in exclusion::decr ement appears wrong if num - countdown == 1

            At the end of the calculation you remove a 0 from the result string if day < 10 but it would be far easier to not put that 0 into the string in the first place in numdate::revert .

            You use of class data is erratic and some classes (exclusion) have class data members that are just not used or that could have automatic scope to the function they are used in.


            The whole thing is an unmitigated mess and a maintenance nightmare I see no obvious errors but then that is hardly surprising since the code is so convoluted that it's operation is not obvious.

            If you really want to go ahead with it I suggest you add output (cout) statements into the code to output the data at various points of the calculation to highlight the point where it is going wrong.

            Comment

            • Alex T
              New Member
              • Oct 2010
              • 29

              #7
              Ok, I changed the main.cpp code for the output:

              Code:
              #include "dateclass.h"
              #include <iostream>
              
              using namespace std;
              
              int main()
              {
              	dateclass current;
              	cout << "Today: " << current.decrement(0) << endl;
              	cout << "2 Days Ago: " << current.decrement(1) << endl; //compensate for skipping holidays
              	cout << "3 Days Ago: " << current.decrement(2) << endl;
              	cout << "4 Days Ago: " << current.decrement(3) << endl;
              	cout << "7 Days Ago: " << current.decrement(4) << endl; //should skip weekends, however, goes to Sunday date
              
              	return 0;
              }
              Output:

              Today: Nov 26, 2010
              2 Days Ago: Nov 24, 2010
              3 Days Ago: Nov 23, 2010
              4 Days Ago: Nov 22, 2010
              7 Days Ago: Nov 21, 2010
              Press any key to continue . . .


              On 7 Days Ago, it should be "Nov 19, 2010", the most recent non-weekend, a Friday. However, it returns the Sunday Date.

              For 5 days, it returns Saturday date, "Nov 20, 2010".

              Also, what did you mean by "seconds past the epoch and just converted to days months and years for output". If you say it is simpler, how would I do it?

              Comment

              • Alex T
                New Member
                • Oct 2010
                • 29

                #8
                By the way, thanks. I spent a whole month working on this.

                Comment

                Working...