Hi, I am hoping to use boost::date_time to do some date calculations. What I want to do is basically work out the number of days to a given date with various exclusions applied. eg. How many working days are there to christmas? using namespace boost::gregorian; int CalculateDaysToChristmas() { date_period someHoliday(date(2006, Dec, 01), date_duration(1)); date today(2006, Sep, 1); date christmas(2006, Dec, 25); int days = 0; for (day_iterator i = today; i != christmas; ++i) { if (is_weekday(*i) && !someHoliday.contains(*i)) ++days; } return days; } However, I can't find a simply way to work out is_weekday ... Secondly, is there some way to put every sunday in as a date_period? Thirdly, this doesn't seem very optimal ... is there a better way of doing this? Thanks, Andrew
kingos@optusnet.com.au wrote:
Hi,
I am hoping to use boost::date_time to do some date calculations. What I want to do is basically work out the number of days to a given date with various exclusions applied.
eg.
How many working days are there to christmas?
using namespace boost::gregorian;
int CalculateDaysToChristmas() { date_period someHoliday(date(2006, Dec, 01), date_duration(1));
date today(2006, Sep, 1);
date christmas(2006, Dec, 25);
int days = 0; for (day_iterator i = today; i != christmas; ++i) { if (is_weekday(*i) && !someHoliday.contains(*i)) ++days; }
return days; }
However, I can't find a simply way to work out is_weekday ...
Here's something I have laying around that does this: using namespace boost::gregorian; inline bool is_weekday(date d) { greg_weekday dow = d.day_of_week(); if (dow == Saturday || dow == Sunday) { return false; } return true; } inline int weekdays_in_period(const date_period& dp) { day_iterator i(dp.begin()); int count = 0; while ( i <= dp.end()) { if (is_weekday(*i)) { count++; } ++i; } return count; } When I'm writing this sort of code I also like to hide the details of getting the date period. Something like this: class holiday_period : public date_period { public: holiday_period(const date& holiday_date) : date_period(day_clock::local_day(), holiday_date) {}; private: }; Now you can write: date christmas(2006, Dec, 25); hoiday_period hp(christmas); days days_until = weekdays_in_period(hp);
Secondly, is there some way to put every sunday in as a date_period?
Not sure what you have in mind here?
Thirdly, this doesn't seem very optimal ... is there a better way of doing this?
No doubt, this is suboptimal. A better way to do this is to figure out is to take advantage of the fact that a week is exactly 7 days and each week contains 5 non-weekend days (note that the weekend days aren't Sat/Sun in all parts of the world). The tricky part is that you have to account for the boundary conditions of landing on a weekend, or starting on a weekend, less than one week, etc. My guess is it would take an hour or two to really write it up and test all the cases. Anyway, I've not had a real reason to ever write this one up. Contributions always welcome ;-) Jeff
Here is a scheme I tried when first trying to use Boost date-time that would approximate the initial request. It is hardly elegant code but it worked for me at the time. I haven't needed it in quite awhile. typedef vector<date> Holidays; typedef vector<int> WeekendDays; //------------------------------------------------------------------------------------- // Calculate number of business days between two dates // // Input dates are yyyymmdd strings - sd1 <= sd2 // Holidays is a vector of dates for "holidays" // WeekenDays is a vector of days of the week considered "weekend" days // // Holidays are excluded only if not on a "weekend" day //------------------------------------------------------------------------------------- long BusinessDays(const string &sd1,const string &sd2,Holidays &holidays,WeekendDays c) { long f, adj, days, startday; date d1(from_undelimited_string(sd1)); date d2(from_undelimited_string(sd2)); date_duration dd = d2 - d1; days = dd.days(); // Adjust for "weekends" as needed f = (long)c.size(); adj = 0; if (f) { // Compute adjustment for initial week date td = d1; date te = d1 + date_duration(7); if (te > d2) te = d2; date_duration one_day(1); for (;td < te;td += one_day) { startday = td.day_of_week(); if (find(c.begin(),c.end(),startday) != c.end()) { adj++; } } } days -= ((days / 7) * f + adj); // Adjust for "other" days like holidays from "calendar" date_period dp(d1,d2); Holidays::iterator hli; for (hli = holidays.begin();hli != holidays.end();hli++) { if (dp.contains(*hli)) { startday = (*hli).day_of_week(); if (find(c.begin(),c.end(),startday) == c.end()) { days--; } } } return days; } Larry ----- Original Message ----- From: "Jeff Garland" <jeff@crystalclearsoftware.com> To: <boost-users@lists.boost.org> Sent: Friday, September 01, 2006 11:31 AM Subject: Re: [Boost-users] Date calculations with exclusions
kingos@optusnet.com.au wrote:
Hi,
I am hoping to use boost::date_time to do some date calculations. What I want to do is basically work out the number of days to a given date with various exclusions applied.
eg.
How many working days are there to christmas?
using namespace boost::gregorian;
int CalculateDaysToChristmas() { date_period someHoliday(date(2006, Dec, 01), date_duration(1));
date today(2006, Sep, 1);
date christmas(2006, Dec, 25);
int days = 0; for (day_iterator i = today; i != christmas; ++i) { if (is_weekday(*i) && !someHoliday.contains(*i)) ++days; }
return days; }
However, I can't find a simply way to work out is_weekday ...
Here's something I have laying around that does this:
using namespace boost::gregorian; inline bool is_weekday(date d) { greg_weekday dow = d.day_of_week(); if (dow == Saturday || dow == Sunday) { return false; } return true; }
inline int weekdays_in_period(const date_period& dp) { day_iterator i(dp.begin()); int count = 0; while ( i <= dp.end()) { if (is_weekday(*i)) { count++; } ++i; } return count; }
When I'm writing this sort of code I also like to hide the details of getting the date period. Something like this:
class holiday_period : public date_period { public: holiday_period(const date& holiday_date) : date_period(day_clock::local_day(), holiday_date) {}; private: };
Now you can write:
date christmas(2006, Dec, 25); hoiday_period hp(christmas); days days_until = weekdays_in_period(hp);
Secondly, is there some way to put every sunday in as a date_period?
Not sure what you have in mind here?
Thirdly, this doesn't seem very optimal ... is there a better way of doing this?
No doubt, this is suboptimal. A better way to do this is to figure out is to take advantage of the fact that a week is exactly 7 days and each week contains 5 non-weekend days (note that the weekend days aren't Sat/Sun in all parts of the world). The tricky part is that you have to account for the boundary conditions of landing on a weekend, or starting on a weekend, less than one week, etc. My guess is it would take an hour or two to really write it up and test all the cases. Anyway, I've not had a real reason to ever write this one up. Contributions always welcome ;-)
Jeff _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (3)
-
Jeff Garland
-
kingosīŧ optusnet.com.au
-
Larry