[Libreoffice-commits] core.git: Branch 'libreoffice-6-0' - basic/source

Eike Rathke erack at redhat.com
Fri May 18 07:35:20 UTC 2018


 basic/source/inc/date.hxx         |    9 +++++++-
 basic/source/runtime/methods.cxx  |   39 +++++++++++++++++++++++++++-----------
 basic/source/runtime/methods1.cxx |   20 +++----------------
 basic/source/sbx/sbxscan.cxx      |    2 -
 4 files changed, 41 insertions(+), 29 deletions(-)

New commits:
commit 07a0748243fed290771b8805398b0ca7a52369f7
Author: Eike Rathke <erack at redhat.com>
Date:   Tue May 15 19:36:52 2018 +0200

    Resolves: tdf#117612 truncate DateAdd("m",...) to last day of month
    
    ... instead of resulting in error because of roll-over not being set.
    
    Fallout from
    
        commit 6d424f07701bf26d8fb173563b567d5f097c33e2
        CommitDate: Tue May 2 23:12:34 2017 +0200
    
            Replace mouth-painted "inaccurate around leap year" rollover algorithm
    
    that does stricter checking but DateAdd() needs a lax checking
    with truncate to last day of month.
    
    (cherry picked from commit 40c9a129e5a53e6eadfe8ca80c98ccf7eda957f9)
    
     Conflicts:
            basic/source/runtime/methods.cxx
    
    Backported.
    
    Change-Id: I9d6f95ad3ac38257d492019bd621070491e98e76
    Reviewed-on: https://gerrit.libreoffice.org/54421
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/basic/source/inc/date.hxx b/basic/source/inc/date.hxx
index 4b28f1d66b02..c0cfd66a5cf7 100644
--- a/basic/source/inc/date.hxx
+++ b/basic/source/inc/date.hxx
@@ -24,7 +24,14 @@
 #include <com/sun/star/util/Time.hpp>
 #include <com/sun/star/util/DateTime.hpp>
 
-bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, bool bUseTwoDigitYear, bool bRollOver, double& rdRet );
+enum class SbDateCorrection
+{
+    None,
+    RollOver,
+    TruncateToMonth
+};
+
+bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, bool bUseTwoDigitYear, SbDateCorrection eCorr, double& rdRet );
 double implTimeSerial( sal_Int16 nHour, sal_Int16 nMinute, sal_Int16 nSecond);
 bool implDateTimeSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay,
                          sal_Int16 nHour, sal_Int16 nMinute, sal_Int16 nSecond,
diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx
index 4a5aaa39a98b..07044ac5e6c5 100644
--- a/basic/source/runtime/methods.cxx
+++ b/basic/source/runtime/methods.cxx
@@ -1733,7 +1733,7 @@ css::util::Date SbxDateToUNODate( const SbxValue* const pVal )
 void SbxDateFromUNODate( SbxValue *pVal, const css::util::Date& aUnoDate)
 {
     double dDate;
-    if( implDateSerial( aUnoDate.Year, aUnoDate.Month, aUnoDate.Day, false, false, dDate ) )
+    if( implDateSerial( aUnoDate.Year, aUnoDate.Month, aUnoDate.Day, false, SbDateCorrection::None, dDate ) )
     {
         pVal->PutDate( dDate );
     }
@@ -1962,8 +1962,9 @@ void SbRtl_CDateFromIso(StarBASIC *, SbxArray & rPar, bool)
             }
 
             double dDate;
-            if (!implDateSerial( (sal_Int16)(nSign * aYearStr.toInt32()),
-                        (sal_Int16)aMonthStr.toInt32(), (sal_Int16)aDayStr.toInt32(), bUseTwoDigitYear, false, dDate ))
+            if (!implDateSerial( static_cast<sal_Int16>(nSign * aYearStr.toInt32()),
+                        static_cast<sal_Int16>(aMonthStr.toInt32()), static_cast<sal_Int16>(aDayStr.toInt32()),
+                        bUseTwoDigitYear, SbDateCorrection::None, dDate ))
                 break;
 
             rPar.Get(0)->PutDate( dDate );
@@ -1992,7 +1993,7 @@ void SbRtl_DateSerial(StarBASIC *, SbxArray & rPar, bool)
     sal_Int16 nDay = rPar.Get(3)->GetInteger();
 
     double dDate;
-    if( implDateSerial( nYear, nMonth, nDay, true, true, dDate ) )
+    if( implDateSerial( nYear, nMonth, nDay, true, SbDateCorrection::RollOver, dDate ) )
     {
         rPar.Get(0)->PutDate( dDate );
     }
@@ -4557,7 +4558,7 @@ sal_Int16 implGetDateYear( double aDate )
 }
 
 bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay,
