How do I able to get which day by input date?
Input Date example: 15-08-2012
How do I know if its monday, tuesday or which day using C++.
I am trying to omit out weekends from the date available of a month, so If i input e.g the month of August 2012, i want to check which day is saturday and which day is sunday, so i can omit it out from the available date for my program.
Code that I tried for getting the amount of days in a month:
if (month == 4 || month == 6 || month == 9 || month == 11)
{
maxDay = 30;
}
else if (month == 2)
//{
// bool isLeapYear = (year% 4 == 0 && year % 100 != 0) || (year % 400 == 0);
// if (isLeapYear)
// {
// maxDay = 29;
// }
//else
{
maxDay = 28;
}
The next thing i want to know is in that month, which day are weekend so i can omit that from result.
#include <ctime>
std::tm time_in = { 0, 0, 0, // second, minute, hour
4, 9, 1984 - 1900 }; // 1-based day, 0-based month, year since 1900
std::time_t time_temp = std::mktime( & time_in );
// the return value from localtime is a static global - do not call
// this function from more than one thread!
std::tm const *time_out = std::localtime( & time_temp );
std::cout << "I was born on (Sunday = 0) D.O.W. " << time_out->tm_wday << '\n';
Date to Day of the week algorithm?
I'd use mktime(). Given day, month and year, fill out a tm, then
call mktime on it:
tm timeStruct = {};
timeStruct.tm_year = year - 1900;
timeStruct.tm_mon = month - 1;
timeStruct.tm_mday = day;
timeStruct.tm_hour = 12; // To avoid any doubts about summer time, etc.
mktime( &timeStruct );
return timeStruct.tm_wday; // 0...6 for Sunday...Saturday
Here is a simpler and probably better implementation as it does not need any extra library imports.
The result returned is an int from 0 to 6 (Sunday, Mon, Tue... Saturday).
#include <iostream>
int dayofweek(int d, int m, int y){
static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
y -= m < 3;
return ( y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
/* Driver function to test above function */
int main(){
int day = dayofweek(23, 10, 2013);
// Above statement finds the week day for 10/23/2013
//dayofweek(<day in month>,<month>,<year>)
std::cout << day;
return 0;
}
You should use mktime and ctime and extract the tm_wday field of the tm structure. It is guaranteed that mktime doesn't require that field, so you can populate a skeleton tm structure, process it and decompose it back into a complete structure:
#include <ctime>
std::tm t = {};
t.tm_mday = 15;
t.tm_mon = 8;
t.tm_year = 2012;
std::tm * p = std::localtime(std::mktime(&t));
// result is p->tm_wday
#include <stdio.h>
#include <time.h>
int main ()
{
char *str = "15-08-2012";
struct tm tm;
if (strptime (str, "%d-%m-%Y", &tm) == NULL) {
/* Bad format !! */
}
char buffer [80];
strftime (buffer, 80, "Day is %a", &tm);
puts (buffer);
return 0;
}
Related
i am working on a code to parse cron format
After going through the different syntax i got stuck on the 'L' operator, specifically on the '3L' which will give me the last Wednesday of the month (e.g the last Wednesday of September 2021 is going to be 29th )
the number 3 is the number of day :
0 = Sunday
1 = Monday
.
.
6 = Saturday
i looked through the internet and i cant find anything that can help me (i dont want use any libraries)
i found this code which calculates the last Friday of every month, i want to change it so i can get the last week day of my choice of any month i want.
EDITED
#include <iostream>
using namespace std;
class lastFriday
{
int lastDay[12]; //to store last day of all month//хранить последний день всего месяца
int year; //for given year//за данный год
string m[12]; // to store names of all 12 months//хранить имя всех 12 месяцев
bool isleap; // to check given year is leap year or not//проверить, является ли год високосным или нет
private:
//function to find leap year//функция поиска високосного года
void isleapyear()
{
if ((year % 4))
{
if (year % 100)
isleap = true;
else if ((year % 400))
isleap = true;
}
}
// to display last friday of each month
void display()
{
for (int x = 0; x < 12; x++)
cout << m[x] << lastDay[x] << endl;
}
//function to find last friday for a given month
int getWeekDay(int m, int d)
{
int y = year;
int f = y + d + 3 * m - 1;
m++;
if (m < 3)
y--;
else
f -= int(.4 * m + 2.3);
f += int(y / 4) - int((y / 100 + 7) * 0.75);
f %= 7;
return f;
}
public:
//set name of 12 months
lastFriday()
{
m[0] = "JANUARY: "; m[1] = "FEBRUARY: "; m[2] = "MARCH: "; m[3] = "APRIL: ";
m[4] = "MAY: "; m[5] = "JUNE: "; m[6] = "JULY: "; m[7] = "AUGUST: ";
m[8] = "SEPTEMBER: "; m[9] = "OCTOBER: "; m[10] = "NOVEMBER: "; m[11] = "DECEMBER: ";
}
//function to find last fridays
void findLastFriday(int y)
{
year = y;
//to check given year is leap year or not
isleapyear();
//if given year is leap year then feb has 28 else 29
int days[] = { 31, isleap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // to set number of days for each month
int d;
//for all 12 months we have to find last friday
for (int i = 0; i < 12; i++)
{
d = days[i];
while (true)
{
if (!getWeekDay(i, d))
break;
d--;
}
lastDay[i] = d;
}
//function call to print display dates of last friday for each month
display();
}
};
int main()
{
int year; //to store year given by user
lastFriday LF;
cout << "Enter the year in the range 1970 to 2037 : ";
cin >> year;
//validation for year between 1970 to 2037
if (year>2037|year<1970)
{
cout << "Not available for this year";
}
else
{
LF.findLastFriday(year);
}
return 0;
}
can anyone help me understand interpreting this code.
thanks!
Fwiw, here's the C++20 solution:
#include <chrono>
#include <iostream>
void
lastFriday(int y)
{
using namespace std;
using namespace std::chrono;
month m = January;
do
{
cout << m << " : " << sys_days{Friday[last]/m/y} << '\n';
} while (++m != January);
}
int
main()
{
lastFriday(2021);
}
Output:
Jan : 2021-01-29
Feb : 2021-02-26
Mar : 2021-03-26
Apr : 2021-04-30
May : 2021-05-28
Jun : 2021-06-25
Jul : 2021-07-30
Aug : 2021-08-27
Sep : 2021-09-24
Oct : 2021-10-29
Nov : 2021-11-26
Dec : 2021-12-31
If you don't have C++20, but you have C++11 or later, you can still do this using this free, open-source, header-only C++20 chrono preview library. Just add #include "date/date.h" and using namespace date;.
This will output the correct values for the civil calendar when y is in the range [-32767, 32767].
If you need to extract integral values for month, day and year, that is easy to do from the object resulting from this expression: sys_days{Friday[last]/m/y}
I found a solution for my problem and I want to share it with you, maybe someone can find it helpful.
I mentioned in my question that i want to get the day of month of the last weekday of any month.
First, in the cron format, if you want to specify that you could write it like this: "0 14 10 ? SEP 3L ?" this means, execute every last Wednesday of September on 10:14:00.
For that to work in my code, I need to get which day of month is on Wednesday,
This code is a portion of my project, but I will try explaining everything,
else if (contains(str[5],'L'))
{
if (str[5] == "L") bdaysOfWeekDesc[6]=6;
else
{
int diff;
auto parts = split(str[5],'L');
auto LDoM = LastDay(stoi(monthReplaced),currentYear);
tm time_in = { 0, 0, 0, LDoM, stoi(monthReplaced)-1, currentYear - 1900};
time_t time_temp = mktime(&time_in);
const tm * time_out = localtime(&time_temp);
if (stoi(parts[0].data()) == time_out->tm_wday)
{
bdaysOfMonthsDesc[time_out->tm_mday] = time_out->tm_mday;
}
else if ((stoi(parts[0].data()) > time_out->tm_wday) || time_out->tm_wday ==0 )
{
diff = time_out->tm_wday - stoi(parts[0].data());
for(size_t j=0;j<=sizeof(bdaysOfMonthsDesc) / sizeof(bdaysOfMonthsDesc[0]);j++)
{
bdaysOfMonthsDesc[j]=0;
bdaysOfMonthsDesc[time_out->tm_mday + abs(diff) - 7] = time_out->tm_mday + abs(diff) - 7;
}
}
else if (stoi(parts[0].data()) < time_out->tm_wday)
{
diff = time_out->tm_wday - stoi(parts[0].data());
for(size_t j=0; j <= sizeof(bdaysOfMonthsDesc) / sizeof(bdaysOfMonthsDesc[0]); j++)
{
bdaysOfMonthsDesc[j] = 0;
bdaysOfMonthsDesc[time_out->tm_mday - abs(diff)] = time_out->tm_mday - abs(diff);
}
}
}
}
the split function is for splitting the field according to the separator given
e.g: auto parts = split("3L", 'L');
parts[0] equals to "3"
the contains function checks if a character exists in a string or not
e.g: contains("3L", 'L');
the split and contains functions are from the croncpp
The LastDay function returns the last day (30 or 31 or 28 or 29) of the month given. This function is from #saqlain response on an other thread
At first, I need to get the date for last day of the month
so:
tm time_in = {seconds, minutes, hours, dayOfMonth, Month, year-1900}
seconds: 0-based,
minutes: 0-based,
hours: 0-based,
DOM: 1-based day,
Month: 0-based month ( the -1 in the code is because my month's field is 1-based)
year: year since 1900
with the mktime() and localtime() functions I can get which weekday is on the 30th or 31st of the month
After that, I tested if the week day I am requesting in the cron format is the same as the weekday of the last day of month,
or if it's superior or inferior.
With this code, my problem was solved, and maybe it can help someone else.
I need to calculate the day number of a given date. The year has 366 days in it. Each month however has a different value and I have to assign the values. Is there a quicker way to do it rather than the way I am going about it?
#include<iostream>
using namespace std;
int main()
{
int day, month, year, dayNumber;
cout<< "Please enter the month, by numerical value:";
cin>> month;
cout<<"Please enter the day, by numerical value:";
cin>> day;
cout<<"Please enter the year, by numerical value:";
cin>> year;
if (month == 1)
{
dayNumber= day;
cout<< "Month;" << '\t'<< month << '\n'
<< "Day:"<<'\t'<< day<< '\n'
<< "Year:"<<'\t'<< year<<'\n'
<< "Day Number:"<< '\t'<< dayNumber<< endl;
}
else if(month==2)
{
dayNumber= day+31;
}
}
Just use mktime:
tm date = {};
date.tm_year = year - 1900;
date.tm_mon = month - 1;
date.tm_mday = day;
mktime( &date );
dayNumber = date.tm_yday;
Otherwise, you'll need a two dimensional table:
int daysToMonth[2][12] =
{
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
};
and a function:
bool isLeapYear( int year )
{
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
The year day is then:
daysToMonth[isLeapYear( year ) ? 1 : 0][month] + day;
First you need to know if the year is a leap year or not :
bool isLeap(year) {
return (((year % 4) == 0) && (((year % 100) != 0) || ((year % 400) == 0))
}
Then you could create, for given year and array or day-per-month number :
unsigned int daysPerMonth[] = {31, (isLeap(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
I only give you chunks of code, but they may help you.
Loop through this array to get the real day number. By an example April 4th 1989, not leap year. It's The number of days 31+28+31 (for January to March) then +4.
In many ways it is probably best to avoid hand-rolling this.
Use boost:
#include <boost/date_time/gregorian/gregorian.hpp>
//...
try {
boost::gregorian::date d(year, month, day);
dayNumber = d.day_of_year();
}
catch (std::out_of_range& e) {
// Alternatively catch bad_year etc exceptions.
std::cout << "Bad date: " << e.what() << std::endl;
}
As James Kanze suggests you could also use mktime to avoid dependency on boost (untested):
tm timeinfo = {};
timeinfo.tm_year = year - 1900;
timeinfo.tm_mon = month - 1;
timeinfo.tm_mday = day;
mktime(&timeinfo);
dayNumber = timeinfo.tm_yday;
You could create a vector containing the numbers of days in each month:
std::vector<int> days_in_month;
days_in_month.push_back(31); //Jan
days_in_month.push_back(29); //Feb
... // so on for each month
Then, to calculate, you could do this:
int day = <day_entered_by_user>;
int month = <month_entered_by_user>;
int num_of_days = 0;
// Sum the number of days for all months preceding the current month
for(int i = 0; i < (month - 1); ++i)
num_of_days += days_in_month[i];
// Finally just add the day entered for the current month
num_of_days += day;
You can store the number of days per month in an array:
int days_per_month[] = {31, 29, 31, ...};
or
std::array<int, 12> days_per_month{{31, 29, 31,...}};
Then you need to loop over that array to calculate the sum of already passed days:
int sum = 0;
for ( int i = 1; i < month; ++i )
{
sum += days_per_month[i - 1]; // note the index shift!
}
dayNumber += sum;
Another alternative is to directly store the sums in the array:
std::array<int, 12> passed_days{{0, 31, 60,...}};
Then you get rid of the loop:
dayNumber += passed_days[month - 1];
For leap years, simply check for the year and if the month is at least 3.
really short code will look like follwoing:
{
int nonleap[12]={0,31, 31+28, 31+28+31, 31+28+31+30 .....};
int leap[12]={0,31, 31+29, 31+29+31, 31+29+31+30 .....};
if(yearIsLeap(year))
return leap[month]+day;
else
return nonleap[month]+day;
}
You guys are making this really difficult, why not just roll up the first 2 answers
int year = 2020, month = 12, day = 10;
tm timeinfo = {};
int dayNumber = 0;
bool isLeap = (((year % 4) == 0) && (((year % 100) != 0) || ((year % 400) == 0));
timeinfo.tm_year = year - 1900;
timeinfo.tm_mon = month - 1;
timeinfo.tm_mday = day;
mktime(&timeinfo);
dayNumber = timeinfo.tm_yday;
if (isLeap && month > 2) dayNumber++;
I was trying to write a roll-your-own timezone converter and I needed a way of determining what the last possible day of the month was. Upon some research, I discovered the formulas for finding a leap year.
It's a small contribution, but maybe I'll save someone else the 20 minutes it took me to figure out and apply it.
This code accepts a signed short month, indexed at 0 (0 is January) and an int year that is indexed as 0 as well (2012 is 2012).
It returns a 1 indexed day (the 27th is the 27th, but in SYSTEMTIME structures, etc., you usually need 0 indexed - just a head's up).
short _get_max_day(short month, int year) {
if(month == 0 || month == 2 || month == 4 || month == 6 || month == 7 || month == 9 || month == 11)
return 31;
else if(month == 3 || month == 5 || month == 8 || month == 10)
return 30;
else {
if(year % 4 == 0) {
if(year % 100 == 0) {
if(year % 400 == 0)
return 29;
return 28;
}
return 29;
}
return 28;
}
}
What about
#include <time.h>
#include <iostream>
int LastDay (int iMonth, int iYear)
{
struct tm when;
time_t lastday;
// Set up current month
when.tm_hour = 0;
when.tm_min = 0;
when.tm_sec = 0;
when.tm_mday = 1;
// Next month 0=Jan
if (iMonth == 12)
{
when.tm_mon = 0;
when.tm_year = iYear - 1900 + 1;
}
else
{
when.tm_mon = iMonth;
when.tm_year = iYear - 1900;
}
// Get the first day of the next month
lastday = mktime (&when);
// Subtract 1 day
lastday -= 86400;
// Convert back to date and time
when = *localtime (&lastday);
return when.tm_mday;
}
int _tmain(int argc, _TCHAR* argv[])
{
for (int m = 1; m <= 12; m++)
std::cout << "Last day of " << m << " is " << LastDay (m, 2002) << std::endl;
return 0;
}
It prints out (for year 2002)...
Last day of 1 is 31
Last day of 2 is 28
Last day of 3 is 31
Last day of 4 is 30
Last day of 5 is 31
Last day of 6 is 30
Last day of 7 is 31
Last day of 8 is 31
Last day of 9 is 30
Last day of 10 is 31
Last day of 11 is 30
Last day of 12 is 31
I use a simple function that returns the whole date in the from of a (Standard) COleDateTime. It may not be as fast other options, but it is very effective, works for leap years and pretty fool proof.
This is the Code that I am using:
COleDateTime get_last_day_of_month(UINT month, UINT year)
{
if(month == 2)
{ // if month is feb, take last day of March and then go back one day
COleDateTime date(year, 3, 1, 0, 0, 0); // 1 March for Year
date -= 1; // go back one day (the standard class will take leap years into account)
return date;
}
else if(month == 4 || month == 6 || month == 9 || month == 11) return COleDateTime(year, month, 30, 0, 0, 0);
else return COleDateTime(year, month, 31, 0, 0, 0);
}
import datetime
from datetime import date
from dateutil.relativedelta import relativedelta
year = int((date.today()).strftime("%Y"))
month = list(range(1, 13, 1))
YearMonthDay = [(datetime.datetime(year, x, 1) + relativedelta(day=31)).strftime("%Y%m%d") for x in month]
print(YearMonthDay)
['20220131', '20220228', '20220331', '20220430', '20220531', '20220630', '20220731', '20220831', '20220930', '20221031', '20221130', '20221231']
In C++20:
#include <chrono>
std::chrono::day
get_max_day(std::chrono::month m, std::chrono::year y)
{
return (y/m/std::chrono::last).day();
}
If you really need it with a type-unsafe API:
int
get_max_day(int m, int y)
{
return unsigned{(std::chrono::last/m/y).day()};
}
Word Year, Month, Day;
TDateTime datum_tdatetime = Date();
// first day of actual month
datum_tdatetime.DecodeDate(&year, &month, &day);
day = 1;
datum_tdatetime = EncodeDate(year, month, day);
// last day of previous month
datum_tdatetime -= 1;
// first day of previous month
datum_tdatetime.DecodeDate(&year, &month, &day);
day = 1;
datum_tdatetime = EncodeDate(year, month, day);
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?
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.
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
I know this is a very old question but it's an interesting and some common one when it comes to working with dates and times. So I thought of sharing some code which calculates the new date without using any inbuilt time functionality in C++.
#include <iostream>
#include <string>
using namespace std;
class Date {
public:
Date(size_t year, size_t month, size_t day):m_year(year), m_month(month), m_day(day) {}
~Date() {}
// Add specified number of days to date
Date operator + (size_t days) const;
// Subtract specified number of days from date
Date operator - (size_t days) const;
size_t Year() { return m_year; }
size_t Month() { return m_month; }
size_t Day() { return m_day; }
string DateStr();
private:
// Leap year check
inline bool LeapYear(int year) const
{ return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); }
// Holds all max days in a general year
static const int MaxDayInMonth[13];
// Private members
size_t m_year;
size_t m_month;
size_t m_day;
};
// Define MaxDayInMonth
const int Date::MaxDayInMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//===========================================================================================
/// Add specified number of days to date
Date Date::operator + (size_t days) const {
// Maximum days in the month
int nMaxDays(MaxDayInMonth[m_month] + (m_month == 2 && LeapYear(m_year) ? 1 : 0));
// Initialize the Year, Month, Days
int nYear(m_year);
int nMonth(m_month);
int nDays(m_day + days);
// Iterate till it becomes a valid day of a month
while (nDays > nMaxDays) {
// Subtract the max number of days of current month
nDays -= nMaxDays;
// Advance to next month
++nMonth;
// Falls on to next year?
if (nMonth > 12) {
nMonth = 1; // January
++nYear; // Next year
}
// Update the max days of the new month
nMaxDays = MaxDayInMonth[nMonth] + (nMonth == 2 && LeapYear(nYear) ? 1 : 0);
}
// Construct date
return Date(nYear, nMonth, nDays);
}
//===========================================================================================
/// Subtract specified number of days from date
Date Date::operator - (size_t days) const {
// Falls within the same month?
if (0 < (m_day - days)) {
return Date(m_year, m_month, m_day - days);
}
// Start from this year
int nYear(m_year);
// Start from specified days and go back to first day of this month
int nDays(days);
nDays -= m_day;
// Start from previous month and check if it falls on to previous year
int nMonth(m_month - 1);
if (nMonth < 1) {
nMonth = 12; // December
--nYear; // Previous year
}
// Maximum days in the current month
int nDaysInMonth = MaxDayInMonth[nMonth] + (nMonth == 2 && LeapYear(nYear) ? 1 : 0);
// Iterate till it becomes a valid day of a month
while (nDays >= 0) {
// Subtract the max number of days of current month
nDays -= nDaysInMonth;
// Falls on to previous month?
if (nDays > 0) {
// Go to previous month
--nMonth;
// Falls on to previous year?
if (nMonth < 1) {
nMonth = 12; // December
--nYear; // Previous year
}
}
// Update the max days of the new month
nDaysInMonth = MaxDayInMonth[nMonth] + (nMonth == 2 && LeapYear(nYear) ? 1 : 0);
}
// Construct date
return Date(nYear, nMonth, (0 < nDays ? nDays : -nDays));
}
//===========================================================================================
/// Get the date string in yyyy/mm/dd format
string Date::DateStr() {
return to_string(m_year)
+ string("/")
+ string(m_month < 10 ? string("0") + to_string(m_month) : to_string(m_month))
+ string("/")
+ string(m_day < 10 ? string("0") + to_string(m_day) : to_string(m_day));
}
int main() {
// Add n days to a date
cout << Date(2017, 6, 25).DateStr() << " + 10 days = "
<< (Date(2017, 6, 25) /* Given Date */ + 10 /* Days to add */).DateStr() << endl;
// Subtract n days from a date
cout << Date(2017, 6, 25).DateStr() << " - 10 days = "
<< (Date(2017, 6, 25) /* Given Date */ - 10 /* Days to subract */).DateStr() << endl;
return 0;
}
Output
2017/06/25 + 10 days = 2017/07/05
2017/06/25 - 10 days = 2017/06/15
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.
I know it is an old question asked almost a decade before. But a few days before I came across the same for an assignment, and here is the answer as in here
// C++ program to find date after adding
// given number of days.
#include<bits/stdc++.h>
using namespace std;
// Return if year is leap year or not.
bool isLeap(int y)
{
if (y%100 != 0 && y%4 == 0 || y %400 == 0)
return true;
return false;
}
// Given a date, returns number of days elapsed
// from the beginning of the current year (1st
// jan).
int offsetDays(int d, int m, int y)
{
int offset = d;
switch (m - 1)
{
case 11:
offset += 30;
case 10:
offset += 31;
case 9:
offset += 30;
case 8:
offset += 31;
case 7:
offset += 31;
case 6:
offset += 30;
case 5:
offset += 31;
case 4:
offset += 30;
case 3:
offset += 31;
case 2:
offset += 28;
case 1:
offset += 31;
}
if (isLeap(y) && m > 2)
offset += 1;
return offset;
}
// Given a year and days elapsed in it, finds
// date by storing results in d and m.
void revoffsetDays(int offset, int y, int *d, int *m)
{
int month[13] = { 0, 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
if (isLeap(y))
month[2] = 29;
int i;
for (i = 1; i <= 12; i++)
{
if (offset <= month[i])
break;
offset = offset - month[i];
}
*d = offset;
*m = i;
}
// Add x days to the given date.
void addDays(int d1, int m1, int y1, int x)
{
int offset1 = offsetDays(d1, m1, y1);
int remDays = isLeap(y1)?(366-offset1):(365-offset1);
// y2 is going to store result year and
// offset2 is going to store offset days
// in result year.
int y2, offset2;
if (x <= remDays)
{
y2 = y1;
offset2 = offset1 + x;
}
else
{
// x may store thousands of days.
// We find correct year and offset
// in the year.
x -= remDays;
y2 = y1 + 1;
int y2days = isLeap(y2)?366:365;
while (x >= y2days)
{
x -= y2days;
y2++;
y2days = isLeap(y2)?366:365;
}
offset2 = x;
}
// Find values of day and month from
// offset of result year.
int m2, d2;
revoffsetDays(offset2, y2, &d2, &m2);
cout << "d2 = " << d2 << ", m2 = " << m2
<< ", y2 = " << y2;
}
// Driven Program
int main()
{
int d = 14, m = 3, y = 2015;
int x = 366;
addDays(d, m, y, x);
return 0;
}
Don't know if this helps or not. I was working on a scheduling system which (in the first simple draft) calculated start date as due date - days lead time. I worked with seconds elapsed (since epoch) to allow greater precision in future drafts of the code.
#include <iostream>
#include <ctime>
int main() {
// lead time in days
int lead_time = 20;
// assign a due_date of (midnight on) 3rd November 2020
tm tm_due_date = { 0, 0, 0, 3, 11, 2020-1900};
// convert due_date to seconds elapsed (since epoch)
time_t tt_due_date = mktime(&tm_due_date);
// subtract lead time seconds
tt_due_date -= 60 * 60 * 24 * lead_time;
// convert back (to local time)
tm *start_date = localtime(&tt_due_date);
// otput the result as something we can readily read
std::cout << asctime(start_date) << "\n";
}
I have some code that uses the Oracle function add_months to increment a Date by X number of months.
I now need to re-implement the same logic in a C / C++ function. For reasons I don't want/need to go into I can't simply issue a query to oracle to get the new date.
Does anyone know of a simple and reliable way of adding X number of months to a time_t?
Some examples of the types of calculations are shown below.
30/01/2009 + 1 month = 28/02/2009
31/01/2009 + 1 month = 28/02/2009
27/02/2009 + 1 month = 27/03/2009
28/02/2009 + 1 month = 31/03/2009
31/01/2009 + 50 months = 31/03/2013
You can use Boost.GregorianDate for this.
More specifically, determine the month by adding the correct date_duration, and then use end_of_month_day() from the date algorithms
Convert time_t to struct tm, add X to month, add months > 12 to years, convert back. tm.tm_mon is an int, adding 32000+ months shouldn't be a problem.
[edit] You might find that matching Oracle is tricky once you get to the harder cases, like adding 12 months to 29/02/2008. Both 01/03/2009 and 28/02/2008 are reasonable.
Really new answer to a really old question!
Using this free and open source library, and a C++14 compiler (such as clang) I can now write this:
#include "date.h"
constexpr
date::year_month_day
add(date::year_month_day ymd, date::months m) noexcept
{
using namespace date;
auto was_last = ymd == ymd.year()/ymd.month()/last;
ymd = ymd + m;
if (!ymd.ok() || was_last)
ymd = ymd.year()/ymd.month()/last;
return ymd;
}
int
main()
{
using namespace date;
static_assert(add(30_d/01/2009, months{ 1}) == 28_d/02/2009, "");
static_assert(add(31_d/01/2009, months{ 1}) == 28_d/02/2009, "");
static_assert(add(27_d/02/2009, months{ 1}) == 27_d/03/2009, "");
static_assert(add(28_d/02/2009, months{ 1}) == 31_d/03/2009, "");
static_assert(add(31_d/01/2009, months{50}) == 31_d/03/2013, "");
}
And it compiles.
Note the remarkable similarity between the actual code, and the OP's pseudo-code:
30/01/2009 + 1 month = 28/02/2009
31/01/2009 + 1 month = 28/02/2009
27/02/2009 + 1 month = 27/03/2009
28/02/2009 + 1 month = 31/03/2009
31/01/2009 + 50 months = 31/03/2013
Also note that compile-time information in leads to compile-time information out.
Method AddMonths_OracleStyle does what you need.
Perhaps you would want to replace IsLeapYear and GetDaysInMonth to some librarian methods.
#include <ctime>
#include <assert.h>
bool IsLeapYear(int year)
{
if (year % 4 != 0) return false;
if (year % 400 == 0) return true;
if (year % 100 == 0) return false;
return true;
}
int daysInMonths[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int GetDaysInMonth(int year, int month)
{
assert(month >= 0);
assert(month < 12);
int days = daysInMonths[month];
if (month == 1 && IsLeapYear(year)) // February of a leap year
days += 1;
return days;
}
tm AddMonths_OracleStyle(const tm &d, int months)
{
bool isLastDayInMonth = d.tm_mday == GetDaysInMonth(d.tm_year, d.tm_mon);
int year = d.tm_year + months / 12;
int month = d.tm_mon + months % 12;
if (month > 11)
{
year += 1;
month -= 12;
}
int day;
if (isLastDayInMonth)
day = GetDaysInMonth(year, month); // Last day of month maps to last day of result month
else
day = std::min(d.tm_mday, GetDaysInMonth(year, month));
tm result = tm();
result.tm_year = year;
result.tm_mon = month;
result.tm_mday = day;
result.tm_hour = d.tm_hour;
result.tm_min = d.tm_min;
result.tm_sec = d.tm_sec;
return result;
}
time_t AddMonths_OracleStyle(const time_t &date, int months)
{
tm d = tm();
localtime_s(&d, &date);
tm result = AddMonths_OracleStyle(d, months);
return mktime(&result);
}