1 <?xml version=
"1.0" encoding=
"utf-8"?>
2 <!DOCTYPE library PUBLIC
"-//Boost//DTD BoostBook XML V1.0//EN"
3 "../../../tools/boostbook/dtd/boostbook.dtd">
5 <!-- Copyright (c) 2005 CrystalClear Software, Inc.
6 Subject to the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
12 <anchor id=
"snap_to_details" />
13 <bridgehead renderas=
"sect4">Reversibility of Operations Pitfall
</bridgehead>
14 <para>A natural expectation when adding a number of months to a date, and then subtracting the same number of months, is to end up exactly where you started. This is most often the result the
<code>date_time
</code> library provides but there is one significant exception: The snap-to-end-of-month behavior implemented by the
<link linkend=
"additional_duration_types">months
</link> duration type. The
<link linkend=
"additional_duration_types">months
</link> duration type may provide unexpected results when the starting day is the
28th,
29th, or
30th in a
31 day month. The
<link linkend=
"iterators_intro">month_iterator
</link> is not affected by this issue and is therefore included in the examples to illustrate a possible alternative.
17 <para>When the starting date is in the middle of a month, adding or subtracting any number of months will result in a date that is the same day of month (e.g. if you start on the
15th, you will end on the
15th). When a date is the last day of the month, adding or subtracting any number of months will give a result that is also the last day of the month (e.g if you start on Jan
31st, you will land on: Feb
28th, Mar
31st, etc).
19 // using months duration type
20 date d(
2005, Nov,
30); // last day of November
21 d + months(
1); // result is last day of December
"2005-Dec-31"
22 d - months(
1); // result is last day of October
"2005-Oct-31"
24 // using month_iterator
25 month_iterator itr(d); // last day of November
26 ++itr; // result is last day of December
"2005-Dec-31"
27 --itr; // back to original starting point
"2005-Nov-30"
28 --itr; // last day of October
"2005-Oct-31"
32 <para>If the start date is the
28th,
29th, or
30th in a
31 day month, the result of adding or subtracting a month may result in the snap-to-end-of-month behavior kicking in unexpectedly. This would cause the final result to be different than the starting date.
34 // using months duration type
35 date d(
2005, Nov,
29);
36 d += months(
1); //
"2005-Dec-29"
37 d += months(
1); //
"2006-Jan-29"
38 d += months(
1); //
"2006-Feb-28" --> snap-to-end-of-month behavior kicks in
39 d += months(
1); //
"2006-Mar-31" --> unexpected result
40 d -= months(
4); //
"2005-Nov-30" --> unexpected result, not where we started
42 // using month_iterator
43 month_iterator itr(date(
2005, Dec,
30));
44 ++itr; //
"2006-Jan-30" --> ok
45 ++itr; //
"2006-Feb-28" --> snap-to DOES NOT kick in
46 ++itr; //
"2006-Mar-30" --> ok
47 --itr; //
"2006-Feb-28" --> ok
48 --itr; //
"2006-Jan-30" --> ok
49 --itr; //
"2005-Dec-30" --> ok, back where we started
53 <para>The additional duration types (
<code>months
</code>,
<code>years
</code>, and
<code>weeks
</code>) are provided as a convenience and can be easily removed to insure this pitfall never occurs. To remove these types simply undefine BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES.
</para>