I am an a process of adapting our codebase to boost date_time library, and one quite annoying problem I encountered is that date iterators conform to InputIterator model, rather then Random Access Iterator.
The reason for this is that it is unclear in all cases that an operation is easily reversed. In particular, the problem comes about with handling the end of the month. Say for example you start an iterator on Jan 30. When you iterate to February what happens? Well the rule the supplied iterator is to back up to the end of the February -- either the 27 or 28th for a leap year. Given that these rules are complex and at least possibly non-reversible I tried to limit the exposure of the iterator: hence input iterator. In retrospect, however, it could probably be RandomAccess because I can't give you an actual case where making the iterator reverse is an actual issue.
By the nature of application I have to calculate quite often something like current date plus N months.
The only way I see so far is doing something like
date d(2002,Dec,26); month_iterator mi(d); for( size_t i=0; i < 5; ++i) ++mi; d = *mi;
This is rather awkward, not to mention inefficient.
If you want to use the iterator you can simply do the following: month_iterator mi(d, 3); // configure iterator to add 3 months at a time. mi++; //adds 3 months. If you don't want to use the iterator there are a couple of possible solutions. One is to do the following: int N = 3; //add 3 months date d(...);// constructed however date d1(d.year(), d.month()+N, d.day()); Well, except that this doesn't handle year wrap arounds and other the issues associated with the end of the month as described above. So you have to write some supporting code to handle these issues. It's not that hard -- you might take a look at the boost/date_time/adjust_functors.hpp for ideas. If you are happy with the rules associated with the iterator for the end of month handling then you can just use the functor that is used by the iterator directly. There is an example in libs/date_time/examples/gregorian/add_month.cpp. It looks like: using namespace boost::gregorian; typedef boost::date_time::month_functor<date> add_month; date d = day_clock::local_day(); add_month mf(3); //add by 3 months at a time date d2 = d + mf.get_offset(d); But don't try date d2 = d - mf.get_offset(d); because you will get the wrong answer. Basically what you need is a month functor that calculates the reverse offset for going backward. The code that's there in the functor could probably be made bi-directional, but it would take some thought and work.
BTW, how am I supposed to roll few months back? It is a forward iterator not even a bidirectional.
See above. I'm adding the month subtraction function to my todo list -- unless you want to take a crack at it ;-)
Even more critique: the iterator is not exactly InputIterator, since it has only prefix increment, and no postfix one.
Right -- will correct, thanks. Jeff