views:

233

answers:

3

I'd like to be able to calculate the dates of business days (mon-fri) given two dates d1 and d2. However in some locales the business days are sat-wed or sun-thur.

Is there a facility in STL or C++ in general that allows for such a calculation?

+6  A: 

No. Business day data is not part of the locale information available in C++. You'll have to build a database of what exactly counts as a 'business day' for all locales of interest.

bdonlan
Jonathan Leffler
Don't forget that local holidays depend on more than just the country, too - in Massachusetts, for example, there's a local holiday "Patriots' day" on April 19th, but the rest of the country doesn't observe it.
bdonlan
+2  A: 

Quantlib has a lot of date handling functions, like adjusting to the next business day or the previous, easter holidays, japanese imperial calendar, counting the number of days between two dates ...

Guillaume
+3  A: 

The locale is even a little more complicated concerning business days, since each industry has its own version of what a bday is. In my industry (financial services) the bond trading calendar is different from the US Equities trading calendar which is different from the Asian commodities calendar.

To just find out what day of the week a date falls on, there is boost date_time library, http://www.boost.org/doc/libs/1_42_0/doc/html/date_time.html which helps filter out some of the obvious non-business days, but does not account for holidays and other oddities. Those will just have to be kept in somome ad-hoc fashion.

This is how I do it in C++ (minus all the error checks)

typedef unsigned Date_t;//for this example, uints work fine
typedef std::vector<Date_t> datevec_t;//we need random access iterators
datevec_t dates;//one vector per locale
//add data in sorted order, one for each bday in the locale
dates.push_back(20090104); 
dates.push_back(20090105);
dates.push_back(20090106);
dates.push_back(20090107);

Computing the dates is done either by using some regular gregorian calendar library plus my special holdiays and other closings data. But in practice I do not compute the dates each time, but load the computed results from some datastore, since it hardly ever changes and is typically known at least a year in advance. (in my case I do this in some scripting langauage, and read the results from a SQL database)

Now to do an existence query

bool is_bday=std::binary_search(dates.begin(),dates.end(),20091225);

To find the 3rd bday proir to the last bday before 20091225

Date_t myday=*(std::lower_bound(dates.begin(),dates.end(),20091225)-3);

To find the number of business days between two calendar dates

int numdays=std::upper_bound(dates.begin(),dates.end(),20100105)
           -std::lower_bound(dates.begin(),dates.end(),20090105);

In SQL I have done something like:

create table BDays(
    bday date,--the business day
    daynum int,--sequential number
    lcode int, --locale 
    primary (bday,ccode),
    unique(daynum,ccode)
    )

Then insert values for each business day, using sequential daynums

   insert BDays values
    (20090104,1,1),
    (20090105,2,1),
    (20090106,3,1),
-- etc for every business day in the locale

This is actually not a lot of data, and only has to be done once. To do an existence query

select count(1) from BDays where bday=20090101 and lcode=1

To do date math, like what is the third bday before the last business day before dec 25?

select b1.bday from BDays b1
join BDays b2 on(b1.lcode=1 and b2.lcode=1 and b1.daynum-3=b2.daynum)   
join (select max(bday) bday from BDays where bday<=20091225 and lcode=1) cday 
on(cday.bday = b2.bday )
Lance Diduck