Thread: Two date objects showing same date?

  1. #1
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283

    Two date objects showing same date?

    I got an interesting issue. I attempted putting together a DateTime class to include in my library. I did very basic testing at this time, and much more to do. I currently have this problem:

    Code:
    DateTime dt1("1/15/2010");
    DateTime dt2("5/2/2009");
    
    cout << dt1.ToString() << endl;  
    cout << dt2.ToString() << endl;
    Both output lines show "5/2/2009". I would expect both to be unique... does it have to do with the system clock and something staying static? I can't seem to tell.

    My last option is not call the clock/time functions and just declare int variables in the class to keep track of the date and time. My goal is to let the user define any date/time, and by default it stores the current local date/time.

    Here's my code:

    Code:
    namespace X3D
    {
    	class DateTime 
    	{
    	private:
    		time_t m_time;
    		tm *m_timeInfo; 
    		char m_buffer[40];
    	public:
    		DateTime(); 
    		DateTime(const int month, const int day, const int year);
    		DateTime(const char *date);
    		const char *ToString(const char *format = DT_MMDDYYYY);
    		void AddDay(int count = 1);
    		void AddMonth(int count = 1);
    		void AddYear(int count = 1);
    		int GetDay();
    		int GetMonth();
    		int GetYear();
    		void SetDate(const int month, const int day, const int year);
    		void SetDate(const char *date);
    		void SetTime(const int hour, const int minute, const int second = 0);
    		void SetTime(const char *time);
    		const char *GetTime();  
    		operator const char *() { return ToString(); } 
    	};
    }

    .CPP file:

    Code:
    #include "X3D_DateTime.h" 
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// DateTime constructor where default date is today's date.
    /// </summary>      
    /////////////////////////////////////////////////////////////
    X3D::DateTime::DateTime()
    {
    	time(&m_time);
    	m_timeInfo = localtime(&m_time);  
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// DateTime constructor where requested date is set.
    /// </summary>     
    /// <param name = "month"> The month to set. </param>
    /// <param name = "day"> The day to set. </param>
    /// <param name = "year"> The year to set. </param> 
    /////////////////////////////////////////////////////////////
    X3D::DateTime::DateTime(const int month, const int day, 
    	const int year)
    {
    	time(&m_time);
    	m_timeInfo = localtime(&m_time);  
    
    	m_timeInfo->tm_mon = month - 1;		// Month range of 0-11
    	m_timeInfo->tm_mday = day;	
    	m_timeInfo->tm_year = year - 1900;	// Takes the number of years after 1900
    
    	mktime(m_timeInfo);
    } 
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// DateTime constructor that converts date string.
    /// </summary>     
    /// <param name = "date"> The date to parse. </param> 
    /////////////////////////////////////////////////////////////
    X3D::DateTime::DateTime(const char *date)
    {
    	int month, day, year;
    	std::stringstream ss;
    
    	ss << date;
    
    	// Get the month, day, and year.
    	ss >> month;
    	ss.ignore(1);
    	ss >> day;
    	ss.ignore(1);
    	ss >> year;
    
    	// Create date.
    	time(&m_time);
    	m_timeInfo = localtime(&m_time);  
    
    	m_timeInfo->tm_mon = month - 1;		// Month range of 0-11
    	m_timeInfo->tm_mday = day;	
    	m_timeInfo->tm_year = year - 1900;	// Takes the number of years after 1900
    
    	mktime(m_timeInfo);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Parses the date to a string object.
    /// </summary>     
    /// <param name = "format"> The format to output. </param> 
    /// <returns> Returns a string representation. </param> 
    /////////////////////////////////////////////////////////////
    const char *X3D::DateTime::ToString(const char *format)
    {
    	strftime(m_buffer, 40, format, m_timeInfo);
    
    	return m_buffer;
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Increments the day.
    /// </summary>     
    /// <param name = "count"> Increment count. </param>  
    /////////////////////////////////////////////////////////////
    void X3D::DateTime::AddDay(int count)
    { 
    	m_timeInfo->tm_mday += count;
    
    	mktime(m_timeInfo);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Increments the month.
    /// </summary>     
    /// <param name = "count"> Increment count. </param> 
    /////////////////////////////////////////////////////////////
    void X3D::DateTime::AddMonth(int count)
    { 
    	m_timeInfo->tm_mon += count;
    
    	mktime(m_timeInfo);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Increments the year.
    /// </summary>     
    /// <param name = "count"> Increment count. </param> 
    /////////////////////////////////////////////////////////////
    void X3D::DateTime::AddYear(int count)
    { 
    	m_timeInfo->tm_year += count;
    
    	mktime(m_timeInfo);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Gets the day.
    /// </summary>     
    /// <returns> Returns the day. </param> 
    /////////////////////////////////////////////////////////////
    int X3D::DateTime::GetDay()
    {
    	strftime(m_buffer, 40, DT_DAY, m_timeInfo);
    
    	return atoi(m_buffer);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Gets the month.
    /// </summary>     
    /// <returns> Returns the day. </param> 
    /////////////////////////////////////////////////////////////
    int X3D::DateTime::GetMonth()
    {
    	strftime(m_buffer, 40, DT_MONTH, m_timeInfo);
    
    	return atoi(m_buffer);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Gets the year.
    /// </summary>     
    /// <returns> Returns the day. </param> 
    /////////////////////////////////////////////////////////////
    int X3D::DateTime::GetYear()
    {
    	strftime(m_buffer, 40, DT_YEAR, m_timeInfo);
    
    	return atoi(m_buffer);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Sets a new date.
    /// </summary>     
    /// <param name = "month"> The month to set. </param>
    /// <param name = "day"> The day to set. </param>
    /// <param name = "year"> The year to set. </param> 
    /////////////////////////////////////////////////////////////
    void X3D::DateTime::SetDate(const int month, const int day, 
    	const int year)
    {
    	time(&m_time);
    	m_timeInfo = localtime(&m_time);  
    
    	m_timeInfo->tm_mon = month - 1;		// Month range of 0-11
    	m_timeInfo->tm_mday = day;	
    	m_timeInfo->tm_year = year - 1900;	// Takes the number of years after 1900
    
    	mktime(m_timeInfo);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Sets the date in string form.
    /// </summary>     
    /// <param name = "date"> The date to parse. </param> 
    /////////////////////////////////////////////////////////////
    void X3D::DateTime::SetDate(const char *date)
    {
    	int month, day, year;
    	std::stringstream ss;
    
    	ss << date;
    
    	// Get the month, day, and year.
    	ss >> month;
    	ss.ignore(1);
    	ss >> day;
    	ss.ignore(1);
    	ss >> year;
    
    	// Create date.
    	time(&m_time);
    	m_timeInfo = localtime(&m_time);  
    
    	m_timeInfo->tm_mon = month - 1;		// Month range of 0-11
    	m_timeInfo->tm_mday = day;	
    	m_timeInfo->tm_year = year - 1900;	// Takes the number of years after 1900
    
    	mktime(m_timeInfo);
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Sets a new time.
    /// </summary>     
    /// <param name = "hour"> The hour to set. </param>
    /// <param name = "minute"> The minute to set. </param>
    /// <param name = "second"> The second to set. </param> 
    /////////////////////////////////////////////////////////////
    void X3D::DateTime::SetTime(const int hour, const int minute, 
    	const int second)
    { 
    	m_timeInfo->tm_hour = hour;
    	m_timeInfo->tm_min = minute;
    	m_timeInfo->tm_sec = second; 
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Sets a new time.
    /// </summary>     
    /// <param name = "time"> The string value. </param> 
    /////////////////////////////////////////////////////////////
    void X3D::DateTime::SetTime(const char *time)
    { 
    	int hour, minute, second = 0;
    	std::stringstream ss;
    	int len = 0;
    
    	// Get string length. 
    	len = strlen(time);
    
    	ss << time;
    
    	// Get the month, day, and year.
    	ss >> hour;
    	ss.ignore(1);
    	m_timeInfo->tm_hour = hour; 
    
    	if (len > 2) { 
    		ss >> minute;
    		ss.ignore(1);
    		m_timeInfo->tm_min = minute;
    	} else {
    		m_timeInfo->tm_min = 0;
    	}
    
    	if (len > 4) {
    		ss >> second;  
    		m_timeInfo->tm_sec = second;  
    	} else {
    		m_timeInfo->tm_sec = 0;
    	} 
    }
    
    /////////////////////////////////////////////////////////////
    /// <summary>
    /// Returns the time in string format.
    /// </summary>     
    /// <returns> Returns the time in string format. </returns>
    /////////////////////////////////////////////////////////////
    const char *X3D::DateTime::GetTime()
    {
    	strftime(m_buffer, 40, DT_TIME, m_timeInfo);
    
    	return m_buffer;
    }
    Last edited by dxfoo; 06-17-2010 at 04:35 PM.

  2. #2
    Registered User
    Join Date
    Mar 2010
    Posts
    109
    Why are you modifying m_timeInfo here:
    Code:
    m_timeInfo = localtime(&m_time);  
    
    m_timeInfo->tm_mon = month - 1;		// Month range of 0-11
    m_timeInfo->tm_mday = day;	
    m_timeInfo->tm_year = year - 1900;	// Takes the number of years after 1900
    You're messing with memory you didn't allocate. Also, why are you setting m_timeInfo to localtime anyway?

    Your constructor is overwriting your first date with the second because you are accessing memory you shouldn't be modifying.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    IIRC, the time_t struct contains the years offset from 1900. So you would have to normalize it in order to use the standard library functions.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Working with dates is kinda new to me, so I didn't know about that part. I guess it was messing with memory. I think I'll go by the other option then... little safer.

  5. #5
    Registered User
    Join Date
    Mar 2010
    Posts
    109
    You can do it. The problem you are having is you are not storing m_timeInfo like you think you are. localtime() allocates memory elsewhere and returns a pointer to that memory, so all you have is a pointer to that area. When you start poking it with assignments, it's not being stored inside your DateTime object like you think. You can retrieve the data you want with a memcpy and then you will have a local copy of the data you want.

    Anyway, you're not too far.

  6. #6
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    hmm so something like this?

    Code:
    time(&m_time);
    tempTimeInfo = localtime(&m_time);  
    memcpy(m_timeInfo, tempTimeInfo, sizeof(tm));
    Although there is a access violation with this example.

  7. #7
    Registered User
    Join Date
    Mar 2010
    Posts
    109
    Almost, but m_timeInfo still doesn't point to any valid memory, unless you decide to make it not a pointer, but an actual tm struct (which is what I'd suggest). Then you'll have the space you need to store your data.

    What you have is copying the data returned by localtime to some random location that m_timeInfo is currently pointing at.

  8. #8
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Sweet, it worked! Thanks a ton.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. libcurl experience and question
    By Dino in forum C Programming
    Replies: 6
    Last Post: 10-26-2009, 02:07 PM
  2. Advancing day by day until it matches a second date
    By nhubred in forum C++ Programming
    Replies: 1
    Last Post: 05-30-2009, 08:55 AM
  3. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  4. CDate Class - handle date manipulation simply
    By LuckY in forum C++ Programming
    Replies: 5
    Last Post: 07-16-2003, 08:35 AM