include/tools/duration.hxx         |   30 ++++++++++-
 sc/source/core/tool/interpr5.cxx   |   22 +++++++-
 tools/qa/cppunit/test_duration.cxx |   78 +++++++++++++++++++++++++++++
 tools/source/datetime/duration.cxx |   97 ++++++++++++++++++++++++++++++++-----
 tools/source/datetime/ttime.cxx    |   12 ++++
 5 files changed, 221 insertions(+), 18 deletions(-)

New commits:
commit c17641839855ba88b1c071c4f5e4533725ff2dbb
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Mon Aug 7 16:37:26 2023 +0200
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Wed Aug 16 13:13:14 2023 +0200

    Resolves: tdf#127334 Backport tools::Duration 
ScInterpreter::CalculateAddSub()
    
    All tools::Duration implementation for completeness.
    
     This is a combination of 5 (+2 typo) commits.
    
    Introduce tools::Duration(sal_Int32 nDays, const Time& rTime) ctor
    
    xChange-Id: If002e04536149b49b2249103ac914d17dec3fae6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153409
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 986c2d86a7b53a6599d014db7327f47cb33d4fea)
    
    Introduce tools::Duration individual time values ctor
    
    xChange-Id: I516d3727cbcf6667b32dc963febbf4b753ef6a91
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153497
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit c968d8989004301b49d67a093a6eb8a629533837)
    
    Clamp and assert maximum hours value in Time::init()
    
    xChange-Id: Ia777222f3c797b90663b55499a57025e410b1d70
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153407
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit b07d72c6c1075efa6b64c67758566426c22c5225)
    
    Use tools::Duration in ScInterpreter::CalculateAddSub()
    
    ... for all (date+)time inflicted operands.
    
    xChange-Id: I93043d912867e2ef7d4af271b5c4566a3ffb4ef9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153291
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 174a72f3fd50d1146d6bedd4cc2a1971aa33be67)
    
    Resolves: tdf#127334 Increase tools::Duration accuracy epsilon unsharpness
    
    ... when converting from double, i.e. to 300 nanoseconds.
    Empirically determined..
    
    xChange-Id: I92c43b5f244923363af5d44bece9c155126ca343
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155324
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 46e672db8002e7aaac881bee65b5c50c4e14c666)
    
    Change-Id: I92c43b5f244923363af5d44bece9c155126ca343
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155427
    Tested-by: Jenkins
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/include/tools/duration.hxx b/include/tools/duration.hxx
index 83b9d12a77b3..9fae80d1d7c9 100644
--- a/include/tools/duration.hxx
+++ b/include/tools/duration.hxx
@@ -31,8 +31,30 @@ public:
         minutes and seconds values here though. */
     Duration(const Time& rStart, const Time& rEnd);
 
-    /** Difference in days, like DateTime()-DateTime(). */
-    explicit Duration(double fTimeInDays);
+    /** Difference in days, like DateTime()-DateTime().
+
+        @param  nAccuracyEpsilonNanoseconds
+                Round for example by 1 nanosecond if it's just 1 off to a
+                second,  i.e. 0999999999 or 0000000001. This can be loosened if
+                necessary. For example, if fTimeInDays is a date+time in
+                "today's" range with a significant seconds resolution, an
+                accuracy epsilon (=unsharpness) of ~300 is required. Hence 
default.
+                Must be 0 <= nAccuracyEpsilonNanoseconds <= 
Time::nanoSecPerSec - 1.
+     */
+    explicit Duration(double fTimeInDays, sal_uInt64 
nAccuracyEpsilonNanoseconds = 300);
+
+    /** Time can be a limited duration as well and can have out-of-range
+        values, it will be normalized. Sign of both days and Time must be equal
+        unless one is 0. */
+    Duration(sal_Int32 nDays, const Time& rTime);
+
+    /** Individual time values can be out-of-range, all will be normalized.
+        Additionally, the resulting time overall hour value is not restricted
+        to sal_uInt16 like it is with Time, as values >=24 flow over into days.
+        For a negative duration only a negative nDays can be given, thus a
+        negative duration of less than one day is not possible. */
+    Duration(sal_Int32 nDays, sal_uInt32 nHours, sal_uInt32 nMinutes, 
sal_uInt32 nSeconds,
+             sal_uInt64 nNanoseconds);
 
     bool IsNegative() const { return mnDays < 0 || maTime.GetTime() < 0; }
     sal_Int32 GetDays() const { return mnDays; }
@@ -55,6 +77,10 @@ private:
     /** Internal days and Time values. */
     Duration(sal_Int32 nDays, sal_Int64 nTime);
 
