
[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. Wouldn't something similar have/already-had been done when skipping days but ignoring the exact hour? (Or does every date-time object work at the fractional-second level? If so, maybe that's what needs fixing.) -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com

On Fri, 23 Apr 2004 23:22:34 -0400, Daryle Walker wrote
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 Unfortunately, as soon as you start accepting these sorts of adjustments you lose the mathmatical properties that you might expect: date d1 += months(1); date d2 = d1 - months(1); d2 == d1 //Sorry, not always true... If instead you are willing to accept proposition 1 and 2 above then this is all trivial...
No, because a day is a fixed length duration while a month isn't -- see above.
(Or does every date-time object work at the fractional-second level? If so, maybe that's what needs fixing.)
No, boost::gregorian::date has a resolution of 1 day -- it can't represent hours, minutes, etc... Jeff

On Apr 24, 2004, at 9:35 AM, Jeff Garland wrote:
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

On Sat, 24 Apr 2004 20:24:19 -0400, Howard Hinnant wrote
And I thought I was the only crazy person ;-)
It's an interesting approach. Basically it is a 'construction' policy that controls month addition rules -- storing the policy to use in the date itself. Of course the alternative is to store that policy decision outside the date. It doesn't matter for a few dates, but if I happen to have 10,000 dates in a collection for some planning application I might want to avoid the extra overhead. Especially given that it is unlikely that the policy would be different for each date.
Yet another variation on the month addition rules. And I can imagine is a fairly common case. Example: Last Friday of the month is payday.
I'm currently using 64 bits to implement this (sizeof(date) == 8 on a 32 bit machine).
boost::gregorian::date uses 32 bits internally.
Hmm, I'm guessing I might be in the satisfy the world category ;-) So seriously, I'm primarily interested in the requirements that drive the features and the features themselves. It would take alot for boost.date_time to move toward the implementation approach you are using. And even if there was agreement it was the right thing, I think the current approach can achieve the same aims without increasing the size of the date representation. With a slightly different interface, of course. In particular, I'm interested in the 'date generation' requirements. One result of last weeks discussion is that I've been re-evaluating what boost.date_time offers, and I see some holes. I've been thinking about some new date generator functions and some of them overlap with what you outlined. Here's some new date generation functions I've been thinking about adding: date next_weekday(const date& d, weekday wd, weeks w=weeks(1)); //next_weekday(d, Monday); //advance to the next monday -- if monday then 7 days //if weeks > 1 then first advance the number of weeks and then //to the weekday date previous_weekday(const date& d, weekday wd, weeks w=weeks(1)); //next_weekday(d, Monday); //advance to previous weekday date date_from_weekday_number(greg_year y, week_number wn, weekday wd); // 2004, 2, Monday == Jan 05 2004 // 2004, 1, Monday == Dec 29 2003 -- yes that's right, iso week numbers // are very weird -- the year rolls back // 2003, 52, Sat == Dec 27 2003 These functions don't generate a date, but rather generate the distance between a date using a rule: days days_until_weekday(const date& d, weekday wd, weeks w=weeks(1)); //if d is on Sunday and wd == Monday return 1 //if d is on Sunday and wd == Sunday return 0 //if weeks > 1 then first advance the number of weeks and then to //the weekday days days_before_weekday(const date& d, weekday wd, weeks w=weeks(1)); //if d is on Sunday and wd == Friday return 2 //if d is on Sunday and wd == Sunday return 0 Jeff

On 4/24/04 9:35 AM, "Jeff Garland" <jeff@crystalclearsoftware.com> wrote:
So maybe a new type should be made that just represents year & month. Every year still only has 12 months. Of course, your problem comes back if you want to mix days in. -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com

"Jeff Garland" <jeff@crystalclearsoftware.com> writes:
if (some_date.is_in(Jun/2004)) std::cout << "that's a hot one!"; -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

On Sun, 25 Apr 2004 17:03:18 -0400, David Abrahams wrote
You didn't need to invent a type to do this -- you just added a function to the date. You would have to reverse it to be what Daryle is suggesting: date d(...); some_month_type x(2004, Jun); x.contains(d); But we already have date_period for this: date start_of_month(...), end_of_month(...); date_period dp(start_of_month, end_of_month); dp.contains(d); So why not a date_period generator function instead? date_period make_month_period(greg_year y, greg_month m); Then it would be: date_period dp = make_month_period(2004, Jun); if (dp.contains(d)) // or is_after, is_before, ... Jeff ps: And where I live you can bank on June being hot :-)

"Jeff Garland" <jeff@crystalclearsoftware.com> writes:
The type is that of Jun/2004
I don't see how they differ, where types are concerned. You just changed how the function is invoked.
That looks painful, though I don't neccessarily understand it.
Also painful-looking. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

On Sun, 25 Apr 2004 18:43:03 -0400, David Abrahams wrote them
Ok my first email didn't help. My point was that there are lots of other ways to do the function you are suggesting that are more consistent with the current library and don't require the addition this type which we can't even seem to create a name for. Basically, your example isn't a compelling use case for me. Jeff
participants (4)
-
Daryle Walker
-
David Abrahams
-
Howard Hinnant
-
Jeff Garland