I've been trying to add a certain number of days (I'm trying to add 30) to the current date.
Let's say today's date is 1/1/2023, after adding the number of days I want to add, I would get 31/1/2023, the main problem would be if I wanted to add if February has 29 days instead of 28.
I got the current date, couldn't add the number of days I wanted because I don't know other way to get the current date without the format being like this "Sun Jan 01 16:29:19 2023".
Just a side note, I saw people adding x days to a date using c, but those problem had the user inserting the date they wanted to the problem, my problem is adding it to the CURRENT DATE.
Anyone can help me with this one?
CodePudding user response:
The standard library time functions already know about leap years and number of days in a month etc. So it makes sense to use that calendrical "expertise".
This is a "duplicate" of my answer at Algorithm to add or subtract days from a date? but adapted slightly to remove the C specifics (hence not marking it as a duplicate). Other answers there may be adapted of course.
#include <time.h>
// Adjust date by a number of days /-
void DatePlusDays( const 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 ) ;
}
Regarding:
"I saw people adding x days to a date using c, but those problem had the user inserting the date they wanted to the problem, my problem is adding it to the CURRENT DATE."
So surely you need only supply the current date as the input. No need to restrict the solution to be quite so inflexible.
Example usage for "current date":
#include <stdio.h>
#include <time.h>
int main( void )
{
struct tm today ;
today = *localtime( time(NULL) ) ;
// Date, plus 30 days
DatePlusDays( &today, 30 ) ;
// Show time/date using default formatting
printf( "%s\n", asctime( &today) ) ;
}
It can be used to subtract days too (pass negative days).
Of course, if you truly do want to restrict the solution to just the current date:
#include <time.h>
// Adjust date by a number of days /-
const struct tm* TodayPlusDays( int days )
{
const time_t ONE_DAY = 24 * 60 * 60 ;
// Seconds since start of epoch
time_t date_seconds = time( NULL ) (days * ONE_DAY) ;
// Update caller's date
// Use localtime because mktime converts to UTC so may change date
return localtime( &date_seconds ) ;
}
Example usage:
#include <stdio.h>
#include <time.h>
int main( void )
{
struct tm today = *TodayPlusDays( 30 ) ;
// Show time/date using default formatting
printf( "%s\n", asctime( &today) ) ;
}
CodePudding user response:
Assuming you've already parsed the date into its component day, month, and year. We can "add days" with a very simple algorithm. And we can even subtract days (or add negative days).
Nothing below uses any of the standard libraries for managing date and time. Nothing against those solutions or the standard libraries. But I wanted to present a simple portable way with the Gregorian calendar that also takes leap years into account.
First a struct to indicate a Date:
struct Date
{
int day;
int month;
int year;
};
Then we need a little helper for leap years.
bool isLeapYear(int year)
{
// leap years happen on 4 year boundaries unless year is divisible by 100 and not 400
// 2000 was a leap year, but 2100 is not
if (year % 400 == 0) return true;
if (year % 100 == 0) return false;
return (year % 4 == 0);
}
And with this data structure for a Date and a leap year detection function, we can build a very simple solution. The basic algorithm is to increment a given date "one day at a time" until the number of added days has been achieved. Each time we increment the day member past the number of days in a month, it gets reset to 1 and the month member gets incremented. And similarly, we handle incrementing to the next year. And then adjust for leap years as well.
// adds "numberOfDays" to the date object pointed to by "d"
void AddDays(Date* d, int numberOfDays)
{
static const int daysInMonths[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static const int daysInMonthsLeap[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int* monthTable = isLeapYear(d->year) ? daysInMonthsLeap : daysInMonths;
// handle the case where we are adding a positive number of days to "d"
while (numberOfDays > 0)
{
d->day ;
if (d->day > monthTable[d->month])
{
d->month ;
if (d->month > 12)
{
d->month = 1;
d->year ;
monthTable = isLeapYear(d->year) ? daysInMonthsLeap : daysInMonths;
}
d->day = 1;
}
numberOfDays--;
}
// handle the case where we are adding a negative number of days to "d".
while (numberOfDays < 0)
{
d->day--;
if (d->day <= 0)
{
d->month--;
if (d->month <= 0)
{
d->year--;
d->month = 12;
monthTable = isLeapYear(d->year) ? daysInMonthsLeap : daysInMonths;
}
d->day = monthTable[d->month];
}
numberOfDays ;
}
}
The above isn't the most efficient - especially if you are adding millions of days onto a given Date object. But for dealing with time adjustments in terms of a small number of days, weeks, or even less than a couple thousand years, you could do a lot worse. A quick benchmark in an optimized build shows that the above works reasonably fast for adding 5 million days to today's date to get to the year 16000 and later.
There's also plenty of opportunities for optimizations in the loops above.