+    /** Prerequisite: mnDays is already set. */
+    void Normalize(sal_uInt64 nHours, sal_uInt64 nMinutes, sal_uInt64 nSeconds,
+                   sal_uInt64 nNanoseconds, bool bNegative);
+
     /** Prerequisite: mnDays is already correctly set and absolute value of
         nanoseconds less than one day. */
     void ApplyTime(sal_Int64 nNS);
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index b27e27c5e188..dcb5ee6ea343 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -27,6 +27,7 @@
 
 #include <unotools/bootstrap.hxx>
 #include <svl/zforlist.hxx>
+#include <tools/duration.hxx>
 
 #include <interpre.hxx>
 #include <global.hxx>
@@ -1220,6 +1221,7 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
     double fVal1 = 0.0, fVal2 = 0.0;
     SvNumFormatType nFmt1, nFmt2;
     nFmt1 = nFmt2 = SvNumFormatType::UNDEFINED;
+    bool bDuration = false;
     SvNumFormatType nFmtCurrencyType = nCurFmtType;
     sal_uLong nFmtCurrencyIndex = nCurFmtIndex;
     SvNumFormatType nFmtPercentType = nCurFmtType;
@@ -1235,6 +1237,7 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
             case SvNumFormatType::DATETIME :
             case SvNumFormatType::DURATION :
                 nFmt2 = nCurFmtType;
+                bDuration = true;
             break;
             case SvNumFormatType::CURRENCY :
                 nFmtCurrencyType = nCurFmtType;
@@ -1258,6 +1261,7 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
             case SvNumFormatType::DATETIME :
             case SvNumFormatType::DURATION :
                 nFmt1 = nCurFmtType;
+                bDuration = true;
             break;
             case SvNumFormatType::CURRENCY :
                 nFmtCurrencyType = nCurFmtType;
@@ -1334,10 +1338,22 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
             if (nFmtPercentType == SvNumFormatType::PERCENT && nFuncFmtType == 
SvNumFormatType::NUMBER)
                 nFuncFmtType = SvNumFormatType::PERCENT;
         }
-        if ( _bSub )
-            PushDouble( ::rtl::math::approxSub( fVal1, fVal2 ) );
+        if ((nFuncFmtType == SvNumFormatType::DURATION || bDuration)
+                && ((_bSub && std::fabs(fVal1 - fVal2) <= SAL_MAX_INT32)
+                    || (!_bSub && std::fabs(fVal1 + fVal2) <= SAL_MAX_INT32)))
+        {
+            if (_bSub)
+                PushDouble( ::tools::Duration( fVal1 - fVal2).GetInDays());
+            else
+                PushDouble( ::tools::Duration( fVal1 + fVal2).GetInDays());
+        }
         else
-            PushDouble( ::rtl::math::approxAdd( fVal1, fVal2 ) );
+        {
+            if (_bSub)
+                PushDouble( ::rtl::math::approxSub( fVal1, fVal2 ) );
+            else
+                PushDouble( ::rtl::math::approxAdd( fVal1, fVal2 ) );
+        }
     }
 }
 
diff --git a/tools/qa/cppunit/test_duration.cxx 
b/tools/qa/cppunit/test_duration.cxx
index 0f5a4e002219..c4032be83a03 100644
--- a/tools/qa/cppunit/test_duration.cxx
+++ b/tools/qa/cppunit/test_duration.cxx
@@ -104,6 +104,84 @@ void DurationTest::testDuration()
         const Duration aN = -aD;
         CPPUNIT_ASSERT_EQUAL(1.5, aN.GetInDays());
     }
