From 07987dc9aefdd48010edd0934dde5239c0dc8019 Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Thu, 2 Jul 2020 20:49:56 +0200 Subject: Resolves: tdf#134455 Let TIMEVALUE() use lax time recognition ... to accept minutes or seconds >59 Prepare SvNumInputOptions as enum class in case further options would be needed for anything else. Change-Id: Ie9ae62adf68f9948e23f55ac32c09a6b992a36e2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97784 Reviewed-by: Eike Rathke Tested-by: Jenkins (cherry picked from commit f106bb4471b6d3627311980ed727459b2da8e448) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97793 Reviewed-by: Adolfo Jayme Barrientos --- include/svl/zforlist.hxx | 13 ++++++++++++- sc/source/core/tool/interpr2.cxx | 2 +- svl/source/numbers/zforfind.cxx | 19 ++++++++++++------- svl/source/numbers/zforfind.hxx | 8 +++++--- svl/source/numbers/zforlist.cxx | 5 +++-- svl/source/numbers/zformat.cxx | 2 +- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/include/svl/zforlist.hxx b/include/svl/zforlist.hxx index adbde81c9315..852be1f7435a 100644 --- a/include/svl/zforlist.hxx +++ b/include/svl/zforlist.hxx @@ -373,6 +373,16 @@ public: typedef std::vector< OUString > NfWSStringsDtor; +/** Input options to be used with IsNumberFormat() */ +enum class SvNumInputOptions : sal_uInt16 +{ + NONE = 0, + LAX_TIME = 1 ///< allow input of minutes or seconds >59 +}; +namespace o3tl { + template<> struct typed_flags : is_typed_flags {}; +} + class SvNumberFormatterRegistry_Impl; class NfCurrencyTable; @@ -532,7 +542,8 @@ public: returned in fOutNumber if input is not a number */ - bool IsNumberFormat( const OUString& sString, sal_uInt32& F_Index, double& fOutNumber ); + bool IsNumberFormat( const OUString& sString, sal_uInt32& F_Index, double& fOutNumber, + SvNumInputOptions eInputOptions = SvNumInputOptions::NONE ); /// Format a number according to a format index, return string and color void GetOutputString( const double& fOutNumber, sal_uInt32 nFIndex, diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index d6c76315b8fd..eeb59550105f 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -935,7 +935,7 @@ void ScInterpreter::ScGetTimeValue() OUString aInputString = GetString().getString(); sal_uInt32 nFIndex = 0; // damit default Land/Spr. double fVal; - if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal)) + if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal, SvNumInputOptions::LAX_TIME)) { SvNumFormatType eType = pFormatter->GetType(nFIndex); if (eType == SvNumFormatType::TIME || eType == SvNumFormatType::DATETIME) diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx index cd889ce4d9d6..ad42df620743 100644 --- a/svl/source/numbers/zforfind.cxx +++ b/svl/source/numbers/zforfind.cxx @@ -949,7 +949,9 @@ inline bool ImpSvNumberInputScan::GetNextNumber( sal_uInt16& i, sal_uInt16& j ) bool ImpSvNumberInputScan::GetTimeRef( double& fOutNumber, sal_uInt16 nIndex, // j-value of the first numeric time part of input, default 0 - sal_uInt16 nCnt ) const // count of numeric time parts + sal_uInt16 nCnt, // count of numeric time parts + SvNumInputOptions eInputOptions + ) const { bool bRet = true; sal_uInt16 nHour; @@ -998,13 +1000,15 @@ bool ImpSvNumberInputScan::GetTimeRef( double& fOutNumber, else if (nIndex - nStartIndex < nCnt) { nMinute = static_cast(sStrArray[nNums[nIndex++]].toInt32()); - if (nIndex > 1 && nMinute > 59) + if (!(eInputOptions & SvNumInputOptions::LAX_TIME) + && nIndex > 1 && nMinute > 59) bRet = false; // 1:60 or 1:123 is invalid, 123:1 is valid } if (nIndex - nStartIndex < nCnt) { nSecond = static_cast(sStrArray[nNums[nIndex++]].toInt32()); - if (nIndex > 1 && nSecond > 59 && !(nHour == 23 && nMinute == 59 && nSecond == 60)) + if (!(eInputOptions & SvNumInputOptions::LAX_TIME) + && nIndex > 1 && nSecond > 59 && !(nHour == 23 && nMinute == 59 && nSecond == 60)) bRet = false; // 1:60 or 1:123 or 1:1:123 is invalid, 123:1 or 123:1:1 is valid, or leap second } if (nIndex - nStartIndex < nCnt) @@ -3649,9 +3653,10 @@ void ImpSvNumberInputScan::ChangeNullDate( const sal_uInt16 Day, * Does rString represent a number (also date, time et al) */ bool ImpSvNumberInputScan::IsNumberFormat( const OUString& rString, // string to be analyzed - SvNumFormatType& F_Type, // IN: old type, OUT: new type + SvNumFormatType& F_Type, // IN: old type, OUT: new type double& fOutNumber, // OUT: number if convertible - const SvNumberformat* pFormat ) // maybe a number format to match against + const SvNumberformat* pFormat, // maybe a number format to match against + SvNumInputOptions eInputOptions ) { OUString aString; bool res; // return value @@ -4052,7 +4057,7 @@ bool ImpSvNumberInputScan::IsNumberFormat( const OUString& rString, // s break; case SvNumFormatType::TIME: - res = GetTimeRef(fOutNumber, 0, nNumericsCnt); + res = GetTimeRef(fOutNumber, 0, nNumericsCnt, eInputOptions); if ( nSign < 0 ) { fOutNumber = -fOutNumber; @@ -4068,7 +4073,7 @@ bool ImpSvNumberInputScan::IsNumberFormat( const OUString& rString, // s if ( res ) { double fTime; - res = GetTimeRef( fTime, k, nNumericsCnt - k ); + res = GetTimeRef( fTime, k, nNumericsCnt - k, eInputOptions); fOutNumber += fTime; } break; diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx index 1efeb215619b..332f0ef6ef94 100644 --- a/svl/source/numbers/zforfind.hxx +++ b/svl/source/numbers/zforfind.hxx @@ -46,9 +46,10 @@ public: /// convert input string to number bool IsNumberFormat( const OUString& rString, /// input string - SvNumFormatType& F_Type, /// format type (in + out) + SvNumFormatType& F_Type, /// format type (in + out) double& fOutNumber, /// value determined (out) - const SvNumberformat* pFormat); /// number format to which compare against + const SvNumberformat* pFormat, /// number format to which compare against + SvNumInputOptions eInputOptions); /// after IsNumberFormat: get decimal position short GetDecPos() const { return nDecPos; } @@ -321,7 +322,8 @@ private: */ bool GetTimeRef( double& fOutNumber, // result as double sal_uInt16 nIndex, // Index of hour in input - sal_uInt16 nCnt ) const; // Count of time substrings in input + sal_uInt16 nCnt, // Count of time substrings in input + SvNumInputOptions eInputOptions ) const; sal_uInt16 ImplGetDay ( sal_uInt16 nIndex ) const; // Day input, 0 if no match sal_uInt16 ImplGetMonth( sal_uInt16 nIndex ) const; // Month input, zero based return, NumberOfMonths if no match sal_uInt16 ImplGetYear ( sal_uInt16 nIndex ); // Year input, 0 if no match diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx index 04e32464d8b2..b166c66b38d1 100644 --- a/svl/source/numbers/zforlist.cxx +++ b/svl/source/numbers/zforlist.cxx @@ -1123,7 +1123,8 @@ SvNumberFormatTable& SvNumberFormatter::GetEntryTable( bool SvNumberFormatter::IsNumberFormat(const OUString& sString, sal_uInt32& F_Index, - double& fOutNumber) + double& fOutNumber, + SvNumInputOptions eInputOptions) { ::osl::MutexGuard aGuard( GetInstanceMutex() ); @@ -1161,7 +1162,7 @@ bool SvNumberFormatter::IsNumberFormat(const OUString& sString, } else { - res = pStringScanner->IsNumberFormat(sString, RType, fOutNumber, pFormat); + res = pStringScanner->IsNumberFormat(sString, RType, fOutNumber, pFormat, eInputOptions); } if (res && !IsCompatible(FType, RType)) // non-matching type { diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx index 01eb9c319d92..23c0919aecf2 100644 --- a/svl/source/numbers/zformat.cxx +++ b/svl/source/numbers/zformat.cxx @@ -855,7 +855,7 @@ SvNumberformat::SvNumberformat(OUString& rString, { sal_Int32 nDecPos; SvNumFormatType F_Type = SvNumFormatType::UNDEFINED; - if (!pISc->IsNumberFormat(sStr, F_Type, fNumber, nullptr) || + if (!pISc->IsNumberFormat(sStr, F_Type, fNumber, nullptr, SvNumInputOptions::NONE) || ( F_Type != SvNumFormatType::NUMBER && F_Type != SvNumFormatType::SCIENTIFIC) ) { -- cgit v1.2.3