diff options
author | Winfried Donkers <winfrieddonkers@libreoffice.org> | 2015-09-22 10:40:25 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2015-10-06 21:21:16 +0000 |
commit | f830600ece806ec365a4839e79afabe183c5e36d (patch) | |
tree | 1bcfeccf135fc1489b1f850ca3462df514f5b294 | |
parent | e3ddcbea3fd8b9402ce2339de47793c4bc2b4b80 (diff) |
tdf#50950 Add ODFF1.2 Calc function ISOWEEKNUM,
make Calc function WEEKNUM compliant with ODFF1.2,
provide backward compatibility for Calc function WEEKNUM,
add unit tests for ISOWEEKNUM, WEEKNUM and backward compatibility.
Change-Id: I63af5543cea2f470d710462e55404ac754022c89
Reviewed-on: https://gerrit.libreoffice.org/18760
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Eike Rathke <erack@redhat.com>
-rw-r--r-- | formula/source/core/api/FormulaCompiler.cxx | 71 | ||||
-rw-r--r-- | formula/source/core/resource/core_resource.src | 9 | ||||
-rw-r--r-- | include/formula/compiler.hrc | 3 | ||||
-rw-r--r-- | include/formula/opcode.hxx | 1 | ||||
-rw-r--r-- | sc/inc/helpids.h | 1 | ||||
-rw-r--r-- | sc/qa/unit/data/contentCSV/date-time-functions.csv | 4 | ||||
-rw-r--r-- | sc/qa/unit/data/ods/date-time-functions.ods | bin | 31555 -> 13560 bytes | |||
-rw-r--r-- | sc/qa/unit/ucalc.cxx | 1 | ||||
-rw-r--r-- | sc/source/core/inc/interpre.hxx | 1 | ||||
-rw-r--r-- | sc/source/core/tool/interpr2.cxx | 39 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 1 | ||||
-rw-r--r-- | sc/source/filter/excel/xlformula.cxx | 3 | ||||
-rw-r--r-- | sc/source/filter/oox/formulabase.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/src/scfuncs.src | 26 |
14 files changed, 141 insertions, 23 deletions
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index 4ee0f7268d82..9d613e992524 100644 --- a/formula/source/core/api/FormulaCompiler.cxx +++ b/formula/source/core/api/FormulaCompiler.cxx @@ -1247,23 +1247,66 @@ void FormulaCompiler::Factor() else if( eOp == ocNot || eOp == ocNeg || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) ) { - pFacToken = mpToken; - eOp = NextToken(); - if( nNumFmt == css::util::NumberFormat::UNDEFINED && eOp == ocNot ) - nNumFmt = css::util::NumberFormat::LOGICAL; - if (eOp == ocOpen) + if (eOp == ocIsoWeeknum && FormulaGrammar::isODFF( meGrammar )) { - NextToken(); - eOp = Expression(); + // tdf#50950 ocIsoWeeknum can have 2 arguments when saved by older versions of Calc; + // the opcode then has to be changed to ocWeek for backward compatibilty + pFacToken = mpToken; + eOp = NextToken(); + bool bNoParam = false; + if (eOp == ocOpen) + { + eOp = NextToken(); + if (eOp == ocClose) + bNoParam = true; + else + eOp = Expression(); + } + else + SetError( errPairExpected); + sal_uInt8 nSepCount = 0; + if( !bNoParam ) + { + nSepCount++; + while ((eOp == ocSep) && (!pArr->GetCodeError() || !mbStopOnError)) + { + nSepCount++; + NextToken(); + eOp = Expression(); + } + } + if (eOp != ocClose) + SetError( errPairExpected); + else + eOp = NextToken(); + pFacToken->SetByte( nSepCount ); + if (nSepCount == 2) + { + pFacToken->NewOpCode( ocWeek, FormulaToken::PrivateAccess()); + } + PutCode( pFacToken ); } else - SetError( errPairExpected); - if (eOp != ocClose) - SetError( errPairExpected); - else if ( !pArr->GetCodeError() ) - pFacToken->SetByte( 1 ); - PutCode( pFacToken ); - eOp = NextToken(); + { + // standard handling of ocNot, ocNeg and 1-parameter opcodes + pFacToken = mpToken; + eOp = NextToken(); + if( nNumFmt == css::util::NumberFormat::UNDEFINED && eOp == ocNot ) + nNumFmt = css::util::NumberFormat::LOGICAL; + if (eOp == ocOpen) + { + NextToken(); + eOp = Expression(); + } + else + SetError( errPairExpected); + if (eOp != ocClose) + SetError( errPairExpected); + else if ( !pArr->GetCodeError() ) + pFacToken->SetByte( 1 ); + PutCode( pFacToken ); + eOp = NextToken(); + } } else if ((SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR) || eOp == ocExternal diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src index ed0aeca4522f..90cd6e5266c3 100644 --- a/formula/source/core/resource/core_resource.src +++ b/formula/source/core/resource/core_resource.src @@ -389,7 +389,8 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF String SC_OPCODE_BETA_INV { Text = "BETAINV" ; }; String SC_OPCODE_BETA_DIST_MS { Text = "COM.MICROSOFT.BETA.DIST" ; }; String SC_OPCODE_BETA_INV_MS { Text = "COM.MICROSOFT.BETA.INV" ; }; - String SC_OPCODE_WEEK { Text = "ISOWEEKNUM" ; }; + String SC_OPCODE_WEEK { Text = "WEEKNUM" ; }; + String SC_OPCODE_ISOWEEKNUM { Text = "ISOWEEKNUM" ; }; String SC_OPCODE_EASTERSUNDAY { Text = "ORG.OPENOFFICE.EASTERSUNDAY" ; }; String SC_OPCODE_GET_DAY_OF_WEEK { Text = "WEEKDAY" ; }; String SC_OPCODE_NETWORKDAYS { Text = "NETWORKDAYS" ; }; @@ -811,6 +812,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML String SC_OPCODE_BETA_DIST_MS { Text = "_xlfn.BETA.DIST" ; }; String SC_OPCODE_BETA_INV_MS { Text = "_xlfn.BETA.INV" ; }; String SC_OPCODE_WEEK { Text = "WEEKNUM" ; }; + String SC_OPCODE_ISOWEEKNUM { Text = "_xlfn.ISOWEEKNUM" ; }; String SC_OPCODE_EASTERSUNDAY { Text = "EASTERSUNDAY" ; }; String SC_OPCODE_GET_DAY_OF_WEEK { Text = "WEEKDAY" ; }; String SC_OPCODE_NETWORKDAYS { Text = "NETWORKDAYS" ; }; @@ -1234,6 +1236,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH String SC_OPCODE_BETA_DIST_MS { Text = "BETA.DIST" ; }; String SC_OPCODE_BETA_INV_MS { Text = "BETA.INV" ; }; String SC_OPCODE_WEEK { Text = "WEEKNUM" ; }; + String SC_OPCODE_ISOWEEKNUM { Text = "ISOWEEKNUM" ; }; String SC_OPCODE_EASTERSUNDAY { Text = "EASTERSUNDAY" ; }; String SC_OPCODE_GET_DAY_OF_WEEK { Text = "WEEKDAY" ; }; String SC_OPCODE_NETWORKDAYS { Text = "NETWORKDAYS" ; }; @@ -2698,6 +2701,10 @@ Resource RID_STRLIST_FUNCTION_NAMES { Text [ en-US ] = "WEEKNUM" ; }; + String SC_OPCODE_ISOWEEKNUM + { + Text [ en-US ] = "ISOWEEKNUM" ; + }; String SC_OPCODE_EASTERSUNDAY { Text [ en-US ] = "EASTERSUNDAY" ; diff --git a/include/formula/compiler.hrc b/include/formula/compiler.hrc index 9d45b9aa9212..984ec02c0edd 100644 --- a/include/formula/compiler.hrc +++ b/include/formula/compiler.hrc @@ -204,7 +204,8 @@ #define SC_OPCODE_ERFC_MS 174 #define SC_OPCODE_ERROR_TYPE_ODF 175 #define SC_OPCODE_ENCODEURL 176 -#define SC_OPCODE_STOP_1_PAR 177 +#define SC_OPCODE_ISOWEEKNUM 177 +#define SC_OPCODE_STOP_1_PAR 178 /*** Functions with more than one parameters ***/ #define SC_OPCODE_START_2_PAR 201 diff --git a/include/formula/opcode.hxx b/include/formula/opcode.hxx index 806147c7a12c..0c4c8e8f510e 100644 --- a/include/formula/opcode.hxx +++ b/include/formula/opcode.hxx @@ -449,6 +449,7 @@ enum OpCode : sal_uInt16 ocBitLshift = SC_OPCODE_BITLSHIFT, // miscellaneous ocWeek = SC_OPCODE_WEEK, + ocIsoWeeknum = SC_OPCODE_ISOWEEKNUM, ocGetDayOfWeek = SC_OPCODE_GET_DAY_OF_WEEK, ocNetWorkdays = SC_OPCODE_NETWORKDAYS, ocNetWorkdays_MS = SC_OPCODE_NETWORKDAYS_MS, diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h index 1c45bbe85189..3b41eb8b2495 100644 --- a/sc/inc/helpids.h +++ b/sc/inc/helpids.h @@ -284,6 +284,7 @@ #define HID_FUNC_DATEDIF "SC_HID_FUNC_DATEDIF" #define HID_FUNC_KALENDERWOCHE "SC_HID_FUNC_KALENDERWOCHE" #define HID_FUNC_OSTERSONNTAG "SC_HID_FUNC_OSTERSONNTAG" +#define HID_FUNC_ISOWEEKNUM "SC_HID_FUNC_ISOWEEKNUM" #define HID_FUNC_BW "SC_HID_FUNC_BW" #define HID_FUNC_ZW "SC_HID_FUNC_ZW" diff --git a/sc/qa/unit/data/contentCSV/date-time-functions.csv b/sc/qa/unit/data/contentCSV/date-time-functions.csv index a43bdc302e81..33aa540f7636 100644 --- a/sc/qa/unit/data/contentCSV/date-time-functions.csv +++ b/sc/qa/unit/data/contentCSV/date-time-functions.csv @@ -19,7 +19,9 @@ .18 0,0.6666666667,0.5 4,3,4 -1,52 +52 +1,1,52 +1,1 52 10,11 52,52 diff --git a/sc/qa/unit/data/ods/date-time-functions.ods b/sc/qa/unit/data/ods/date-time-functions.ods Binary files differindex 9f6e044aa9b9..19244b6d37be 100644 --- a/sc/qa/unit/data/ods/date-time-functions.ods +++ b/sc/qa/unit/data/ods/date-time-functions.ods diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index e6d9081ff1cc..0dda665f5e3c 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -2366,6 +2366,7 @@ void Test::testFunctionLists() "EASTERSUNDAY", "HOUR", "ISLEAPYEAR", + "ISOWEEKNUM", "MINUTE", "MONTH", "MONTHS", diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 85ede44132cf..280d9d1548a3 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -616,6 +616,7 @@ void ScGetMonth(); void ScGetDay(); void ScGetDayOfWeek(); void ScGetWeekOfYear(); +void ScGetIsoWeekOfYear(); void ScEasterSunday(); sal_uInt16 GetWeekendAndHolidayMasks( const sal_uInt8 nParamCount, const sal_uInt32 nNullDate, ::std::vector<double>& rSortArray, bool bWeekendMask[ 7 ] ); diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index 5699816693d4..95fd1aa9760b 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -213,7 +213,44 @@ void ScInterpreter::ScGetWeekOfYear() Date aDate = *(pFormatter->GetNullDate()); aDate += (long)::rtl::math::approxFloor(GetDouble()); - PushInt( (int) aDate.GetWeekOfYear( nFlag == 1 ? SUNDAY : MONDAY )); + + sal_Int32 nMinimumNumberOfDaysInWeek; + DayOfWeek eFirstDayOfWeek; + switch ( nFlag ) + { + case 1 : + case 11 : + case 2 : + case 12 : + case 13 : + case 14 : + case 15 : + case 16 : + case 17 : + eFirstDayOfWeek = (DayOfWeek) ( ( nFlag - 1 ) % 10 ); + nMinimumNumberOfDaysInWeek = 1; //the week containing January 1 is week 1 + break; + case 21 : + case 150 : + // ISO 8601 + eFirstDayOfWeek = MONDAY; + nMinimumNumberOfDaysInWeek = 4; + break; + default : + PushIllegalArgument(); + return; + } + PushInt( (int) aDate.GetWeekOfYear( eFirstDayOfWeek, nMinimumNumberOfDaysInWeek ) ); + } +} + +void ScInterpreter::ScGetIsoWeekOfYear() +{ + if ( MustHaveParamCount( GetByte(), 1 ) ) + { + Date aDate = *(pFormatter->GetNullDate()); + aDate += (long)::rtl::math::approxFloor(GetDouble()); + PushInt( (int) aDate.GetWeekOfYear( MONDAY, 4 ) ); } } diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 211ac7cb49f1..e8a3b1d454aa 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -3697,6 +3697,7 @@ StackVar ScInterpreter::Interpret() case ocGetDay : ScGetDay(); break; case ocGetDayOfWeek : ScGetDayOfWeek(); break; case ocWeek : ScGetWeekOfYear(); break; + case ocIsoWeeknum : ScGetIsoWeekOfYear(); break; case ocEasterSunday : ScEasterSunday(); break; case ocNetWorkdays : ScNetWorkdays( false); break; case ocNetWorkdays_MS : ScNetWorkdays( true ); break; diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx index 157d11bc0d93..90429333fac3 100644 --- a/sc/source/filter/excel/xlformula.cxx +++ b/sc/source/filter/excel/xlformula.cxx @@ -545,7 +545,8 @@ static const XclFunctionInfo saFuncTable_2013[] = // IMCOSH, IMCOT, IMCSC, IMCSCH, IMSEC, IMSECH, IMSINH and IMTAN are // implemented in the Analysis Add-In. EXC_FUNCENTRY_V_RO( ocIsFormula, 1, 1, 0, "ISFORMULA" ), - EXC_FUNCENTRY_V_VR( ocWeek, 1, 2, 0, "ISOWEEKNUM" ), + EXC_FUNCENTRY_V_VR( ocWeek, 1, 2, 0, "WEEKNUM" ), + EXC_FUNCENTRY_V_VR( ocIsoWeeknum, 1, 1, 0, "ISOWEEKNUM" ), EXC_FUNCENTRY_A_VR( ocMatrixUnit, 1, 1, 0, "MUNIT" ), EXC_FUNCENTRY_V_VR( ocNumberValue, 1, 3, 0, "NUMBERVALUE" ), EXC_FUNCENTRY_V_VR( ocDuration, 3, 3, 0, "PDURATION" ), diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx index b4bcb25a0020..cdfc9227056b 100644 --- a/sc/source/filter/oox/formulabase.cxx +++ b/sc/source/filter/oox/formulabase.cxx @@ -876,9 +876,7 @@ static const FunctionData saFuncTable2013[] = { "IMSINH", "IMSINH", NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALL_NEW | FUNCFLAG_EXTERNAL }, { "IMTAN", "IMTAN", NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALL_NEW | FUNCFLAG_EXTERNAL }, { "ISFORMULA", "ISFORMULA", NOID, NOID, 1, 1, V, { RO }, FUNCFLAG_MACROCALL_NEW }, - /* FIXME: ISOWEEKNUM vs. WEEKNUM mess needs to be sorted out before we can - * import. */ - { 0/*"ISOWEEKNUM"*/, "ISOWEEKNUM", NOID, NOID, 1, 2, V, { VR }, FUNCFLAG_MACROCALL_NEW }, + { "ISOWEEKNUM", "ISOWEEKNUM", NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALL_NEW }, { "MUNIT", "MUNIT", NOID, NOID, 1, 1, A, { VR }, FUNCFLAG_MACROCALL_NEW }, { "NUMBERVALUE", "NUMBERVALUE", NOID, NOID, 1, 3, V, { VR }, FUNCFLAG_MACROCALL_NEW }, { "PDURATION", "PDURATION", NOID, NOID, 3, 3, V, { VR }, FUNCFLAG_MACROCALL_NEW }, diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src index f5166bfbd451..b298d7378fe1 100644 --- a/sc/source/ui/src/scfuncs.src +++ b/sc/source/ui/src/scfuncs.src @@ -1185,7 +1185,31 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1 }; String 5 // Description of Parameter 2 { - Text [ en-US ] = "Indicates the first day of the week (1 = Sunday, other values = Monday)." ; + Text [ en-US ] = "Indicates the first day of the week and when week 1 starts." ; + }; + }; + // -=*# Resource for function ISOWEEKNUM #*=- + Resource SC_OPCODE_ISOWEEKNUM + { + String 1 // Description + { + Text [ en-US ] = "Calculates the ISO 8601 calender week for the given date." ; + }; + ExtraData = + { + 0; + ID_FUNCTION_GRP_DATETIME; + U2S( HID_FUNC_ISOWEEKNUM ); + 1; 0; 0; + 0; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "Number" ; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "The internal number of the date." ; }; }; // -=*# Resource for function EASTERSUNDAY #*=- |