-        bool bUseTwoDigitYear, bool bRollOver, double& rdRet )
+        bool bUseTwoDigitYear, SbDateCorrection eCorr, double& rdRet )
 {
     // XXX NOTE: For VBA years<0 are invalid and years in the range 0..29 and
     // 30..99 can not be input as they are 2-digit for 2000..2029 and
@@ -4620,14 +4621,14 @@ bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay,
      * documentation would need to be adapted. As is, the DateSerial() runtime
      * function works as dumb as documented.. (except that the resulting date
      * is checked for validity now and not just day<=31 and month<=12).
-     * If change wanted then simply remove overriding bRollOver here and adapt
+     * If change wanted then simply remove overriding RollOver here and adapt
      * documentation.*/
 #if HAVE_FEATURE_SCRIPTING
-    if (!SbiRuntime::isVBAEnabled())
-        bRollOver = false;
+    if (eCorr == SbDateCorrection::RollOver && !SbiRuntime::isVBAEnabled())
+        eCorr = SbDateCorrection::None;
 #endif
 
-    if (nYear == 0 || (!bRollOver && (nAddMonths || nAddDays || !aCurDate.IsValidDate())))
+    if (nYear == 0 || (eCorr == SbDateCorrection::None && (nAddMonths || nAddDays || !aCurDate.IsValidDate())))
     {
 #if HAVE_FEATURE_SCRIPTING
         StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
@@ -4635,13 +4636,29 @@ bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay,
         return false;
     }
 
-    if (bRollOver)
+    if (eCorr != SbDateCorrection::None)
     {
         aCurDate.Normalize();
         if (nAddMonths)
             aCurDate.AddMonths( nAddMonths);
         if (nAddDays)
             aCurDate.AddDays( nAddDays);
+        if (eCorr == SbDateCorrection::TruncateToMonth && aCurDate.GetMonth() != nMonth)
+        {
+            if (aCurDate.GetYear() == SAL_MAX_INT16 && nMonth == 12)
+            {
+                // Roll over and back not possible, hard max.
+                aCurDate.SetMonth(12);
+                aCurDate.SetDay(31);
+            }
+            else
+            {
+                aCurDate.SetMonth(nMonth);
+                aCurDate.SetDay(1);
+                aCurDate.AddMonths(1);
+                aCurDate.AddDays(-1);
+            }
+        }
     }
 
     long nDiffDays = GetDayDiff( aCurDate );
@@ -4664,7 +4681,7 @@ bool implDateTimeSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay,
                          double& rdRet )
 {
     double dDate;
-    if(!implDateSerial(nYear, nMonth, nDay, false/*bUseTwoDigitYear*/, false/*bRollOver*/, dDate))
+    if(!implDateSerial(nYear, nMonth, nDay, false/*bUseTwoDigitYear*/, SbDateCorrection::None, dDate))
         return false;
     rdRet += dDate + implTimeSerial(nHour, nMinute, nSecond);
     return true;
diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx
index f6d404dd548d..6921fe639f87 100644
--- a/basic/source/runtime/methods1.cxx
+++ b/basic/source/runtime/methods1.cxx
@@ -1898,7 +1898,7 @@ void SbRtl_DateAdd(StarBASIC *, SbxArray & rPar, bool)
                 nTargetYear16 = limitDate( nTargetYear, nMonth, nDay );
                 /* TODO: should the result be error if the date was limited? It never was. */
                 nTargetMonth = nMonth;
-                bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, false, true, dNewDate );
+                bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, false, SbDateCorrection::TruncateToMonth, dNewDate );
                 break;
             }
             case INTERVAL_Q:
@@ -1943,26 +1943,14 @@ void SbRtl_DateAdd(StarBASIC *, SbxArray & rPar, bool)
                 }
                 nTargetYear16 = limitDate( nTargetYear, nTargetMonth, nDay );
                 /* TODO: should the result be error if the date was limited? It never was. */
-                bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, false, true, dNewDate );
+                bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, false, SbDateCorrection::TruncateToMonth, dNewDate );
                 break;
             }
             default: break;
         }
 
         if( bOk )
-        {
-            // Overflow?
-            sal_Int16 nNewYear, nNewMonth, nNewDay;
-            implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate );
-            sal_Int16 nCorrectionDay = nDay;
-            while( nNewMonth > nTargetMonth )
-            {
-                nCorrectionDay--;
-                implDateSerial( nTargetYear16, nTargetMonth, nCorrectionDay, false, true, dNewDate );
-                implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate );
-            }
             dNewDate += dHoursMinutesSeconds;
-        }
     }
 
     rPar.Get(0)->PutDate( dNewDate );
@@ -2147,7 +2135,7 @@ double implGetDateOfFirstDayInFirstWeek
         nFirstWeekMinDays = 7;      // vbFirstFourDays
 
     double dBaseDate;
-    implDateSerial( nYear, 1, 1, false, false, dBaseDate );
+    implDateSerial( nYear, 1, 1, false, SbDateCorrection::None, dBaseDate );
 
     sal_Int16 nWeekDay0101 = implGetWeekDay( dBaseDate );
     sal_Int16 nDayDiff = nWeekDay0101 - nFirstDay;
@@ -2207,7 +2195,7 @@ void SbRtl_DatePart(StarBASIC *, SbxArray & rPar, bool)
         {
             sal_Int16 nYear = implGetDateYear( dDate );
             double dBaseDate;
-            implDateSerial( nYear, 1, 1, false, false, dBaseDate );
+            implDateSerial( nYear, 1, 1, false, SbDateCorrection::None, dBaseDate );
             nRet = 1 + sal_Int32( dDate - dBaseDate );
             break;
         }
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index 3408c0e9f151..5ba4f52d5497 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -772,7 +772,7 @@ void SbxValue::Format( OUString& rRes, const OUString* pFmt ) const
             {
                 sal_Int16 nYear = implGetDateYear( nNumber );
                 double dBaseDate;
-                implDateSerial( nYear, 1, 1, true, false, dBaseDate );
+                implDateSerial( nYear, 1, 1, true, SbDateCorrection::None, dBaseDate );
                 sal_Int32 nYear32 = 1 + sal_Int32( nNumber - dBaseDate );
                 rRes = OUString::number(nYear32);
             }


More information about the Libreoffice-commits mailing list