# Algorithm to add or subtract days from a date?

I'm trying to write a Date class in an attempt to learn C++.

I'm trying to find an algorithm to add or subtract days to a date, where Day starts from 1 and Month starts from 1. It's proving to be very complex, and google doesn't turn up much,

Does anyone know of an algorithm which does this?

## Answers

The easiest way is to actually write two functions, one which converts the day to a number of days from a given start date, then another which converts back to a date. Once the date is expressed as a number of days, it's trivial to add or subtract to it.

You can find the algorithms here: http://alcor.concordia.ca/~gpkatch/gdate-algorithm.html

You don't really need an algorithm as such (at least not something worthy of the name), the standard library can do most of the heavy lifting; calender calculations are notoriously tricky. So long as you don't need dates earlier than 1900, then:

#include <ctime> // Adjust date by a number of days +/- void DatePlusDays( struct tm* date, int days ) { const time_t ONE_DAY = 24 * 60 * 60 ; // Seconds since start of epoch time_t date_seconds = mktime( date ) + (days * ONE_DAY) ; // Update caller's date // Use localtime because mktime converts to UTC so may change date *date = *localtime( &date_seconds ) ; ; }

**Example usage:**

#include <iostream> int main() { struct tm date = { 0, 0, 12 } ; // nominal time midday (arbitrary). int year = 2010 ; int month = 2 ; // February int day = 26 ; // 26th // Set up the date structure date.tm_year = year - 1900 ; date.tm_mon = month - 1 ; // note: zero indexed date.tm_mday = day ; // note: not zero indexed // Date, less 100 days DatePlusDays( &date, -100 ) ; // Show time/date using default formatting std::cout << asctime( &date ) << std::endl ; }

I'm assuming this is for some kind of an exercise, otherwise you would use a time class that's already provided to you.

You could store your time as the number of milliseconds since a certain date. And then you can add the appropriate value and convert from that to the date upon calling the accessors of your class.

Here's a sketch of a very simple approach. For simplicity of ideas I will assume that d, the number of days to add, is positive. It is easy to extend the below to cases where d is negative.

Either d is less than 365 or d is greater than or equal to 365.

If d is less than 365:

m = 1; while(d > numberOfDaysInMonth(m, y)) { d -= numberOfDaysInMonth(m, y); m++; } return date with year = y, month = m, day = d;

If d is greater than 365:

while(d >= 365) { d -= 365; if(isLeapYear(y)) { d -= 1; } y++; } // now use the case where d is less than 365

Alternatively, you could express the date in, say, Julian form and then merely add to the Julian form and conver to ymd format.

One approach is to map the date to the Julian number of the date, do your integer operations and then transform back.

You will find plenty of resources for the julian functions.

I would suggest writing first a routine which converts year-month-day into a number of days since fixed date, say, since 1.01.01. And a symmetric routine which would convert it back.

Don't forget to process leap years correctly!

Having those two, your task would be trivial.

Try this function. It correctly calculates additions or subtractions. dateTime argument must be in UTC format.

tm* dateTimeAdd(const tm* const dateTime, const int& days, const int& hours, const int& mins, const int& secs) { tm* newTime = new tm; memcpy(newTime, dateTime, sizeof(tm)); newTime->tm_mday += days; newTime->tm_hour += hours; newTime->tm_min += mins; newTime->tm_sec += secs; time_t nt_seconds = mktime(newTime) - timezone; delete newTime; return gmtime(&nt_seconds); }

And there are example of using:

time_t t = time(NULL); tm* utc = gmtime(&t); tm* newUtc = dateTimeAdd(utc, -5, 0, 0, 0); //subtract 5 days