xmloff/source/core/xmluconv.cxx |  101 ++++++++++++++--------------------------
 1 file changed, 36 insertions(+), 65 deletions(-)

New commits:
commit 238f180e0813368f697b77768b1ca50714ae47ed
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Fri Aug 31 18:18:41 2018 +0200
Commit:     Eike Rathke <er...@redhat.com>
CommitDate: Mon Sep 3 08:37:50 2018 +0200

    SvXMLUnitConverter::convertDateTime: use tools::Time::GetClock()
    
    ... to not round up to the next magnitude.
    
    Change-Id: Ibda6e014ae3bdbe021e208c8781f619b112bee21
    Reviewed-on: https://gerrit.libreoffice.org/59887
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Eike Rathke <er...@redhat.com>

diff --git a/xmloff/source/core/xmluconv.cxx b/xmloff/source/core/xmluconv.cxx
index 76f9467b9fe4..237c041e92cc 100644
--- a/xmloff/source/core/xmluconv.cxx
+++ b/xmloff/source/core/xmluconv.cxx
@@ -319,61 +319,12 @@ void SvXMLUnitConverter::convertDateTime( OUStringBuffer& 
rBuffer,
         bool bAddTimeIf0AM )
 {
     double fValue = fDateTime;
-    sal_Int32 nValue = static_cast <sal_Int32> (::rtl::math::approxFloor 
(fValue));
+    const sal_Int32 nDays = static_cast <sal_Int32> (::rtl::math::approxFloor 
(fValue));
     Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
-    aDate.AddDays( nValue);
-    fValue -= nValue;
-    double fCount;
-    if (nValue > 0)
-         fCount = ::rtl::math::approxFloor 
(log10(static_cast<double>(nValue))) + 1;
-    else if (nValue < 0)
-         fCount = ::rtl::math::approxFloor (log10(static_cast<double>(nValue * 
-1))) + 1;
-    else
-        fCount = 0.0;
-    sal_Int16 nCount = sal_Int16(fCount);
-    bool bHasTime(false);
-    double fHoursValue = 0;
-    double fMinsValue = 0;
-    double fSecsValue = 0;
-    double f100SecsValue = 0;
-    if (fValue > 0.0)
-    {
-        bHasTime = true;
-        fValue *= 24;
-        fHoursValue = ::rtl::math::approxFloor (fValue);
-        fValue -= fHoursValue;
-        fValue *= 60;
-        fMinsValue = ::rtl::math::approxFloor (fValue);
-        fValue -= fMinsValue;
-        fValue *= 60;
-        fSecsValue = ::rtl::math::approxFloor (fValue);
-        fValue -= fSecsValue;
-        if (fValue > 0.0)
-            f100SecsValue = ::rtl::math::round( fValue, 
XML_MAXDIGITSCOUNT_TIME - nCount);
-        else
-            f100SecsValue = 0.0;
+    aDate.AddDays( nDays);
+    fValue -= nDays;
+    const bool bHasTime = (fValue > 0.0);
 
-        if (f100SecsValue == 1.0)
-        {
-            f100SecsValue = 0.0;
-            fSecsValue += 1.0;
-        }
-        if (fSecsValue >= 60.0)
-        {
-            fSecsValue -= 60.0;
-            fMinsValue += 1.0;
-        }
-        if (fMinsValue >= 60.0)
-        {
-            fMinsValue -= 60.0;
-            fHoursValue += 1.0;
-        }
-        if (fHoursValue >= 24.0)
-        {
-            fHoursValue -= 24.0;
-            aDate.AddDays(1);
-        }
-    }
     sal_Int16 nTempYear = aDate.GetYear();
     assert(nTempYear != 0);
     if (nTempYear < 0)
@@ -400,29 +351,49 @@ void SvXMLUnitConverter::convertDateTime( OUStringBuffer& 
rBuffer,
     if (nTemp < 10)
         rBuffer.append( '0');
     rBuffer.append( sal_Int32( nTemp));
-    if(bHasTime || bAddTimeIf0AM)
+    if (bHasTime || bAddTimeIf0AM)
     {
+        double fCount;
+        if (nDays > 0)
+            fCount = ::rtl::math::approxFloor 
(log10(static_cast<double>(nDays))) + 1;
+        else if (nDays < 0)
+            fCount = ::rtl::math::approxFloor (log10(static_cast<double>(nDays 
* -1))) + 1;
+        else
+            fCount = 0.0;
+        const int nDigits = sal_Int16(fCount) + 4;  // +4 for *86400 in seconds
+        const int nFractionDecimals = std::max( XML_MAXDIGITSCOUNT_TIME - 
nDigits, 0);
+
+        sal_uInt16 nHour, nMinute, nSecond;
+        double fFractionOfSecond;
+        // Pass the original date+time value for proper scaling and rounding.
+        tools::Time::GetClock( fDateTime, nHour, nMinute, nSecond, 
fFractionOfSecond, nFractionDecimals);
+
         rBuffer.append( 'T');
-        if (fHoursValue < 10)
+        if (nHour < 10)
             rBuffer.append( '0');
-        rBuffer.append( sal_Int32( fHoursValue));
+        rBuffer.append( sal_Int32( nHour));
         rBuffer.append( ':');
-        if (fMinsValue < 10)
+        if (nMinute < 10)
             rBuffer.append( '0');
-        rBuffer.append( sal_Int32( fMinsValue));
+        rBuffer.append( sal_Int32( nMinute));
         rBuffer.append( ':');
-        if (fSecsValue < 10)
+        if (nSecond < 10)
             rBuffer.append( '0');
-        rBuffer.append( sal_Int32( fSecsValue));
-        if (f100SecsValue > 0.0)
+        rBuffer.append( sal_Int32( nSecond));
+        if (nFractionDecimals)
         {
-            OUString a100th( ::rtl::math::doubleToUString( fValue,
+            // nFractionDecimals+1 to not round up what GetClock() carefully
+            // truncated.
+            OUString aFraction( ::rtl::math::doubleToUString( 
fFractionOfSecond,
                         rtl_math_StringFormat_F,
-                        XML_MAXDIGITSCOUNT_TIME - nCount, '.', true));
-            if ( a100th.getLength() > 2 )
+                        nFractionDecimals + 1, '.', true));
+            const sal_Int32 nLen = aFraction.getLength();
+            if ( nLen > 2 )
             {
+                // Truncate nFractionDecimals+1 digit if it was not rounded to 
zero.
+                const sal_Int32 nCount = nLen - 2 - static_cast<int>(nLen > 
nFractionDecimals + 2);
                 rBuffer.append( '.');
-                rBuffer.appendCopy( a100th, 2 );     // strip 0.
+                rBuffer.appendCopy( aFraction, 2, nCount);     // strip 0.
             }
         }
     }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to