summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWinfried Donkers <winfrieddonkers@libreoffice.org>2015-09-22 10:40:25 +0200
committerEike Rathke <erack@redhat.com>2015-10-06 21:21:16 +0000
commitf830600ece806ec365a4839e79afabe183c5e36d (patch)
tree1bcfeccf135fc1489b1f850ca3462df514f5b294
parentPrefer getSelectedFiles to getFiles (vcl) (diff)
downloadcore-f830600ece806ec365a4839e79afabe183c5e36d.tar.gz
core-f830600ece806ec365a4839e79afabe183c5e36d.zip
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.cxx71
-rw-r--r--formula/source/core/resource/core_resource.src9
-rw-r--r--include/formula/compiler.hrc3
-rw-r--r--include/formula/opcode.hxx1
-rw-r--r--sc/inc/helpids.h1
-rw-r--r--sc/qa/unit/data/contentCSV/date-time-functions.csv4
-rw-r--r--sc/qa/unit/data/ods/date-time-functions.odsbin31555 -> 13560 bytes
-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.cxx39
-rw-r--r--sc/source/core/tool/interpr4.cxx1
-rw-r--r--sc/source/filter/excel/xlformula.cxx3
-rw-r--r--sc/source/filter/oox/formulabase.cxx4
-rw-r--r--sc/source/ui/src/scfuncs.src26
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
index 9f6e044aa9b9..19244b6d37be 100644
--- a/sc/qa/unit/data/ods/date-time-functions.ods
+++ b/sc/qa/unit/data/ods/date-time-functions.ods
Binary files differ
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 #*=-