
Bob Bell wrote: The interpretation that makes sense to me is: adding one month means the same day of the next month, unless the date's not valid, in which case I expect moving backwards to the latest date of said month. That's what humans do when you say "next month", so I would think anything else would be surprising.
That would surprise me as well. date = January 30; add_month(date); add_month(date); date == March 30 ? Not March 28/29 No? Which means of course a lot of state has to be held by date, because otherwise February does rounding. As in the number of days until the end of the month. Yours, -Gary-

On Tue, 13 Apr 2004 16:26:52 -0700 "Powell, Gary" <powellg@amazon.com> wrote:
That would surprise me as well.
date = January 30;
add_month(date); add_month(date);
date == March 30 ? Not March 28/29 No?
Which means of course a lot of state has to be held by date, because otherwise February does rounding. As in the number of days until the end of the month.
Or, instead, you use something like... date = January END or LAST; meaning the last day of the month. Then, adding a month would always jump to the last day of the next month. I imagine with... date = February 28; add_month(date); you would want March 28, and not March 31???

From: Jody Hagins <jody-boost-011304@atdesk.com>
"Powell, Gary" <powellg@amazon.com> wrote:
That would surprise me as well.
date = January 30;
add_month(date); add_month(date);
date == March 30 ? Not March 28/29 No?
I'd expect April 1st or 2nd, depending upon whether it was a leap year. I'm not sure what you're saying you'd expect.
Which means of course a lot of state has to be held by date, because otherwise February does rounding. As in the number of days until the end of the month.
For my expected result, it would simply increment the month and then check for the corresponding day of the month. If it's past the end of the month, it falls back to advancing by 30 days. Then, the logic is repeated by the second call.
Or, instead, you use something like...
date = January END or LAST;
meaning the last day of the month. Then, adding a month would always jump to the last day of the next month. I imagine with...
That would work well.
date = February 28; add_month(date);
you would want March 28, and not March 31???
Yes. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Powell, Gary wrote:
Bob Bell wrote: The interpretation that makes sense to me is: adding one month means the same day of the next month, unless the date's not valid, in which case I expect moving backwards to the latest date of said month. That's what humans do when you say "next month", so I would think anything else would be surprising.
That would surprise me as well.
date = January 30;
add_month(date); add_month(date);
date == March 30 ? Not March 28/29 No?
Which means of course a lot of state has to be held by date, because otherwise February does rounding. As in the number of days until the end of the month.
I don't have a problem with your example because it shows two discrete operations. I don't expect the date to remember its history and apply future operations based on that history, which is what you'd need in order to end up with March 30. Otherwise, the date's behavior becomes very hard to predict, not to mention implement. I just wouldn't use the two discrete add_months in your example _unless_ I wanted the behavior you see as surprising. Otherwise, I'd use add_month(date, 2); Bob

