summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWinfried Donkers <osc@dci-electronics.nl>2012-05-09 14:47:13 (GMT)
committerEike Rathke <erack@redhat.com>2012-05-13 11:51:13 (GMT)
commit4e71be498903dee5bf719a73f4976bb5356335dd (patch)
treebe542ccf54df83afe75f56ae341b11c66afedef9
parent2068144fdcfdee3abe2a90b3b4b3bd49589618f2 (diff)
fdo#44456 added calc function DATEDIF as in ODF1.2
Change-Id: I082ea20d02bf37d515fc33d627281696fc48fcb6
-rw-r--r--formula/inc/formula/compiler.hrc7
-rw-r--r--formula/inc/formula/opcode.hxx1
-rw-r--r--formula/source/core/resource/core_resource.src6
-rw-r--r--sc/inc/helpids.h1
-rw-r--r--sc/qa/unit/ucalc.cxx1
-rw-r--r--sc/source/core/inc/interpre.hxx1
-rw-r--r--sc/source/core/tool/interpr2.cxx91
-rw-r--r--sc/source/core/tool/interpr4.cxx1
-rw-r--r--sc/source/filter/excel/xlformula.cxx1
-rw-r--r--sc/source/filter/oox/formulabase.cxx2
-rw-r--r--sc/source/ui/src/scfuncs.src46
-rw-r--r--sc/util/hidother.src1
12 files changed, 155 insertions, 4 deletions
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..b726685b 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; };