[Libreoffice-commits] .: 2 commits - formula/inc formula/source sc/inc sc/qa sc/source sc/util

Eike Rathke erack at kemper.freedesktop.org
Sun May 13 04:51:20 PDT 2012


 formula/inc/formula/compiler.hrc               |    7 -
 formula/inc/formula/opcode.hxx                 |    1 
 formula/source/core/resource/core_resource.src |    6 
 sc/inc/helpids.h                               |    1 
 sc/qa/unit/ucalc.cxx                           |    1 
 sc/source/core/inc/interpre.hxx                |    1 
 sc/source/core/tool/interpr2.cxx               |  171 +++++++++++++++++++++++++
 sc/source/core/tool/interpr4.cxx               |    1 
 sc/source/filter/excel/xlformula.cxx           |    1 
 sc/source/filter/oox/formulabase.cxx           |    2 
 sc/source/ui/src/scfuncs.src                   |   46 ++++++
 sc/util/hidother.src                           |    1 
 12 files changed, 235 insertions(+), 4 deletions(-)

New commits:
commit 40c8170c5281cd7b19313a79f902ef9715351c9f
Author: Eike Rathke <erack at redhat.com>
Date:   Sun May 13 13:50:01 2012 +0200

    changes to patch fdo#44456 added calc function DATEDIF
    
    * use operator && instead of 'and'
    * use correct types
      * long operator -(Date,Date)
      * sal_uInt16 GetDay(), GetMonth(), GetYear()
    * check for error after argument pop and bail out if so
    * day difference can be pushed and return immediately without further
      calculation
    * ensure only one value is pushed
    * correct calculation of years and months
      * only complete years and months are to be returned, same day,month in
        different years is a complete year (birthday-like), same day in different
        months is a complete month.
        * "y" returned 1 for 2012-02-29,2013-02-28 or 2012-03-29,2013-03-28
          * must be 0 instead
      * "y" returned 0 for 2011-03-28,2013-03-29
        * must be 1 instead
      * negative values are never returned
      * reversed arguments are not allowed
      * algorithm for "md" extracted from Excel behavior, see source
      * changes to other intervals as well
    * changed term Format to Interval in FormulaWizard (and code) for clarity
    * mention interval arguments in FormulaWizard
    * in sc/source/filter/oox/formulabase.cxx reverted the entry's move from
      saFuncTableBiff5 to saFuncTableOdf
      * saFuncTableOdf member's are "Functions defined by OpenFormula, but not
        supported by Calc or by Excel", this function now is supported by both
      * instead, changed FUNCFLAG_IMPORTONLY to 0 in entry of saFuncTableBiff5 and
        added FunctionData::mpcOdfFuncName "DATEDIF"
      * otherwise with the FUNCFLAG_MACROCALLODF a macro call is generated for
        Excel export that Excel doesn't know and can only be imported by LibO
        again, and without the BIFF function identifier the function could not be
        imported from original binary Excel documents

diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 4f159a0..e89121e 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -412,37 +412,53 @@ void ScInterpreter::ScGetDiffDate360()
     }
 }
 
