Boost logo

Boost Users :

From: Larry (lknain_at_[hidden])
Date: 2006-09-01 22:01:33


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_at_[hidden]>
To: <boost-users_at_[hidden]>
Sent: Friday, September 01, 2006 11:31 AM
Subject: Re: [Boost-users] Date calculations with exclusions

> kingos_at_[hidden] 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_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net