summaryrefslogtreecommitdiff
path: root/xmloff
diff options
context:
space:
mode:
authorFrank Schoenheit [fs] <frank.schoenheit@sun.com>2010-09-15 13:55:35 +0200
committerFrank Schoenheit [fs] <frank.schoenheit@sun.com>2010-09-15 13:55:35 +0200
commit3810e697af86a7e044d5ae305a172bfec23ab166 (patch)
tree70b4f72c8bd4154aa892ac66ce06730d82a79cd9 /xmloff
parentd09dd8986436f17717443823ef18bd8552fdf408 (diff)
dba34a: #i110304# when converting a string to a css.util.DateTime, don't go the way via a float, as it causes rounding errors
Diffstat (limited to 'xmloff')
-rw-r--r--xmloff/source/core/xmluconv.cxx88
1 files changed, 41 insertions, 47 deletions
diff --git a/xmloff/source/core/xmluconv.cxx b/xmloff/source/core/xmluconv.cxx
index 28abf2edbcbd..4a748f99ec54 100644
--- a/xmloff/source/core/xmluconv.cxx
+++ b/xmloff/source/core/xmluconv.cxx
@@ -874,32 +874,27 @@ void SvXMLUnitConverter::convertTime( ::rtl::OUStringBuffer& rBuffer,
}
/** convert ISO Time String to double; negative durations allowed */
-sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
- const ::rtl::OUString& rString)
+static bool lcl_convertTime( const ::rtl::OUString& rString, sal_Int32& o_rDays, sal_Int32& o_rHours, sal_Int32& o_rMins,
+ sal_Int32& o_rSecs, sal_Bool& o_rIsNegativeTime, double& o_rFractionalSecs )
{
rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase();
const sal_Unicode* pStr = aTrimmed.getStr();
// negative time duration?
- sal_Bool bIsNegativeDuration = sal_False;
if ( sal_Unicode('-') == (*pStr) )
{
- bIsNegativeDuration = sal_True;
+ o_rIsNegativeTime = sal_True;
pStr++;
}
if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P"
- return sal_False;
+ return false;
- rtl::OUString sDoubleStr;
- sal_Bool bSuccess = sal_True;
+ ::rtl::OUString sDoubleStr;
+ sal_Bool bSuccess = true;
sal_Bool bDone = sal_False;
sal_Bool bTimePart = sal_False;
sal_Bool bIsFraction = sal_False;
- sal_Int32 nDays = 0;
- sal_Int32 nHours = 0;
- sal_Int32 nMins = 0;
- sal_Int32 nSecs = 0;
sal_Int32 nTemp = 0;
while ( bSuccess && !bDone )
@@ -910,7 +905,7 @@ sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c )
{
if ( nTemp >= SAL_MAX_INT32 / 10 )
- bSuccess = sal_False;
+ bSuccess = false;
else
{
if ( !bIsFraction )
@@ -928,17 +923,17 @@ sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
{
if ( c == sal_Unicode('H') )
{
- nHours = nTemp;
+ o_rHours = nTemp;
nTemp = 0;
}
else if ( c == sal_Unicode('M') )
{
- nMins = nTemp;
+ o_rMins = nTemp;
nTemp = 0;
}
else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) )
{
- nSecs = nTemp;
+ o_rSecs = nTemp;
nTemp = 0;
bIsFraction = sal_True;
sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
@@ -947,13 +942,13 @@ sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
{
if ( !bIsFraction )
{
- nSecs = nTemp;
+ o_rSecs = nTemp;
nTemp = 0;
sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
}
}
else
- bSuccess = sal_False; // invalid character
+ bSuccess = false; // invalid character
}
else
{
@@ -961,7 +956,7 @@ sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
bTimePart = sal_True;
else if ( c == sal_Unicode('D') )
{
- nDays = nTemp;
+ o_rDays = nTemp;
nTemp = 0;
}
else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') )
@@ -969,14 +964,28 @@ sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
//! how many days is a year or month?
DBG_ERROR("years or months in duration: not implemented");
- bSuccess = sal_False;
+ bSuccess = false;
}
else
- bSuccess = sal_False; // invalid character
+ bSuccess = false; // invalid character
}
}
if ( bSuccess )
+ o_rFractionalSecs = sDoubleStr.toDouble();
+ return bSuccess;
+}
+
+sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
+ const ::rtl::OUString& rString)
+{
+ sal_Int32 nDays = 0;
+ sal_Int32 nHours = 0;
+ sal_Int32 nMins = 0;
+ sal_Int32 nSecs = 0;
+ sal_Bool bIsNegativeDuration = sal_False;
+ double fFractionalSecs = 0.0;
+ if ( lcl_convertTime( rString, nDays, nHours, nMins, nSecs, bIsNegativeDuration, fFractionalSecs ) )
{
if ( nDays )
nHours += nDays * 24; // add the days to the hours part
@@ -985,12 +994,11 @@ sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
double fMin = nMins;
double fSec = nSecs;
double fSec100 = 0.0;
- double fFraction = sDoubleStr.toDouble();
fTempTime = fHour / 24;
fTempTime += fMin / (24 * 60);
fTempTime += fSec / (24 * 60 * 60);
fTempTime += fSec100 / (24 * 60 * 60 * 60);
- fTempTime += fFraction / (24 * 60 * 60);
+ fTempTime += fFractionalSecs / (24 * 60 * 60);
// negative duration?
if ( bIsNegativeDuration )
@@ -999,8 +1007,9 @@ sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
}
fTime = fTempTime;
+ return sal_True;
}
- return bSuccess;
+ return sal_False;
}
/** convert util::DateTime to ISO Time String */
@@ -1022,33 +1031,18 @@ void SvXMLUnitConverter::convertTime( ::rtl::OUStringBuffer& rBuffer,
sal_Bool SvXMLUnitConverter::convertTime( ::com::sun::star::util::DateTime& rDateTime,
const ::rtl::OUString& rString )
{
- double fCalculatedTime = 0.0;
- if( convertTime( fCalculatedTime, rString ) )
- {
- // #101357# declare as volatile to prevent optimization
- // (gcc 3.0.1 Linux)
- volatile double fTempTime = fCalculatedTime;
- fTempTime *= 24;
- double fHoursValue = ::rtl::math::approxFloor (fTempTime);
- fTempTime -= fHoursValue;
- fTempTime *= 60;
- double fMinsValue = ::rtl::math::approxFloor (fTempTime);
- fTempTime -= fMinsValue;
- fTempTime *= 60;
- double fSecsValue = ::rtl::math::approxFloor (fTempTime);
- fTempTime -= fSecsValue;
- double f100SecsValue = 0.0;
-
- if( fTempTime > 0.00001 )
- f100SecsValue = fTempTime;
-
+ sal_Int32 nDays = 0, nHours = 0, nMins = 0, nSecs = 0;
+ sal_Bool bIsNegativeDuration = sal_False;
+ double fFractionalSecs = 0.0;
+ if ( lcl_convertTime( rString, nDays, nHours, nMins, nSecs, bIsNegativeDuration, fFractionalSecs ) )
+ {
rDateTime.Year = 0;
rDateTime.Month = 0;
rDateTime.Day = 0;
- rDateTime.Hours = static_cast < sal_uInt16 > ( fHoursValue );
- rDateTime.Minutes = static_cast < sal_uInt16 > ( fMinsValue );
- rDateTime.Seconds = static_cast < sal_uInt16 > ( fSecsValue );
- rDateTime.HundredthSeconds = static_cast < sal_uInt16 > ( f100SecsValue * 100.0 );
+ rDateTime.Hours = static_cast < sal_uInt16 > ( nHours );
+ rDateTime.Minutes = static_cast < sal_uInt16 > ( nMins );
+ rDateTime.Seconds = static_cast < sal_uInt16 > ( nSecs );
+ rDateTime.HundredthSeconds = static_cast < sal_uInt16 > ( fFractionalSecs * 100.0 );
return sal_True;
}