From 4e0d438df13f2509a0966f1aeec81194059af48d Mon Sep 17 00:00:00 2001 From: Peter Kovacs Date: Sun, 16 Oct 2022 23:32:12 +0200 Subject: [PATCH] first implementation of datedif --- main/formula/inc/formula/compiler.hrc | 5 +- .../source/core/resource/core_resource.src | 4 + main/sc/inc/helpids.h | 1 + main/sc/source/core/inc/interpre.hxx | 1 + main/sc/source/core/tool/interpr2.cxx | 82 +++++++++++++++++++ main/sc/source/core/tool/interpr4.cxx | 1 + main/sc/source/ui/src/scfuncs.src | 46 +++++++++++ main/sc/util/hidother.src | 1 + 8 files changed, 139 insertions(+), 2 deletions(-) diff --git a/main/formula/inc/formula/compiler.hrc b/main/formula/inc/formula/compiler.hrc index 1a20efae88..aa28d21b5b 100644 --- a/main/formula/inc/formula/compiler.hrc +++ b/main/formula/inc/formula/compiler.hrc @@ -402,10 +402,11 @@ #define SC_OPCODE_BITXOR 406 #define SC_OPCODE_BITLSHIFT 407 #define SC_OPCODE_BITRSHIFT 408 +#define SC_OPCODE_DATEDIF 409 -#define SC_OPCODE_STOP_2_PAR 409 +#define SC_OPCODE_STOP_2_PAR 410 -#define SC_OPCODE_LAST_OPCODE_ID 408 /* last OpCode */ +#define SC_OPCODE_LAST_OPCODE_ID 409 /* last OpCode */ /*** Interna ***/ #define SC_OPCODE_INTERNAL_BEGIN 9999 diff --git a/main/formula/source/core/resource/core_resource.src b/main/formula/source/core/resource/core_resource.src index 9949aebba9..ebc5f0d6ff 100644 --- a/main/formula/source/core/resource/core_resource.src +++ b/main/formula/source/core/resource/core_resource.src @@ -354,6 +354,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF String SC_OPCODE_BITXOR { Text= "BITXOR" ; }; String SC_OPCODE_BITLSHIFT { Text= "BITLSHIFT" ; }; String SC_OPCODE_BITRSHIFT { Text= "BITRSHIFT" ; }; + String SC_OPCODE_DATEDIF { Text = "DATEDIF" ; }; /* BEGIN defined ERROR.TYPE() values. */ String SC_OPCODE_ERROR_NULL { Text = "#NULL!" ; }; @@ -696,6 +697,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH String SC_OPCODE_BITXOR { Text = "BITXOR" ; }; String SC_OPCODE_BITLSHIFT { Text= "BITLSHIFT" ; }; String SC_OPCODE_BITRSHIFT { Text= "BITRSHIFT" ; }; + String SC_OPCODE_DATEDIF { Text = "DATEDIF" ; }; /* BEGIN defined ERROR.TYPE() values. */ String SC_OPCODE_ERROR_NULL { Text = "#NULL!" ; }; @@ -1940,6 +1942,8 @@ Resource RID_STRLIST_FUNCTION_NAMES { Text [ en-US ] = "BITRSHIFT"; }; + String SC_OPCODE_DATEDIF { Text [ en-US ] = "DATEDIF" ; }; + /* BEGIN defined ERROR.TYPE() values. */ /* ERROR.TYPE( #NULL! ) == 1 */ String SC_OPCODE_ERROR_NULL diff --git a/main/sc/inc/helpids.h b/main/sc/inc/helpids.h index 76a398a1eb..d6ddcdf965 100644 --- a/main/sc/inc/helpids.h +++ b/main/sc/inc/helpids.h @@ -396,6 +396,7 @@ #define HID_DAI_FUNC_DIFFWEEKS "SC_HID_DAI_FUNC_DIFFWEEKS" #define HID_DAI_FUNC_DIFFYEARS "SC_HID_DAI_FUNC_DIFFYEARS" #define HID_DAI_FUNC_ROT13 "SC_HID_DAI_FUNC_ROT13" +#define HID_FUNC_DATEDIF "SC_HID_FUNC_DATEDIF" #define HID_SCPAGE_OPREDLINBE_FT_CONTENT "SC_HID_SCPAGE_OPREDLINBE_FT_CONTENT" #define HID_MN_FORMAT_STYLE "SC_HID_MN_FORMAT_STYLE" diff --git a/main/sc/source/core/inc/interpre.hxx b/main/sc/source/core/inc/interpre.hxx index 0d50d34d94..a299b6ea4e 100644 --- a/main/sc/source/core/inc/interpre.hxx +++ b/main/sc/source/core/inc/interpre.hxx @@ -640,6 +640,7 @@ void ScBase(); void ScDecimal(); void ScConvert(); void ScEuroConvert(); +void ScDateDif(); //----------------------- Finanzfunktionen ------------------------------------ void ScNPV(); diff --git a/main/sc/source/core/tool/interpr2.cxx b/main/sc/source/core/tool/interpr2.cxx index 2d8dfcd2d9..041724fb1f 100644 --- a/main/sc/source/core/tool/interpr2.cxx +++ b/main/sc/source/core/tool/interpr2.cxx @@ -688,6 +688,88 @@ void ScInterpreter::ScNPV() } } +void ScInterpreter::ScDateDif() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDateDif"); + if ( MustHaveParamCount( GetByte(), 3 ) ) + { + String ReturnFormat = GetString(); + double StartDate = GetDouble(); + Date tmpDate = *( pFormatter->GetNullDate() ); + tmpDate += (long) ::rtl::math::approxFloor( tmpDate ); + sal_Int32 StartDays = tmpDate.GetDay(); + sal_Int32 StartMonth = tmpDate.GetMonth(); + sal_Int32 StartYear = tmpDate.GetYear(); + + double EndDate = GetDouble(); + tmpDate = *( pFormatter->GetNullDate() ); + tmpDate += (long) ::rtl::math::approxFloor( EndDate ); + sal_Int32 EndDays = tmpDate.GetDay(); + sal_Int32 EndMonth = tmpDate.GetMonth(); + sal_Int32 EndYear = tmpDate.GetYear(); + + + switch(ReturnFormat.ToLowerAscii()) { + case d: + // return number of days + PushDouble( EndDate - StartDate); + break; + case m: + // return number of months + sal_Int32 diffMonth = EndMonth - StartMonth + 12 * (EndYear - StartYear); + if (StartDate > EndDate && StartDays > EndDays ) + { + diffMonth -= 1; + } + else if ( EndDays > StartDays ) + { + diffMonth += 1; + } + PushInt(diffMonth); + break; + case ym: + // return number of months, ignoring years + sal_Int32 diffMonth = EndMonth - StartMonth; + if (StartDate > EndDate && StartDays > EndDays ) + { + diffMonth -= 1; + } + else if ( EndMonth > StartMonth && StartDays > EndDays ) + { + diffMonth += 1; + } + PushInt(diffMonth); + break; + case md: + // return number of days, ignoring months and years + tmpDate = Date(EndDays,StartMonth,StartYear) + double sameYear = double(tmpDate - *( pFormatter->GetNullDate() ); + PushDouble( fabs(sameYear - StartDate)); + break; + case yd: + // return number of days, ignoring years + tmpDate = Date(EndDays,EndMonth,StartYear) + double sameYear = double(tmpDate - *( pFormatter->GetNullDate() ); + PushDouble( fabs(sameYear - StartDate)); + break; + case y: + // return number of years + sal_Int32 diffYears = EndYear - StartYear; + if (EndYear > StartYear) { + if((EndMonth = StartMonth && StartDate >= EndDate) || (EndMonth > StartMonth)) + diffYears -= 1; + } + else if ((EndMonth = StartMonth && EndDate >= StartDate) || (StartMonth > EndMonth)) + diffYears += 1; + PushInt(diffYears); + break; + default: + // unsupported format + PushIllegalArgument(); + } + } +} + void ScInterpreter::ScIRR() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIRR" ); diff --git a/main/sc/source/core/tool/interpr4.cxx b/main/sc/source/core/tool/interpr4.cxx index cef3c22b6a..16c25e011b 100644 --- a/main/sc/source/core/tool/interpr4.cxx +++ b/main/sc/source/core/tool/interpr4.cxx @@ -3771,6 +3771,7 @@ StackVar ScInterpreter::Interpret() case ocBitXor : ScBitXor(); break; case ocBitLShift : ScBitLShift(); break; case ocBitRShift : ScBitRShift(); break; + case ocDateDif : ScDateDif(); break; case ocNone : nFuncFmtType = NUMBERFORMAT_UNDEFINED; break; default : PushError( errUnknownOpCode); break; } diff --git a/main/sc/source/ui/src/scfuncs.src b/main/sc/source/ui/src/scfuncs.src index 572892c56c..52ad11fd19 100644 --- a/main/sc/source/ui/src/scfuncs.src +++ b/main/sc/source/ui/src/scfuncs.src @@ -9597,6 +9597,52 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; }; + 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"; + }; + }; + }; #if defined(U2S) diff --git a/main/sc/util/hidother.src b/main/sc/util/hidother.src index 8c3bed2211..5e66a68827 100644 --- a/main/sc/util/hidother.src +++ b/main/sc/util/hidother.src @@ -491,3 +491,4 @@ hidspecial HID_FUNC_BITOR { HelpID = HID_FUNC_BITOR; }; hidspecial HID_FUNC_BITXOR { HelpID = HID_FUNC_BITXOR; }; hidspecial HID_FUNC_BITLSHIFT { HelpID = HID_FUNC_BITLSHIFT; }; hidspecial HID_FUNC_BITRSHIFT { HelpID = HID_FUNC_BITRSHIFT; }; +hidspecial HID_FUNC_DATEDIF { HelpID = HID_FUNC_DATEDIF; };