On Tue, 13 Apr 2004 18:30:46 -0700, Robert Bell wrote Whew, looks like a bad day to be away from my email ;-)
Powell, Gary wrote:
Bob Bell wrote: The interpretation that makes sense to me is: adding one month means the same day of the next month, unless the date's not valid, in which case I expect moving backwards to the latest date of said month. That's what humans do when you say "next month", so I would think anything else would be surprising.
I think that 'least suprising' is actually determined by the application. I can see at least several 'reasonable behaviors'. 1) Rollback to the end of the month (as Gary points out chained calculation gets weird here). 2) Throw an exception if an invalid date is generated. That lets the client app just deal with it. 3) Set the returned date to 'not_a_date_time' if an invalid date is generated. I think Rob's add 30 days on invalid is less common, but not unreasonable. In the unreasonable camp I would include: 1) Artificially extend the short months with virtual days -- Yes, I'm told that in some domains they use this technique. Of course as soon as I did something in this domain I would be forced to change my mind on how 'unreasonable' it is. So for me it is becoming ever more clear that I was right to stay out if this very dark cave in the first place. BTW, if you are born on Feb 29th of a leap year, when do you celebrate your birthday? You can only do it on the day of birth every 4 years ;-)
That would surprise me as well.
date = January 30;
add_month(date); add_month(date);
date == March 30 ? Not March 28/29 No?
Which means of course a lot of state has to be held by date, because
otherwise February does rounding. As in the number of days until the end of the month.
Not going to happen...
I don't have a problem with your example because it shows two discrete operations. I don't expect the date to remember its history and apply future operations based on that history, which is what you'd need in order to end up with March 30. Otherwise, the date's behavior becomes very hard to predict, not to mention implement.
It turns out that the month_iterator in fact does implement this logic. So starting on Jan 31, 2000 (a leap year) and incrementing by 1 you get: 2000-Jan-31 2000-Feb-29 2000-Mar-31 2000-Apr-30 2000-May-31 By starting in a 'long month' it effectively snaps to the end of the month. If you start on Feb 29 you get: 2000-Feb-29 2000-Mar-29 2000-Apr-29 Which almost never reaches the end of the month. All of this is the reason that the month_iterator template allows you to substitute an alternate algorithm of your liking.
I just wouldn't use the two discrete add_months in your example _unless_ I wanted the behavior you see as surprising. Otherwise, I'd use
add_month(date, 2);
I can see the bug report now: void f(date& d) { //... d = add_month(d); } //somewhere else in program date d(...); f(d); f(d); //oops I really wanted add_month(d,2) behavior Point is that in a 5 line program it is obvious -- in a million line program not necessarily so. This email thread seems to be writing the repsonse to the FAQ: Q: Why is there no add_month function in the library? A: Because we can't agree on what it means... Jeff

Jeff, Wednesday, April 14, 2004, 5:05:37 AM, you wrote: JG> I can see the bug report now: JG> void f(date& d) JG> { JG> //... JG> d = add_month(d); JG> } JG> //somewhere else in program JG> date d(...); JG> f(d); JG> f(d); //oops I really wanted add_month(d,2) behavior JG> Point is that in a 5 line program it is obvious -- in a million line program JG> not necessarily so. The only requirement for the add_month function I have is that after d2 = add_month(add_month(d1, N), -N), d1 and d2 should be in the same month. Someone developing a million line program should understand that add_month(add_month(d, 1), 1) may be not the same day as add_month(d, 2). JG> This email thread seems to be writing the repsonse to the FAQ: JG> Q: Why is there no add_month function in the library? JG> A: Because we can't agree on what it means... Does that mean that add_month won't be implemented? What if we call it inc_month, instead of add_month? inc_month (Increase Month) in no way assumes that the day of the month will stay the same, it will just increase the month. Val Samko http://val.digiways.com

On Wed, 14 Apr 2004 13:04:34 +0100, Val Samko wrote
JG> This email thread seems to be writing the repsonse to the FAQ: JG> Q: Why is there no add_month function in the library? JG> A: Because we can't agree on what it means...
Does that mean that add_month won't be implemented? What if we call
It's a few lines of code -- so I think I'll still put it in :-)
it inc_month, instead of add_month? inc_month (Increase Month) in no way assumes that the day of the month will stay the same, it will just increase the month.
Yes, perhaps a different name would help eliminate any confusion that we are doing 'math' here. Jeff

"Jeff Garland" <jeff@crystalclearsoftware.com> writes:
On Wed, 14 Apr 2004 13:04:34 +0100, Val Samko wrote
JG> This email thread seems to be writing the repsonse to the FAQ: JG> Q: Why is there no add_month function in the library? JG> A: Because we can't agree on what it means...
Does that mean that add_month won't be implemented? What if we call
It's a few lines of code -- so I think I'll still put it in :-)
it inc_month, instead of add_month? inc_month (Increase Month) in no way assumes that the day of the month will stay the same, it will just increase the month.
Yes, perhaps a different name would help eliminate any confusion that we are doing 'math' here.
I think readability is more important. Nobody but pedants have problems with string + string. Likewise I think: d + 2*months or whatever is better than the functional-looking alternatives. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
"Jeff Garland" <jeff@crystalclearsoftware.com> writes:
On Wed, 14 Apr 2004 13:04:34 +0100, Val Samko wrote
Does that mean that add_month won't be implemented? What if we call it inc_month, instead of add_month? inc_month (Increase Month) in no way assumes that the day of the month will stay the same, it will just increase the month.
Yes, perhaps a different name would help eliminate any confusion that we are doing 'math' here.
I think readability is more important. Nobody but pedants have problems with string + string. Likewise I think:
d + 2*months
or whatever is better than the functional-looking alternatives.
If there was universal acceptance of what it means to add two months to a date, I might agree. Given the imprecise notion of what it means to add two months, however, I disagree. "next_month" or "increment_month" versus "add_month" better distinguish the imprecision. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

