Resolves: tdf#125099 round duration results in interpreter already

So wall clock time formats less likely display a one-off value,
duration formats are too rarely used if the expected duration is
less than 24 hours.

Change-Id: I9b0872420699b17e3ed3f20993f8cfe02761f862
Reviewed-on: https://gerrit.libreoffice.org/71909
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
diff --git a/include/svl/zforlist.hxx b/include/svl/zforlist.hxx
index 5d7f0da..0a08f4f 100644
--- a/include/svl/zforlist.hxx
+++ b/include/svl/zforlist.hxx
@@ -109,9 +109,14 @@ enum class SvNumFormatType : sal_Int16
         @since LibreOffice 5.1
      */
     EMPTY = css::util::NumberFormat::EMPTY, // 4096
    /** @internal selects a time duration format.
        8192 + TIME (4)
        @since LibreOffice 6.2
     */
     DURATION = css::util::NumberFormat::DURATION, // 8196
};
namespace o3tl {
    template<> struct typed_flags<SvNumFormatType> : is_typed_flags<SvNumFormatType, 0x1dff> {};
    template<> struct typed_flags<SvNumFormatType> : is_typed_flags<SvNumFormatType, 0x2dff> {};
}

/** enum values for <method>SvNumberFormatter::GetFormatIndex</method>
diff --git a/offapi/com/sun/star/util/NumberFormat.idl b/offapi/com/sun/star/util/NumberFormat.idl
index 2bc297a..e66a59d 100644
--- a/offapi/com/sun/star/util/NumberFormat.idl
+++ b/offapi/com/sun/star/util/NumberFormat.idl
@@ -99,6 +99,13 @@ published constants NumberFormat
     */
    const short EMPTY = 4096;


    /** @internal selects a time duration format.
        8192 + TIME (4)
        @since LibreOffice 6.2
     */
    const short DURATION = 8196;

};


diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 5713a5b..286583e 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -4423,6 +4423,7 @@ StackVar ScInterpreter::Interpret()
                    case SvNumFormatType::DATE:
                    case SvNumFormatType::TIME:
                    case SvNumFormatType::DATETIME:
                    case SvNumFormatType::DURATION:
                        nRetIndexExpr = nFuncFmtIndex;
                    break;
                    default:
@@ -4537,13 +4538,26 @@ StackVar ScInterpreter::Interpret()
                        // unnecessarily duplicate the information.
                        if (pCur->GetDoubleType() != 0)
                        {
                            const double fVal = PopDouble();
                            double fVal = PopDouble();
                            if (!bForcedResultType)
                            {
                                if (nCurFmtType != nFuncFmtType)
                                    nRetIndexExpr = 0;  // carry format index only for matching type
                                nRetTypeExpr = nFuncFmtType = nCurFmtType;
                            }
                            if (nRetTypeExpr == SvNumFormatType::DURATION)
                            {
                                // Round the duration in case a wall clock time
                                // display format is used instead of a duration
                                // format. To micro seconds which then catches
                                // the converted hh:mm:ss.9999997 cases.
                                if (fVal != 0.0)
                                {
                                    fVal *= 86400.0;
                                    fVal = rtl::math::round( fVal, 6);
                                    fVal /= 86400.0;
                                }
                            }
                            PushTempToken( CreateFormulaDoubleToken( fVal));
                        }
                        if ( nFuncFmtType == SvNumFormatType::UNDEFINED )
@@ -4653,6 +4667,11 @@ StackVar ScInterpreter::Interpret()
    else
        nRetFmtType = SvNumFormatType::NUMBER;

    // Currently (2019-05-06) nothing else can cope with a duration format
    // type, change to time as it was before.
    if (nRetFmtType == SvNumFormatType::DURATION)
        nRetFmtType = SvNumFormatType::TIME;

    if (nGlobalError != FormulaError::NONE && GetStackType() != svError )
        PushError( nGlobalError);

diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index 504233a..e928b97 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -1126,15 +1126,16 @@ ScMatrixRef ScInterpreter::MatConcat(const ScMatrixRef& pMat1, const ScMatrixRef
    return xResMat;
}

// for DATE, TIME, DATETIME
// for DATE, TIME, DATETIME, DURATION
static void lcl_GetDiffDateTimeFmtType( SvNumFormatType& nFuncFmt, SvNumFormatType nFmt1, SvNumFormatType nFmt2 )
{
    if ( nFmt1 != SvNumFormatType::UNDEFINED || nFmt2 != SvNumFormatType::UNDEFINED )
    {
        if ( nFmt1 == nFmt2 )
        {
            if ( nFmt1 == SvNumFormatType::TIME || nFmt1 == SvNumFormatType::DATETIME )
                nFuncFmt = SvNumFormatType::TIME;   // times result in time
            if ( nFmt1 == SvNumFormatType::TIME || nFmt1 == SvNumFormatType::DATETIME
                    || nFmt1 == SvNumFormatType::DURATION )
                nFuncFmt = SvNumFormatType::DURATION;   // times result in time duration
            // else: nothing special, number (date - date := days)
        }
        else if ( nFmt1 == SvNumFormatType::UNDEFINED )
@@ -1178,6 +1179,7 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
            case SvNumFormatType::DATE :
            case SvNumFormatType::TIME :
            case SvNumFormatType::DATETIME :
            case SvNumFormatType::DURATION :
                nFmt2 = nCurFmtType;
            break;
            case SvNumFormatType::CURRENCY :
@@ -1200,6 +1202,7 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
            case SvNumFormatType::DATE :
            case SvNumFormatType::TIME :
            case SvNumFormatType::DATETIME :
            case SvNumFormatType::DURATION :
                nFmt1 = nCurFmtType;
            break;
            case SvNumFormatType::CURRENCY :