+    {
+        const Duration aD(1, Time(2, 3, 4, 5));
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(2), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(3), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(4), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(5), 
aD.GetTime().GetNanoSec());
+    }
+    {
+        // 235929599 seconds == SAL_MAX_UINT16 hours + 59 minutes + 59 seconds
+        const Duration aD(0, Time(0, 0, 235929599, Time::nanoSecPerSec - 1));
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2730), aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(15), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(59), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(59), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(999999999), 
aD.GetTime().GetNanoSec());
+    }
+    {
+        // 235929599 seconds == SAL_MAX_UINT16 hours + 59 minutes + 59 seconds
+        const Duration aD(0, 0, 0, 235929599, Time::nanoSecPerSec - 1);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2730), aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(15), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(59), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(59), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(999999999), 
aD.GetTime().GetNanoSec());
+    }
+    {
+        const Duration aD(1, 2, 3, 4, 5);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(2), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(3), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(4), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(5), 
aD.GetTime().GetNanoSec());
+    }
+    {
+        const Duration aD(-1, 2, 3, 4, 5);
+        CPPUNIT_ASSERT(aD.IsNegative());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-1), aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(2), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(3), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(4), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(5), 
aD.GetTime().GetNanoSec());
+    }
+    {
+        const Duration aD(1, SAL_MAX_UINT32, SAL_MAX_UINT32, SAL_MAX_UINT32, 
SAL_MAX_UINT64);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(182202802), aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(17), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(48), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(709551615), 
aD.GetTime().GetNanoSec());
+    }
+    {
+        const Duration aD(-1, SAL_MAX_UINT32, SAL_MAX_UINT32, SAL_MAX_UINT32, 
SAL_MAX_UINT64);
+        CPPUNIT_ASSERT(aD.IsNegative());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-182202802), aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(17), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(48), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(709551615), 
aD.GetTime().GetNanoSec());
+    }
+    { // Maximum days with all max possible.
+        const Duration aD(1965280846, SAL_MAX_UINT32, SAL_MAX_UINT32, 
SAL_MAX_UINT32,
+                          SAL_MAX_UINT64);
+        CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT32, aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(17), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(48), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(709551615), 
aD.GetTime().GetNanoSec());
+    }
+    { // Maximum negative days with all max possible.
+        const Duration aD(-1965280847, SAL_MAX_UINT32, SAL_MAX_UINT32, 
SAL_MAX_UINT32,
+                          SAL_MAX_UINT64);
+        CPPUNIT_ASSERT_EQUAL(SAL_MIN_INT32, aD.GetDays());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), 
aD.GetTime().GetHour());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(17), 
aD.GetTime().GetMin());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(48), 
aD.GetTime().GetSec());
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(709551615), 
aD.GetTime().GetNanoSec());
+    }
     { // Add()
         const DateTime aS(Date(23, 11, 1999), Time(0, 0, 0));
         const DateTime aE(Date(23, 11, 1999), Time(1, 23, 45));
diff --git a/tools/source/datetime/duration.cxx 
b/tools/source/datetime/duration.cxx
index 1199ced39443..a655f016a1bc 100644
--- a/tools/source/datetime/duration.cxx
+++ b/tools/source/datetime/duration.cxx
@@ -47,8 +47,9 @@ Duration::Duration(const Time& rStart, const Time& rEnd)
     }
 }
 
-Duration::Duration(double fTimeInDays)
+Duration::Duration(double fTimeInDays, sal_uInt64 nAccuracyEpsilonNanoseconds)
 {
+    assert(nAccuracyEpsilonNanoseconds <= Time::nanoSecPerSec - 1);
     double fInt, fFrac;
     if (fTimeInDays < 0.0)
     {
@@ -66,19 +67,21 @@ Duration::Duration(double fTimeInDays)
         fFrac *= Time::nanoSecPerDay;
         fFrac = ::rtl::math::approxFloor(fFrac);
         sal_Int64 nNS = static_cast<sal_Int64>(fFrac);
-        // Round by 1 nanosecond if it's just 1 off to a second, i.e.
-        // 0999999999 or 0000000001. This could be losened to rounding by 2 or
-        // such if necessary.
         const sal_Int64 nN = nNS % Time::nanoSecPerSec;
-        if (std::abs(nN) == 1)
-            nNS -= (nNS < 0) ? -1 : 1;
-        else if (std::abs(nN) == Time::nanoSecPerSec - 1)
+        if (nN)
         {
-            nNS += (nNS < 0) ? -1 : 1;
-            if (std::abs(nNS) >= Time::nanoSecPerDay)
+            const sal_uInt64 nA = std::abs(nN);
+            if (nA <= nAccuracyEpsilonNanoseconds)
+                nNS -= (nNS < 0) ? -nN : nN;
+            else if (nA >= Time::nanoSecPerSec - nAccuracyEpsilonNanoseconds)
             {
-                mnDays += nNS / Time::nanoSecPerDay;
-                nNS %= Time::nanoSecPerDay;
+                const sal_Int64 nD = Time::nanoSecPerSec - nA;
+                nNS += (nNS < 0) ? -nD : nD;
+                if (std::abs(nNS) >= Time::nanoSecPerDay)
+                {
+                    mnDays += nNS / Time::nanoSecPerDay;
+                    nNS %= Time::nanoSecPerDay;
+                }
             }
         }
         maTime.MakeTimeFromNS(nNS);
@@ -86,12 +89,80 @@ Duration::Duration(double fTimeInDays)
     }
 }
 
+Duration::Duration(sal_Int32 nDays, const Time& rTime)
+    : mnDays(nDays)
+{
+    assert(nDays == 0 || rTime.GetTime() == 0 || (nDays < 0) == 
(rTime.GetTime() < 0));
+    Normalize(rTime.GetHour(), rTime.GetMin(), rTime.GetSec(), 
rTime.GetNanoSec(),
+              ((nDays < 0) || (rTime.GetTime() < 0)));
+}
+
+Duration::Duration(sal_Int32 nDays, sal_uInt32 nHours, sal_uInt32 nMinutes, 
sal_uInt32 nSeconds,
+                   sal_uInt64 nNanoseconds)
+    : mnDays(nDays)
+{
+    Normalize(nHours, nMinutes, nSeconds, nNanoseconds, nDays < 0);
+}
+
 Duration::Duration(sal_Int32 nDays, sal_Int64 nTime)
     : maTime(nTime)
     , mnDays(nDays)
 {
 }
 
