Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2004-04-24 19:24:19

On Apr 24, 2004, at 9:35 AM, Jeff Garland wrote:

> On Fri, 23 Apr 2004 23:22:34 -0400, Daryle Walker wrote
>> [NOTE: I haven't worked on this library; I'm just going by the posts
>> I see here.]
>> For this increment/decrement by a month problem, is there any way to
>> store a date with only a month resolution? Nothing smaller will be
>> stored, so day crossovers won't be a problem.
> I think what you mean is a 'duration' with month resolution. Ala
> months m1(3);
> months m2(2);
> months m3 = m2 + m1;
> //...
> This can be done, but the issue is that to work with the date timepoint
> calculation is done at single day resolution. And there isn't a fixed
> number
> of days in a month, so you CANNOT say:
> days dd(28) == months(1); //proposition 1
> Similarly the following is NOT true:
> days dd(365) == years(1); //proposition 2
> Conversly, you can always say this:
> days dd(28) == weeks(4);
> So the problem is while a week is a fixed length that is well known to
> be 7
> days, a month and year are not. The length of a month and year
> depends on the
> context of the date. So people want the following sort of behavior:
> date d1 += months(12); //if d1 is a leap year add 366 days instead
> of 365

I've also only been skimming the date-time += month issue. I have an
hobbyist's interest in the subject having lovingly crafted and
maintained a date class of my own over the last decade (hasn't
everybody! :-) ).

Fwiw, here's what I'm currently doing, and it was inspired by reading
the discussion in boost. When I back-fitted my revised date class into
my existing applications (holiday/birthday reminder, mortgage
computations, and the ever important stock option calculator!) the
transition was very smooth. Of course what I'm using dates for is just
tinker-toy stuff compared to a commercial quality date-aware app so
please take this for what it's worth...

gregorian::date can not hold an invalid date. If an attempt is made to
create or assign to a gregorian::date with a value that would result in
an invalid date, a gregorian::bad_date exception is thrown.

Months can be added to dates, but may result in an invalid date
(throwing an exception):

date = mar/31/2004;
date += month(1); // error! bad_date thrown, date uneffected

However mar/31/2004 can also be specified with "last":

date = mar/last/2004;
date += month(1); // ok, apr/30/2004

mar/31/2004 == mar/last/2004 but the latter is tagged with extra
information that implies the semantics of "last day of the month"
rather than "31st day of the month". Similarly for adding years:

date = feb/29/2004;
date += year(1); // error, bad_date thrown


date = feb/last/2004; // same as feb/29/2004
date += year(1); // ok, feb/28/2005

The following loop prints out the last day of each month:

for (date d = jan/last/2004, end = dec/last/2004; d <= end; d +=
     std::cout << d << '\n';


There's similar functionality for finding the nth day-of-week of a
month/year, or the last day-of-week of a month/year.

for (date d = last*sat/jan/2004, end = last*sat/dec/2004; d <= end; d
+= month(1))
     std::cout << d << '\n';

I'm currently using 64 bits to implement this (sizeof(date) == 8 on a
32 bit machine). I'd be happy to share more details if there is
interest. This is just a hobby for me. I'm not trying to write the
"date class that satisfies the world". I'm satisfied and in hobbies
that's all that counts. :-)


Boost list run by bdawes at, gregod at, cpdaniel at, john at