-//fdo#44456 function DATEDIF as defined in ODF1.2 (Par. 6.10.3)
+// fdo#44456 function DATEDIF as defined in ODF1.2 (Par. 6.10.3)
 void ScInterpreter::ScGetDateDif()
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDateDif" );
     if ( MustHaveParamCount( GetByte(), 3 ) )
     {
-        String aFormat = GetString();
-        double nDate2  = GetDouble();
-        double nDate1  = GetDouble();
-        int    dd      = nDate2 - nDate1;
-
-        //split dates in day, month, year for use with formats other than "d"
-        int d1, m1, y1, d2, m2, y2;
-        Date aDate = *( pFormatter->GetNullDate() );
-        aDate += (long) ::rtl::math::approxFloor( nDate1 );
-        y1 = aDate.GetYear();
-        m1 = aDate.GetMonth();
-        d1 = aDate.GetDay();
-        aDate = *( pFormatter->GetNullDate() );
-        aDate += (long) ::rtl::math::approxFloor( nDate2 );
-        y2 = aDate.GetYear();
-        m2 = aDate.GetMonth();
-        d2 = aDate.GetDay();
-
-        if ( dd == 0 )
-            PushInt( 0 );     // nothing to do...
-
-        if ( aFormat.EqualsIgnoreCaseAscii( "d" ) )        // return number of days
-            PushInt( dd );
-        else if (  aFormat.EqualsIgnoreCaseAscii( "m" ) )  // return number of months
+        String aInterval = GetString();
+        double nDate2    = GetDouble();
+        double nDate1    = GetDouble();
+
+        if (nGlobalError)
+        {
+            PushError( nGlobalError);
+            return;
+        }
+
+        // Excel doesn't swap dates or return negative numbers, so don't we.
+        if (nDate1 > nDate2)
         {
+            PushIllegalArgument();
+            return;
+        }
+
+        long dd = nDate2 - nDate1;
+        // Zero difference or number of days can be returned immediately.
+        if (dd == 0 || aInterval.EqualsIgnoreCaseAscii( "d" ))
+        {
+            PushDouble( dd );
+            return;
+        }
+
+        // split dates in day, month, year for use with formats other than "d"
+        sal_uInt16 d1, m1, y1, d2, m2, y2;
+        Date aDate1( *( pFormatter->GetNullDate()));
+        aDate1 += (long) ::rtl::math::approxFloor( nDate1 );
+        y1 = aDate1.GetYear();
+        m1 = aDate1.GetMonth();
+        d1 = aDate1.GetDay();
+        Date aDate2( *( pFormatter->GetNullDate()));
+        aDate2 += (long) ::rtl::math::approxFloor( nDate2 );
+        y2 = aDate2.GetYear();
+        m2 = aDate2.GetMonth();
+        d2 = aDate2.GetDay();
+
+        if (  aInterval.EqualsIgnoreCaseAscii( "m" ) )
+        {
+            // Return number of months.
             int md = m2 - m1 + 12 * (y2 - y1);
             if ( nDate2 > nDate1 )
             {
@@ -451,52 +467,116 @@ void ScInterpreter::ScGetDateDif()
             }
             else
             {
-                if ( d2 > d1 )
+                if ( d2 >= d1 )
                     md += 1;
             }
             PushInt( md );
         }
-        else if ( aFormat.EqualsIgnoreCaseAscii( "y" ) )   // return number of years
+        else if ( aInterval.EqualsIgnoreCaseAscii( "y" ) )
         {
-            int yd = y2 - y1;
+            // Return number of years.
+            int yd;
             if ( y2 > y1 )
             {
-                if ( ( m2 == m1 and d2 >= d1 ) || ( m2 > m1 ) )
-                    yd = y2 - y1 - 1;
+                if (m2 > m1 || (m2 == m1 && d2 >= d1))
+                    yd = y2 - y1;       // complete years between dates
+                else
+                    yd = y2 - y1 - 1;   // one incomplete year
             }
             else
             {
-                if ( ( m2 == m1 and d2 <= d1 ) || ( m2 < m1 ) )
-                    yd = y2 - y1 + 1;
+                // Year is equal as we don't allow reversed arguments, no
+                // complete year between dates.
+                yd = 0;
             }
             PushInt( yd );
         }
-        else if ( aFormat.EqualsIgnoreCaseAscii( "md" ) )  // return number of days, ignoring months and years
-        {
-            aDate = Date( d2, m1, y1 );
-            double nd2 = double( aDate - *( pFormatter->GetNullDate() ) );
-            PushInt( nd2 - nDate1 );
-        }
-        else if ( aFormat.EqualsIgnoreCaseAscii( "ym" ) )  // return number of months, ignoring years
-        {
-            int md = m2 - m1;
-            if ( m2 > m1 )
+        else if ( aInterval.EqualsIgnoreCaseAscii( "md" ) )
+        {
+            // Return number of days, ignoring months and years.
+            // This is actually the remainder of days when subtracting years
+            // and months from the difference of dates. Birthday-like 23 years
+            // and 10 months and 42 days.
+
+            // Algorithm's roll-over behavior extracted from Excel by try and
+            // error..
+            // If day1 < day2 then simply day2 - day1.
+            // If day1 > day2 and month1 <= month2 then set day1 in month
+            // before date of day2 and subtract dates, e.g. for
+            // 2012-01-28,2012-03-01 set 2012-02-28 and then
+            // (2012-03-01)-(2012-02-28) => 2 days (leap year).
+            // For 2011-01-29,2011-03-01 the non-existent 2011-02-29 rolls over
+            // to 2011-03-01 so the result is 0. Same for day 31 in months with
+            // only 30 days.
+            // If day1 >= day2 and month1 > month2 then set year2 to year1 and
+            // subtract dates reverse (effectively swaps day1/month1 with
+            // day2/month2).
+            // If day1 == day2 and month1 <= month2 the result is 0.
+
+            long nd;
+            if (d1 < d2)
+                nd = d2 - d1;
+            else if (m1 > m2)   // && d1 >= d2
             {
-                if ( d2 < d1 )
-                    md -= 1;
+                aDate2.SetYear( y1 );
+                aDate2.Normalize();
+                nd = aDate1 - aDate2;
             }
+            else if (d1 == d2)  // && m1 <= m2
+                nd = 0;
+            else                // d1 > d2 && m1 <= m2
+            {
+                if (m2 == 1)
+                {
+                    aDate1.SetYear( y2 - 1 );
+                    aDate1.SetMonth( 12 );
+                }
+                else
+                {
+                    aDate1.SetYear( y2 );
+                    aDate1.SetMonth( m2 - 1 );
+                }
+                // aDate1 day is still d1
+                aDate1.Normalize();
+                nd = aDate2 - aDate1;
+            }
+            PushDouble( nd );
+        }
+        else if ( aInterval.EqualsIgnoreCaseAscii( "ym" ) )
+        {
+            // Return number of months, ignoring years.
+
+            /* TODO: check what Excel really does, though this seems to be
+             * reasonable */
+
+            int md;
+            if (m1 == m2)
+                md = 0;
             else
             {
-                if ( m2 < m1 && d2 > d1 )
-                    md += 1;
+                md = m2 - m1;
+                if (m1 > m2)
+                    md += 12;   // year roll-over
+                if (d1 > d2)
+                    --md;       // one incomplete month
             }
             PushInt( md );
         }
-        else if ( aFormat.EqualsIgnoreCaseAscii( "yd" ) ) // return number of days, ignoring years
+        else if ( aInterval.EqualsIgnoreCaseAscii( "yd" ) )
         {
-            aDate = Date( d2, m2, y1 );
-            double nd2 = double( aDate - *( pFormatter->GetNullDate() ) );
-            PushInt( nd2 - nDate1 );
+            // Return number of days, ignoring years.
+
+            /* TODO: check what Excel really does, though this seems to be
+             * reasonable */
+
+            // Condition corresponds with "y".
+            if (m2 > m1 || (m2 == m1 && d2 >= d1))
+                aDate1.SetYear( y2 );
+            else
+                aDate1.SetYear( y2 - 1 );   // one incomplete year
+            aDate1.Normalize();
+            double nd = aDate2 - aDate1;
+            PushDouble( nd );
         }
         else
             PushIllegalArgument();               // unsupported format
diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx
index 2017e0b..b80dbfa 100644
--- a/sc/source/filter/oox/formulabase.cxx
+++ b/sc/source/filter/oox/formulabase.cxx
@@ -665,6 +665,7 @@ static const FunctionData saFuncTableBiff5[] =
     { "COUNTIF",                "COUNTIF",              346,    346,    2,  2,  V, { RO, VR }, 0 },
     { "COUNTBLANK",             "COUNTBLANK",           347,    347,    1,  1,  V, { RO }, 0 },
     { "ISPMT",                  "ISPMT",                350,    350,    4,  4,  V, { VR }, 0 },
+    { "DATEDIF",                "DATEDIF",              351,    351,    3,  3,  V, { VR }, 0 },
     { 0,                        "DATESTRING",           352,    352,    1,  1,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     { 0,                        "NUMBERSTRING",         353,    353,    2,  2,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     { "ROMAN",                  "ROMAN",                354,    354,    1,  2,  V, { VR }, 0 },
@@ -741,7 +742,6 @@ static const FunctionData saFuncTableOdf[] =
     { "CHISQINV",               0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "COMBINA",                0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "DAYS",                   0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
-    { "DATEDIF",                0,                      NOID,   NOID,   3,  3,  V, { RR }, FUNCFLAG_MACROCALLODF },
     { "DECIMAL",                0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "FDIST",                  0,                      NOID,   NOID,   3,  4,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "FINV",                   0,                      NOID,   NOID,   3,  3,  V, { VR }, FUNCFLAG_MACROCALLODF },
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index b726685..53780de 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -977,7 +977,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
     {
         String 1    // description
         {
-            Text [ en-US ] = "Returns the number of whole days, months or years between 'start date' and 'end date'";
+            Text [ en-US ] = "Returns the number of whole days, months or years between 'start date' and 'end date'.";
         };
         ExtraData =
         {
@@ -995,7 +995,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
 
         String 3 // description of parameter 1  DateDif
         {
-            Text [ en-US ] = "The start date";
+            Text [ en-US ] = "The start date.";
         };
 
         String 4 // name of parameter 2         DateDif
@@ -1005,17 +1005,17 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
 
         String 5 // description of parameter 2  DateDif
         {
-            Text [ en-US ] = "The end date";
+            Text [ en-US ] = "The end date.";
         };
 
         String 6 // name of parameter 3         DateDif
         {
-            Text [ en-US ] = "Format";
+            Text [ en-US ] = "Interval";
         };
 
         String 7 // description of parameter 3  DateDif
         {
-            Text [ en-US ] = "Format of the result";
+            Text [ en-US ] = "Interval to be calculated. Can be \"d\", \"m\", \"y\", \"ym\", \"md\" or \"yd\".";
         };
     };
      // -=*# Resource for function KALENDERWOCHE #*=-
commit 4e71be498903dee5bf719a73f4976bb5356335dd
Author: Winfried Donkers <osc at dci-electronics.nl>
Date:   Wed May 9 16:47:13 2012 +0200

    fdo#44456 added calc function DATEDIF as in ODF1.2
    
    Change-Id: I082ea20d02bf37d515fc33d627281696fc48fcb6

diff --git a/formula/inc/formula/compiler.hrc b/formula/inc/formula/compiler.hrc
index 15d8aab..a2d4bb5 100644
--- a/formula/inc/formula/compiler.hrc
+++ b/formula/inc/formula/compiler.hrc
@@ -399,10 +399,11 @@
 #define SC_OPCODE_BITXOR            397
 #define SC_OPCODE_BITRSHIFT         398
 #define SC_OPCODE_BITLSHIFT         399
-#define SC_OPCODE_STOP_2_PAR        400
-#define SC_OPCODE_LAST_OPCODE_ID    399     /* last OpCode */
+#define SC_OPCODE_GET_DATEDIF       400
+#define SC_OPCODE_STOP_2_PAR        401
+#define SC_OPCODE_LAST_OPCODE_ID    401     /* last OpCode */
 
-/*** Interna ***/
+/*** Internal ***/
 #define SC_OPCODE_INTERNAL_BEGIN   9999
 #define SC_OPCODE_TTT              9999
 #define SC_OPCODE_INTERNAL_END     9999
diff --git a/formula/inc/formula/opcode.hxx b/formula/inc/formula/opcode.hxx
index b1e585c..a1543dd 100644
--- a/formula/inc/formula/opcode.hxx
+++ b/formula/inc/formula/opcode.hxx
@@ -212,6 +212,7 @@ enum OpCodeEnum
         ocGetTime           = SC_OPCODE_GET_TIME,
         ocGetDiffDate       = SC_OPCODE_GET_DIFF_DATE,
         ocGetDiffDate360    = SC_OPCODE_GET_DIFF_DATE_360,
+        ocGetDateDif        = SC_OPCODE_GET_DATEDIF,
         ocMin               = SC_OPCODE_MIN,
         ocMax               = SC_OPCODE_MAX,
         ocSum               = SC_OPCODE_SUM,
diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src
index 12cb57d..1259231 100644
--- a/formula/source/core/resource/core_resource.src
+++ b/formula/source/core/resource/core_resource.src
@@ -170,6 +170,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF
     String SC_OPCODE_GET_TIME { Text = "TIME" ; };
     String SC_OPCODE_GET_DIFF_DATE { Text = "DAYS" ; };
     String SC_OPCODE_GET_DIFF_DATE_360 { Text = "DAYS360" ; };
+    String SC_OPCODE_GET_DATEDIF { Text = "DATEDIF" ; };
     String SC_OPCODE_MIN { Text = "MIN" ; };
     String SC_OPCODE_MIN_A { Text = "MINA" ; };
     String SC_OPCODE_MAX { Text = "MAX" ; };
@@ -502,6 +503,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH
     String SC_OPCODE_GET_TIME { Text = "TIME" ; };
     String SC_OPCODE_GET_DIFF_DATE { Text = "DAYS" ; };
     String SC_OPCODE_GET_DIFF_DATE_360 { Text = "DAYS360" ; };
+    String SC_OPCODE_GET_DATEDIF { Text = "DATEDIF" ; };
     String SC_OPCODE_MIN { Text = "MIN" ; };
     String SC_OPCODE_MIN_A { Text = "MINA" ; };
     String SC_OPCODE_MAX { Text = "MAX" ; };
@@ -1175,6 +1177,10 @@ Resource RID_STRLIST_FUNCTION_NAMES
     {
         Text [ en-US ] = "DAYS360" ;
     };
+    String SC_OPCODE_GET_DATEDIF
+    {
+        Text [ en-US ] = "DATEDIF" ;
+    };
     String SC_OPCODE_MIN
     {
         Text [ en-US ] = "MIN" ;
diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h
index 5eec0d1..8d41ab7 100644
--- a/sc/inc/helpids.h
+++ b/sc/inc/helpids.h
@@ -434,6 +434,7 @@
 #define HID_FUNC_WOCHENTAG                                      "SC_HID_FUNC_WOCHENTAG"
 #define HID_FUNC_JAHR                                           "SC_HID_FUNC_JAHR"
 #define HID_FUNC_TAGE                                           "SC_HID_FUNC_TAGE"
+#define HID_FUNC_DATEDIF                                        "SC_HID_FUNC_DATEDIF"
 #define HID_FUNC_KALENDERWOCHE                                  "SC_HID_FUNC_KALENDERWOCHE"
 #define HID_FUNC_OSTERSONNTAG                                   "SC_HID_FUNC_OSTERSONNTAG"
 
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index d875e42..ef33e64 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -3076,6 +3076,7 @@ void Test::testFunctionLists()
 
     const char* aDateTime[] = {
         "DATE",
+        "DATEDIF",
         "DATEVALUE",
         "DAY",
         "DAYS",
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 192c2e0..5f57fef 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -591,6 +591,7 @@ void ScGetDate();
 void ScGetTime();
 void ScGetDiffDate();
 void ScGetDiffDate360();
+void ScGetDateDif();
 void ScPower();
 void ScAmpersand();
 void ScAdd();
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index f022e9c..4f159a0 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -412,6 +412,97 @@ void ScInterpreter::ScGetDiffDate360()
     }
 }
 
+//fdo#44456 function DATEDIF as defined in ODF1.2 (Par. 6.10.3)
+void ScInterpreter::ScGetDateDif()
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetDateDif" );
+    if ( MustHaveParamCount( GetByte(), 3 ) )
+    {
+        String aFormat = GetString();
+        double nDate2  = GetDouble();
+        double nDate1  = GetDouble();
+        int    dd      = nDate2 - nDate1;
+
+        //split dates in day, month, year for use with formats other than "d"
+        int d1, m1, y1, d2, m2, y2;
+        Date aDate = *( pFormatter->GetNullDate() );
+        aDate += (long) ::rtl::math::approxFloor( nDate1 );
+        y1 = aDate.GetYear();
+        m1 = aDate.GetMonth();
+        d1 = aDate.GetDay();
+        aDate = *( pFormatter->GetNullDate() );
+        aDate += (long) ::rtl::math::approxFloor( nDate2 );
+        y2 = aDate.GetYear();
+        m2 = aDate.GetMonth();
+        d2 = aDate.GetDay();
+
+        if ( dd == 0 )
+            PushInt( 0 );     // nothing to do...
+
+        if ( aFormat.EqualsIgnoreCaseAscii( "d" ) )        // return number of days
+            PushInt( dd );
+        else if (  aFormat.EqualsIgnoreCaseAscii( "m" ) )  // return number of months
+        {
+            int md = m2 - m1 + 12 * (y2 - y1);
+            if ( nDate2 > nDate1 )
+            {
+                if ( d2 < d1 )
+                    md -= 1;
+            }
+            else
+            {
+                if ( d2 > d1 )
+                    md += 1;
+            }
+            PushInt( md );
+        }
+        else if ( aFormat.EqualsIgnoreCaseAscii( "y" ) )   // return number of years
+        {
+            int yd = y2 - y1;
+            if ( y2 > y1 )
+            {
+                if ( ( m2 == m1 and d2 >= d1 ) || ( m2 > m1 ) )
+                    yd = y2 - y1 - 1;
+            }
+            else
+            {
+                if ( ( m2 == m1 and d2 <= d1 ) || ( m2 < m1 ) )
+                    yd = y2 - y1 + 1;
+            }
+            PushInt( yd );
+        }
+        else if ( aFormat.EqualsIgnoreCaseAscii( "md" ) )  // return number of days, ignoring months and years
+        {
+            aDate = Date( d2, m1, y1 );
+            double nd2 = double( aDate - *( pFormatter->GetNullDate() ) );
+            PushInt( nd2 - nDate1 );
+        }
+        else if ( aFormat.EqualsIgnoreCaseAscii( "ym" ) )  // return number of months, ignoring years
+        {
+            int md = m2 - m1;
+            if ( m2 > m1 )
+            {
+                if ( d2 < d1 )
+                    md -= 1;
+            }
+            else
+            {
+                if ( m2 < m1 && d2 > d1 )
+                    md += 1;
+            }
+            PushInt( md );
+        }
+        else if ( aFormat.EqualsIgnoreCaseAscii( "yd" ) ) // return number of days, ignoring years
+        {
+            aDate = Date( d2, m2, y1 );
+            double nd2 = double( aDate - *( pFormatter->GetNullDate() ) );
+            PushInt( nd2 - nDate1 );
+        }
+        else
+            PushIllegalArgument();               // unsupported format
+    }
+}
+
 void ScInterpreter::ScGetTimeValue()
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetTimeValue" );
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 8764b45..e48a5a8 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3910,6 +3910,7 @@ StackVar ScInterpreter::Interpret()
                 case ocGetTime          : ScGetTime();                  break;
                 case ocGetDiffDate      : ScGetDiffDate();              break;
                 case ocGetDiffDate360   : ScGetDiffDate360();           break;
+                case ocGetDateDif       : ScGetDateDif();               break;
                 case ocMin              : ScMin( false );               break;
                 case ocMinA             : ScMin( true );                break;
                 case ocMax              : ScMax( false );               break;
diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx
index 8685041..fcd052a 100644
--- a/sc/source/filter/excel/xlformula.cxx
+++ b/sc/source/filter/excel/xlformula.cxx
@@ -382,6 +382,7 @@ static const XclFunctionInfo saFuncTable_Odf[] =
     EXC_FUNCENTRY_ODF( ocChiSqDist,     2,  3,  0,  "CHISQDIST" ),
     EXC_FUNCENTRY_ODF( ocChiSqInv,      2,  2,  0,  "CHISQINV" ),
     EXC_FUNCENTRY_ODF( ocKombin2,       2,  2,  0,  "COMBINA" ),
+    EXC_FUNCENTRY_ODF( ocGetDateDif,    3,  3,  0,  "DATEDIF" ),
     EXC_FUNCENTRY_ODF( ocGetDiffDate,   2,  2,  0,  "DAYS" ),
     EXC_FUNCENTRY_ODF( ocDecimal,       2,  2,  0,  "DECIMAL" ),
     EXC_FUNCENTRY_ODF( ocFDist,         3,  4,  0,  "FDIST" ),
diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx
index efc9930..2017e0b 100644
--- a/sc/source/filter/oox/formulabase.cxx
+++ b/sc/source/filter/oox/formulabase.cxx
@@ -665,7 +665,6 @@ static const FunctionData saFuncTableBiff5[] =
     { "COUNTIF",                "COUNTIF",              346,    346,    2,  2,  V, { RO, VR }, 0 },
     { "COUNTBLANK",             "COUNTBLANK",           347,    347,    1,  1,  V, { RO }, 0 },
     { "ISPMT",                  "ISPMT",                350,    350,    4,  4,  V, { VR }, 0 },
-    { 0,                        "DATEDIF",              351,    351,    3,  3,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc
     { 0,                        "DATESTRING",           352,    352,    1,  1,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     { 0,                        "NUMBERSTRING",         353,    353,    2,  2,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     { "ROMAN",                  "ROMAN",                354,    354,    1,  2,  V, { VR }, 0 },
@@ -742,6 +741,7 @@ static const FunctionData saFuncTableOdf[] =
     { "CHISQINV",               0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "COMBINA",                0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "DAYS",                   0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
+    { "DATEDIF",                0,                      NOID,   NOID,   3,  3,  V, { RR }, FUNCFLAG_MACROCALLODF },
     { "DECIMAL",                0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "FDIST",                  0,                      NOID,   NOID,   3,  4,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "FINV",                   0,                      NOID,   NOID,   3,  3,  V, { VR }, FUNCFLAG_MACROCALLODF },
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index 1363edb..b726685 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -972,6 +972,52 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
             Text [ en-US ] = "The start date for calculating the difference in days." ;
         };
     };
+     // -=*# Resource for function DATEDIF #*=-
+    Resource SC_OPCODE_GET_DATEDIF
+    {
+        String 1    // description
+        {
+            Text [ en-US ] = "Returns the number of whole days, months or years between 'start date' and 'end date'";
+        };
+        ExtraData =
+        {
+            0;
+            ID_FUNCTION_GRP_DATETIME;
+            U2S( HID_FUNC_DATEDIF );
+            3;  0;  0; 0;
+            0;
+        };
+
+        String 2 // name of parameter 1         DateDif
+        {
+            Text [ en-US ] = "Start date";
+        };
+
+        String 3 // description of parameter 1  DateDif
+        {
+            Text [ en-US ] = "The start date";
+        };
+
+        String 4 // name of parameter 2         DateDif
+        {
+            Text [ en-US ] = "End date";
+        };
+
+        String 5 // description of parameter 2  DateDif
+        {
+            Text [ en-US ] = "The end date";
+        };
+
+        String 6 // name of parameter 3         DateDif
+        {
+            Text [ en-US ] = "Format";
+        };
+
+        String 7 // description of parameter 3  DateDif
+        {
+            Text [ en-US ] = "Format of the result";
+        };
+    };
      // -=*# Resource for function KALENDERWOCHE #*=-
     Resource SC_OPCODE_WEEK
     {
diff --git a/sc/util/hidother.src b/sc/util/hidother.src
index 363e08c..85d36f9 100644
--- a/sc/util/hidother.src
+++ b/sc/util/hidother.src
@@ -113,6 +113,7 @@ hidspecial HID_FUNC_HEUTE        { HelpID = HID_FUNC_HEUTE; };
 hidspecial HID_FUNC_WOCHENTAG    { HelpID = HID_FUNC_WOCHENTAG; };
 hidspecial HID_FUNC_JAHR         { HelpID = HID_FUNC_JAHR; };
 hidspecial HID_FUNC_TAGE         { HelpID = HID_FUNC_TAGE; };
+hidspecial HID_FUNC_DATEDIF      { HelpID = HID_FUNC_DATEDIF; };
 hidspecial HID_FUNC_KALENDERWOCHE        { HelpID = HID_FUNC_KALENDERWOCHE; };
 hidspecial HID_FUNC_OSTERSONNTAG         { HelpID = HID_FUNC_OSTERSONNTAG; };
 hidspecial HID_FUNC_BW       { HelpID = HID_FUNC_BW; };


More information about the Libreoffice-commits mailing list