$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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
but:
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 += 
month(1))
     std::cout << d << '\n';
01/31/04
02/29/04
03/31/04
04/30/04
05/31/04
06/30/04
07/31/04
08/31/04
09/30/04
10/31/04
11/30/04
12/31/04
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';
 
01/31/04
02/28/04
03/27/04
04/24/04
05/29/04
06/26/04
07/31/04
08/28/04
09/25/04
10/30/04
11/27/04
12/25/04
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. :-)
-Howard