]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix bugs in the recently added wxDateTime::DiffAsDateSpan().
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 4 Oct 2012 22:48:30 +0000 (22:48 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 4 Oct 2012 22:48:30 +0000 (22:48 +0000)
Correct the test for negative spans less than a month and use the correct
month for computing the number of days in it.

Also add unit tests for problematic cases.

Closes #14704.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72616 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/common/datetime.cpp
tests/datetime/datetimetest.cpp

index 462347d7d654a3321d4e0a8554dc240d86251588..05ceb27e0d25f3b9da9e49d808afd9aefb6659bd 100644 (file)
@@ -1612,25 +1612,34 @@ wxDateSpan wxDateTime::DiffAsDateSpan(const wxDateTime& dt) const
         inv = -1;
 
     int y = GetYear() - dt.GetYear();
+    int m = GetMonth() - dt.GetMonth();
+    int d = GetDay() - dt.GetDay();
 
     // If month diff is negative, dt is the year before, so decrease year
     // and set month diff to its inverse, e.g. January - December should be 1,
     // not -11.
-    int m = GetMonth() - dt.GetMonth();
-    if ( m * inv < 0 )
+    if ( m * inv < 0 || (m == 0 && d * inv < 0))
     {
         m += inv * MONTHS_IN_YEAR;
         y -= inv;
     }
 
-    // Same logic for days as for months above. Use number of days in month
-    // from the month which end date we're crossing.
-    int d = GetDay() - dt.GetDay();
+    // Same logic for days as for months above.
     if ( d * inv < 0 )
     {
-        d += inv * wxDateTime::GetNumberOfDays(
-            inv > 0 ? dt.GetMonth() : GetMonth(),
-            inv > 0 ? dt.GetYear() : GetMonth());
+        // Use number of days in month from the month which end date we're
+        // crossing. That is month before this for positive diff, and this
+        // month for negative diff.
+        // If we're on january and using previous month, we get december
+        // previous year, but don't care, december has same amount of days
+        // every year.
+        wxDateTime::Month monthfordays = GetMonth();
+        if (inv > 0 && monthfordays == wxDateTime::Jan)
+            monthfordays = wxDateTime::Dec;
+        else if (inv > 0)
+            monthfordays = static_cast<wxDateTime::Month>(monthfordays - 1);
+
+        d += inv * wxDateTime::GetNumberOfDays(monthfordays, GetYear());
         m -= inv;
     }
 
index 00a76af0ea8d09e2b76d76b6ba4a4d65ea61158e..e317c4707de1b0ee4313559e646552d2eb2482ad 100644 (file)
@@ -1214,6 +1214,31 @@ void DateTimeTestCase::TestTimeArithmetics()
         CPPUNIT_ASSERT_EQUAL( dt1, dt2 + 2*span );
         CPPUNIT_ASSERT_EQUAL( span, dt1.DiffAsDateSpan(dt) );
     }
+
+    // More date span arithmetics tests
+    wxDateTime dtd1(5, wxDateTime::Jun, 1998);
+    wxDateTime dtd2(6, wxDateTime::Aug, 1999);
+
+    // All parts in dtd2 is after dtd1
+    CPPUNIT_ASSERT_EQUAL( wxDateSpan(1, 2, 0, 1), dtd2.DiffAsDateSpan(dtd1) );
+
+    // Year and month after, day earlier, so no full month
+    // Jul has 31 days, so it's 31 - 5 + 4 = 30, or 4w 2d
+    dtd2.Set(4, wxDateTime::Aug, 1999);
+    CPPUNIT_ASSERT_EQUAL( wxDateSpan(1, 1, 4, 2), dtd2.DiffAsDateSpan(dtd1) );
+
+    // Year and day after, month earlier, so no full year, but same day diff as
+    // first example
+    dtd2.Set(6, wxDateTime::May, 1999);
+    CPPUNIT_ASSERT_EQUAL( wxDateSpan(0, 11, 0, 1), dtd2.DiffAsDateSpan(dtd1) );
+
+    // Year after, month and day earlier, so no full month and no full year
+    // April has 30 days, so it's 30 - 5 + 4 = 29, or 4w 1d
+    dtd2.Set(4, wxDateTime::May, 1999);
+    CPPUNIT_ASSERT_EQUAL( wxDateSpan(0, 10, 4, 1), dtd2.DiffAsDateSpan(dtd1) );
+
+    // And a reverse. Now we should use days in Jun (again 30 => 4w 1d)
+    CPPUNIT_ASSERT_EQUAL( wxDateSpan(0, -10, -4, -1), dtd1.DiffAsDateSpan(dtd2) );
 }
 
 void DateTimeTestCase::TestDSTBug()