From: Val Samko <boost@digiways.com>
Wednesday, April 14, 2004, 5:05:37 AM, you wrote:
The only requirement for the add_month function I have is that after d2 = add_month(add_month(d1, N), -N), d1 and d2 should be in the same month.
Why do you have that requirement? Note that that fits my "next_month" idea just fine.
Someone developing a million line program should understand that add_month(add_month(d, 1), 1) may be not the same day as add_month(d, 2).
Shouldn't they expect them to arrive at the same or very nearly the same answer? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Jeff Garland" <jeff@crystalclearsoftware.com> writes:
On Tue, 13 Apr 2004 18:30:46 -0700, Robert Bell wrote
Whew, looks like a bad day to be away from my email ;-)
Powell, Gary wrote:
Bob Bell wrote: The interpretation that makes sense to me is: adding one month means the same day of the next month, unless the date's not valid, in which case I expect moving backwards to the latest date of said month. That's what humans do when you say "next month", so I would think anything else would be surprising.
I think that 'least suprising' is actually determined by the application. I can see at least several 'reasonable behaviors'. 1) Rollback to the end of the month (as Gary points out chained calculation gets weird here).
reasonable
2) Throw an exception if an invalid date is generated. That lets the client app just deal with it.
reasonable
3) Set the returned date to 'not_a_date_time' if an invalid date is generated.
marginally reasonable. very inconvenient.
I think Rob's add 30 days on invalid is less common, but not unreasonable.
I'm not comfortable with it. It's too nonuniform.
In the unreasonable camp I would include: 1) Artificially extend the short months with virtual days -- Yes, I'm told that in some domains they use this technique.
Hang on a sec. I think a variation of this one isn't so bad: if you ask for the day when it's invalid, it rolls back to the end of the month (and there's another way to find out the day number that's really stored). The result is sort of like #1, but where chained calculations magically "do the right thing".
Of course as soon as I did something in this domain I would be forced to change my mind on how 'unreasonable' it is. So for me it is becoming ever more clear that I was right to stay out if this very dark cave in the first place.
... but it's warm in here! ...
BTW, if you are born on Feb 29th of a leap year, when do you celebrate your birthday? You can only do it on the day of birth every 4 years ;-)
Some people like the idea of growing old at 1/4 speed.
It turns out that the month_iterator in fact does implement this logic. So starting on Jan 31, 2000 (a leap year) and incrementing by 1 you get: 2000-Jan-31 2000-Feb-29 2000-Mar-31 2000-Apr-30 2000-May-31
That looks like what I was suggesting above.
By starting in a 'long month' it effectively snaps to the end of the month.
If you start on Feb 29 you get: 2000-Feb-29 2000-Mar-29 2000-Apr-29
Which almost never reaches the end of the month. All of this is the reason that the month_iterator template allows you to substitute an alternate algorithm of your liking.
Hmpf; too much parameterization? I guess I'd be inclined to rely on people to know that you can't iterate through "end of months" by simply repeatedly adding a month to a date. You have to iterate over months and then pass through an end-of-month transformation.
I just wouldn't use the two discrete add_months in your example _unless_ I wanted the behavior you see as surprising. Otherwise, I'd use
add_month(date, 2);
I can see the bug report now:
void f(date& d) { //... d = add_month(d); }
//somewhere else in program date d(...); f(d); f(d); //oops I really wanted add_month(d,2) behavior
Point is that in a 5 line program it is obvious -- in a million line program not necessarily so.
Yep. I like your iterator's behavior.
This email thread seems to be writing the repsonse to the FAQ: Q: Why is there no add_month function in the library? A: Because we can't agree on what it means...
I think making the behavior consistent with month_iterator can be the only right answer. If you were to change the behavior of month_iterator I'd still think that (but please don't! It's already perfect! ;->) -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
"Jeff Garland" <jeff@crystalclearsoftware.com> writes:
On Tue, 13 Apr 2004 18:30:46 -0700, Robert Bell wrote
Powell, Gary wrote:
Bob Bell wrote: The interpretation that makes sense to me is: adding one month means the same day of the next month, unless the date's not valid, in which case I expect moving backwards to the latest date of said month. That's what humans do when you say "next month", so I would think anything else would be surprising.
I just noticed that here Bob uses the phrase "next month" when discussing the behavior of a function named "add_month." This justifies the separation I mentioned in another post.
I think that 'least suprising' is actually determined by the application. I can see at least several 'reasonable behaviors'. 1) Rollback to the end of the month (as Gary points out chained calculation gets weird here).
reasonable
For some uses, certainly.
2) Throw an exception if an invalid date is generated. That lets the client app just deal with it.
reasonable
Yes.
3) Set the returned date to 'not_a_date_time' if an invalid date is generated.
marginally reasonable. very inconvenient.
Agreed.
I think Rob's add 30 days on invalid is less common, but not unreasonable.
I'm not comfortable with it. It's too nonuniform.
This I don't get. What's nonuniform about it? It advances to the same day of the month in the next month, or by a minimum of 30 days, if it would otherwise be an invalid date. Look at it this way: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 1 2 3 4 Starting from "30" in the 5th line, advance by a month. It could mean four weeks, which means "27" in the next month. It could mean 30 days -- as accountants would do (they use 360 day years in their computations) -- which means "1" in the last line, in the month after next. In both cases, "adding a month" means march through the days of the year according to a formula. Given the oddball arrangement of our calendar, we expect certain vagueness when using phrases like "next month" or "a month from now." Thus, I don't think it is unreasonable to account for differing notions, especially when they conform to what people actually do. (I contend that my algorithm does fit what people actually do, at least with the phrase, "a month from now.")
In the unreasonable camp I would include: 1) Artificially extend the short months with virtual days -- Yes, I'm told that in some domains they use this technique.
Hang on a sec. I think a variation of this one isn't so bad: if you ask for the day when it's invalid, it rolls back to the end of the month (and there's another way to find out the day number that's really stored). The result is sort of like #1, but where chained calculations magically "do the right thing".
Do you mean that you get a date object that "knows" it really means March 1 based upon adding 1/12 of a year, to avoid cumulative addition errors, but when queried, tells you its February 28 (29)? That's a different type, then, right?
Of course as soon as I did something in this domain I would be forced to change my mind on how 'unreasonable' it is. So for me it is becoming ever more clear that I was right to stay out if this very dark cave in the first place.
That's why I started by suggesting that there should be a scheme to account for differing ideas of what it means to add a month. Perhaps we have increment_month() or next_month() and add_month(), where add_month() can be parameterized -- through whatever technique -- to use different algorithms. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;
participants (7)
-
David Abrahams
-
Jeff Garland
-
Jody Hagins
-
Powell, Gary
-
Rob Stewart
-
Robert Bell
-
Val Samko