+void Duration::Normalize(sal_uInt64 nHours, sal_uInt64 nMinutes, sal_uInt64 
nSeconds,
+                         sal_uInt64 nNanoseconds, bool bNegative)
+{
+    if (nNanoseconds >= Time::nanoSecPerSec)
+    {
+        nSeconds += nNanoseconds / Time::nanoSecPerSec;
+        nNanoseconds %= Time::nanoSecPerSec;
+    }
+    if (nSeconds >= Time::secondPerMinute)
+    {
+        nMinutes += nSeconds / Time::secondPerMinute;
+        nSeconds %= Time::secondPerMinute;
+    }
+    if (nMinutes >= Time::minutePerHour)
+    {
+        nHours += nMinutes / Time::minutePerHour;
+        nMinutes %= Time::minutePerHour;
+    }
+    if (nHours >= Time::hourPerDay)
+    {
+        sal_Int64 nDiff = nHours / Time::hourPerDay;
+        nHours %= Time::hourPerDay;
+        bool bOverflow = false;
+        if (bNegative)
+        {
+            nDiff = -nDiff;
+            bOverflow = (nDiff < SAL_MIN_INT32);
+            bOverflow |= o3tl::checked_add(mnDays, 
static_cast<sal_Int32>(nDiff), mnDays);
+            if (bOverflow)
+                mnDays = SAL_MIN_INT32;
+        }
+        else
+        {
+            bOverflow = (nDiff > SAL_MAX_INT32);
+            bOverflow |= o3tl::checked_add(mnDays, 
static_cast<sal_Int32>(nDiff), mnDays);
+            if (bOverflow)
+                mnDays = SAL_MAX_INT32;
+        }
+        assert(!bOverflow);
+        if (bOverflow)
+        {
+            nHours = Time::hourPerDay - 1;
+            nMinutes = Time::minutePerHour - 1;
+            nSeconds = Time::secondPerMinute - 1;
+            nNanoseconds = Time::nanoSecPerSec - 1;
+        }
+    }
+    maTime = Time(nHours, nMinutes, nSeconds, nNanoseconds);
+    if (bNegative)
+        maTime = -maTime;
+    assert(mnDays == 0 || maTime.GetTime() == 0 || (mnDays < 0) == 
(maTime.GetTime() < 0));
+}
+
 void Duration::ApplyTime(sal_Int64 nNS)
 {
     if (mnDays > 0 && nNS < 0)
@@ -105,7 +176,7 @@ void Duration::ApplyTime(sal_Int64 nNS)
         nNS = -Time::nanoSecPerDay + nNS;
     }
     maTime.MakeTimeFromNS(nNS);
-    assert(mnDays == 0 || maTime.GetTime() == 0 || (mnDays < 0) == (nNS < 0));
+    assert(mnDays == 0 || maTime.GetTime() == 0 || (mnDays < 0) == 
(maTime.GetTime() < 0));
 }
 
 void Duration::SetTimeDiff(const Time& rStart, const Time& rEnd)
@@ -168,7 +239,7 @@ Duration Duration::Mult(sal_Int32 nMult, bool& rbOverflow) 
const
     }
     if (bBadNS)
     {
-        // Simple calculation in overall nanoseconds overflew, try with
+        // Simple calculation in overall nanoseconds overflowed, try with
         // individual components.
         const sal_uInt64 nMult64 = (nMult < 0) ? -nMult : nMult;
         do
diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx
index 148bf0cbecc6..fcfa2e080e99 100644
--- a/tools/source/datetime/ttime.cxx
+++ b/tools/source/datetime/ttime.cxx
@@ -125,6 +125,18 @@ void tools::Time::init( sal_uInt32 nHour, sal_uInt32 nMin, 
sal_uInt32 nSec, sal_
     nHour    += nMin / minInHour;
     nMin     %= minInHour;
 
+    // 922337 * HOUR_MASK = 9223370000000000000 largest possible value, 922338
+    // would be -9223364073709551616.
+    assert(HOUR_MASK * nHour >= 0 && "use tools::Duration with days instead!");
+    if (HOUR_MASK * nHour < 0)
+        nHour = 922337;
+
+    // But as is, GetHour() retrieves only sal_uInt16. Though retrieving in
+    // nanoseconds or milliseconds might be possible this is all crap.
+    assert(nHour <= SAL_MAX_UINT16 && "use tools::Duration with days 
instead!");
+    if (nHour > SAL_MAX_UINT16)
+        nHour = SAL_MAX_UINT16;
+
     // construct time
     nTime = nNanoSec +
             nSec  * SEC_MASK +

Reply via email to