Nolemonpledge
Nolemonpledge

Reputation: 139

Adding Days to a Date c++

I am trying to add a certain amount of days to a date. I've looked at examples such as Arithmetics on calendar dates in C or C++ (add N days to given date), but I'm still coming across this problem.

If the num_of_days is a large number, let's say 100, and the beginning day is expire_time.tm_mday = 10. The final day is 110. So when I do mktime(&expire_time); it doesn't convert this day to a valid time; the expire_time.tm_mday still is equal to 110. I want it to add like 3 months on and be a day between 1-31. Why is this?

void add_num_of_days(int* month, int* day, int* year, int num_of_days) 
{
   struct tm expire_time = {};
   int date_to_days;
   expire_time.tm_year = *year - 1900;
   expire_time.tm_mon = *month - 1;
   expire_time.tm_mday = *day;

   //expire_time.tm_mday = 15;
   //num_of_days = 40;
   expire_time.tm_mday += num_of_days;

   mktime(&expire_time);

   //expire_time.tm_mday = 55! (NOT WHAT I WANT).
   *day = expire_time.tm_mday;
   *month = expire_time.tm_mon + 1;
   *year = expire_time.tm_year + 1900;
}

The calling code:

month1 = atoi(start_date.Mid(0, 2)) + 1;
day1 = atoi(start_date.Mid(2, 2));
year1 = atoi(start_date.Mid(4)) + 1900;
//Add the number of days the license 
//period is for to the start date.
add_num_of_days(&month1, &day1, &year1, atoi(num_of_days));

Start date:

//First 32 bits is for the starting date.
CString start_date = get_start_date(byte_array.Mid(0, 32));
//Example start_date would be 01152016 for Jan 15th 2016.

Upvotes: 0

Views: 2362

Answers (1)

Algirdas Preidžius
Algirdas Preidžius

Reputation: 1767

You are not checking the return value of mktime(&expire_time);. According to the documentation it returns -1 if calendar time cannot be represented, so in that case your input parameter is unchanged.

To avoid such problems you may change your procedure to:

bool add_num_of_days(int* month, int* day, int* year, int num_of_days) 
{
   struct tm expire_time = {};
   int date_to_days;
   expire_time.tm_year = *year - 1900;
   expire_time.tm_mon = *month - 1;
   expire_time.tm_mday = *day;

   expire_time.tm_mday += num_of_days;

   if (-1 == mktime(&expire_time))
   {
      return false;
   }

   *day = expire_time.tm_mday;
   *month = expire_time.tm_mon + 1;
   *year = expire_time.tm_year + 1900;
   return true;
}

And then checking the return value of your function on invocation.


And, now let's get to the reason why the mktime says that it can't convert your date.

When you are using 01152016 as your input date, the year in the date is 2016. However, when you are converting from the string to an int, you add additional 1900 to it (year1 = atoi(start_date.Mid(4)) + 1900;), making the date equal to 3916. Apparently, that is too far in the future than mktime can handle (my guess would be, that it can't represent your date within the size limits of time_t).

Note, even though you subtract the year 1900 in your function, to mktime the year is still equal to 3916, since tm.tm_year is defined as "years since 1900", so when you have 2016 years after the year 1900, it is still equal to 3916.

Upvotes: 1

Related Questions