diff options
author | Lionel Elie Mamane <lionel@mamane.lu> | 2013-03-17 08:36:26 +0100 |
---|---|---|
committer | Lionel Elie Mamane <lionel@mamane.lu> | 2013-04-18 21:34:46 +0200 |
commit | 9830fd36dbdb72c79703b0c61efc027fba793c5a (patch) | |
tree | 2e9d698e6ca109dc6627adb5c84aa2b635bcfe92 /forms | |
parent | 5aaaf0694b6e3213685563fc3bc90d19b10f5c75 (diff) |
date/time IDL datatypes incompatible change
- nanosecond precision
- signed (allowed negative) year
Also: assorted improvements / bugfixes in date/time handling code.
Some factorisation of copy/pasted code.
Change-Id: I761a1b0b8731c82f19a0c37acbcf43d3c06d6cd6
Diffstat (limited to 'forms')
-rw-r--r-- | forms/qa/integration/forms/TimeValidator.java | 4 | ||||
-rw-r--r-- | forms/source/component/Time.cxx | 13 | ||||
-rw-r--r-- | forms/source/xforms/convert.cxx | 102 | ||||
-rw-r--r-- | forms/source/xforms/datatypes.cxx | 13 |
4 files changed, 34 insertions, 98 deletions
diff --git a/forms/qa/integration/forms/TimeValidator.java b/forms/qa/integration/forms/TimeValidator.java index ab9f036c2b67..36d1ae8f6e90 100644 --- a/forms/qa/integration/forms/TimeValidator.java +++ b/forms/qa/integration/forms/TimeValidator.java @@ -70,11 +70,11 @@ public class TimeValidator extends integration.forms.ControlValidator private boolean isInvalidTime( com.sun.star.util.Time timeValue ) { - return ( timeValue.Hours == -1 ) && ( timeValue.Minutes == -1 ) && ( timeValue.Seconds == -1 ) && ( timeValue.HundredthSeconds == -1 ); + return ( timeValue.Hours == -1 ) && ( timeValue.Minutes == -1 ) && ( timeValue.Seconds == -1 ) && ( timeValue.NanoSeconds == -1 ); } private boolean isFullHour( com.sun.star.util.Time timeValue ) { - return ( timeValue.Minutes == 0 ) && ( timeValue.Seconds == 0 ) && ( timeValue.HundredthSeconds == 0 ); + return ( timeValue.Minutes == 0 ) && ( timeValue.Seconds == 0 ) && ( timeValue.NanoSeconds == 0 ); } } diff --git a/forms/source/component/Time.cxx b/forms/source/component/Time.cxx index 7b7b56c2821c..420a317fcefd 100644 --- a/forms/source/component/Time.cxx +++ b/forms/source/component/Time.cxx @@ -246,7 +246,7 @@ sal_Bool OTimeModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) util::Time aTime; if ( !( aControlValue >>= aTime ) ) { - sal_Int32 nAsInt(0); + sal_Int64 nAsInt(0); aControlValue >>= nAsInt; aTime = DBTypeConversion::toTime(nAsInt); } @@ -256,7 +256,7 @@ sal_Bool OTimeModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) else { util::DateTime aDateTime = m_xColumn->getTimestamp(); - aDateTime.HundredthSeconds = aTime.HundredthSeconds; + aDateTime.NanoSeconds = aTime.NanoSeconds; aDateTime.Seconds = aTime.Seconds; aDateTime.Minutes = aTime.Minutes; aDateTime.Hours = aTime.Hours; @@ -279,7 +279,7 @@ void OTimeModel::impl_translateControlValueToUNOTime( Any& _rUNOValue ) const _rUNOValue = getControlValue(); if ( _rUNOValue.hasValue() ) { - sal_Int32 nTime = 0; + sal_Int64 nTime = 0; OSL_VERIFY( _rUNOValue >>= nTime ); if ( nTime == ::Time( 99, 99, 99 ).GetTime() ) // "invalid time" in VCL is different from "invalid time" in UNO @@ -305,7 +305,7 @@ Any OTimeModel::translateExternalValueToControlValue( const Any& _rExternalValue { util::Time aTime; OSL_VERIFY( _rExternalValue >>= aTime ); - aControlValue <<= DBTypeConversion::toINT32( aTime ); + aControlValue <<= DBTypeConversion::toINT64( aTime ); } return aControlValue; } @@ -325,8 +325,9 @@ Any OTimeModel::translateDbColumnToControlValue() if ( m_xColumn->wasNull() ) m_aSaveValue.clear(); else - // the aggregated set expects an Int32 as value ... - m_aSaveValue <<= DBTypeConversion::toINT32( aTime ); + // TODO FIXME: "the aggregated set expects an Int32 as value ..." + // need to fix it for int64 + m_aSaveValue <<= DBTypeConversion::toINT64( aTime ); return m_aSaveValue; } diff --git a/forms/source/xforms/convert.cxx b/forms/source/xforms/convert.cxx index b440f4b3705f..6dac9298aa6a 100644 --- a/forms/source/xforms/convert.cxx +++ b/forms/source/xforms/convert.cxx @@ -33,13 +33,14 @@ #include <com/sun/star/util/Date.hpp> #include <com/sun/star/util/DateTime.hpp> #include <com/sun/star/util/Time.hpp> +#include <unotools/datetime.hxx> using xforms::Convert; using com::sun::star::uno::Any; using com::sun::star::uno::makeAny; -using com::sun::star::util::Time; using namespace std; using namespace o3tl; +using namespace utl; typedef com::sun::star::util::Date UNODate; typedef com::sun::star::util::Time UNOTime; @@ -279,30 +280,7 @@ namespace UNODate aDate( 1, 1, 1900 ); - sal_Int32 nToken = 0; - StringTokenizer aTokenizer( rString, '-' ); - while ( aTokenizer.hasNextToken() ) - { - sal_Int32 nTokenValue = 0; - if ( !aTokenizer.getNextToken().toInt32( nTokenValue ) ) - { - bWellformed = false; - break; - } - - if ( nToken == 0 ) - aDate.Year = (sal_uInt16)nTokenValue; - else if ( nToken == 1 ) - aDate.Month = (sal_uInt16)nTokenValue; - else if ( nToken == 2 ) - aDate.Day = (sal_uInt16)nTokenValue; - else - { - bWellformed = false; - break; - } - ++nToken; - } + bWellformed = ISO8601parseDate(rString, aDate); // sanity checks if ( ( aDate.Year > 9999 ) || ( aDate.Month < 1 ) || ( aDate.Month > 12 ) || ( aDate.Day < 1 ) || ( aDate.Day > 31 ) ) @@ -337,10 +315,15 @@ namespace lcl_appendInt32ToBuffer( rTime.Minutes, sInfo, 2 ); sInfo.appendAscii( ":" ); lcl_appendInt32ToBuffer( rTime.Seconds, sInfo, 2 ); - if ( rTime.HundredthSeconds ) + if ( rTime.NanoSeconds != 0 ) { - sInfo.appendAscii( "." ); - lcl_appendInt32ToBuffer( rTime.HundredthSeconds, sInfo, 2 ); + OSL_ENSURE(rTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999"); + sInfo.append('.'); + std::ostringstream ostr; + ostr.fill('0'); + ostr.width(9); + ostr << rTime.NanoSeconds; + sInfo.append(OUString::createFromAscii(ostr.str().c_str())); } return sInfo.makeStringAndClear(); @@ -361,62 +344,7 @@ namespace UNOTime aTime( 0, 0, 0, 0 ); - OUString sString( rString ); - // see if there's a decimal separator for the seconds, - // and if so, handle it separately - sal_Int32 nDecimalSepPos = rString.indexOf( '.' ); - if ( nDecimalSepPos == -1 ) - // ISO 8601 allows for both a comma and a dot - nDecimalSepPos = rString.indexOf( ',' ); - if ( nDecimalSepPos != -1 ) - { - // handle fractional seconds - OUString sFractional = sString.copy( nDecimalSepPos + 1 ); - if ( sFractional.getLength() > 2 ) - // our precision is HundrethSeconds - it's all a css.util.Time can hold - sFractional = sFractional.copy( 0, 2 ); - if ( !sFractional.isEmpty() ) - { - sal_Int32 nFractional = 0; - if ( StringTokenizer( sFractional, 0 ).getNextToken().toInt32( nFractional ) ) - { - aTime.HundredthSeconds = (sal_uInt16)nFractional; - if ( nFractional < 10 ) - aTime.HundredthSeconds *= 10; - } - else - bWellformed = false; - } - - // strip the fraction before further processing - sString = sString.copy( 0, nDecimalSepPos ); - } - - // split into the tokens which are separated by colon - sal_Int32 nToken = 0; - StringTokenizer aTokenizer( sString, ':' ); - while ( aTokenizer.hasNextToken() ) - { - sal_Int32 nTokenValue = 0; - if ( !aTokenizer.getNextToken().toInt32( nTokenValue ) ) - { - bWellformed = false; - break; - } - - if ( nToken == 0 ) - aTime.Hours = (sal_uInt16)nTokenValue; - else if ( nToken == 1 ) - aTime.Minutes = (sal_uInt16)nTokenValue; - else if ( nToken == 2 ) - aTime.Seconds = (sal_uInt16)nTokenValue; - else - { - bWellformed = false; - break; - } - ++nToken; - } + bWellformed = ISO8601parseTime(rString, aTime); // sanity checks // note that Seconds == 60 denotes leap seconds. Normally, they're not allowed everywhere, @@ -431,7 +359,7 @@ namespace && ( aTime.Hours == 24 ) && ( ( aTime.Minutes != 0 ) || ( aTime.Seconds != 0 ) - || ( aTime.HundredthSeconds != 0 ) + || ( aTime.NanoSeconds != 0 ) ) ) bWellformed = false; @@ -458,7 +386,7 @@ namespace UNODate aDate( aDateTime.Day, aDateTime.Month, aDateTime.Year ); OUString sDate = lcl_toXSD_UNODate_typed( aDate ); - UNOTime aTime( aDateTime.HundredthSeconds, aDateTime.Seconds, aDateTime.Minutes, aDateTime.Hours ); + UNOTime aTime( aDateTime.NanoSeconds, aDateTime.Seconds, aDateTime.Minutes, aDateTime.Hours ); OUString sTime = lcl_toXSD_UNOTime_typed( aTime ); OUStringBuffer sInfo; @@ -489,7 +417,7 @@ namespace aTime = lcl_toUNOTime( rString.copy( nDateTimeSep + 1 ) ); } UNODateTime aDateTime( - aTime.HundredthSeconds, aTime.Seconds, aTime.Minutes, aTime.Hours, + aTime.NanoSeconds, aTime.Seconds, aTime.Minutes, aTime.Hours, aDate.Day, aDate.Month, aDate.Year ); return makeAny( aDateTime ); diff --git a/forms/source/xforms/datatypes.cxx b/forms/source/xforms/datatypes.cxx index e1fcdebecf24..66dbd907856a 100644 --- a/forms/source/xforms/datatypes.cxx +++ b/forms/source/xforms/datatypes.cxx @@ -829,7 +829,14 @@ namespace xforms if ( !( aTypedValue >>= aValue ) ) return false; - ::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.HundredthSeconds ); + ::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.NanoSeconds ); + // no loss/rounding; IEEE 754 double-precision floating-point + // has a mantissa of 53 bits; we need at the very most 50 bits: + // format of aToolsTime.GetTime() is (in decimal) hhmmssnnnnnnnnn + // and 999999999999999 = 0x38D7EA4C67FFF + // in reality I doubt we need (much) more than + // 240000000000000 = 0x0DA475ABF0000 + // that is 48 bits fValue = aToolsTime.GetTime(); return true; } @@ -846,7 +853,7 @@ namespace xforms { Time aValue; OSL_VERIFY( _rValue >>= aValue ); - ::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.HundredthSeconds ); + ::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.NanoSeconds ); _rDoubleValue = aToolsTime.GetTime(); } @@ -869,7 +876,7 @@ namespace xforms { ::DateTime aToolsValue( ::Date( _rValue.Day, _rValue.Month, _rValue.Year ), - ::Time( _rValue.Hours, _rValue.Minutes, _rValue.Seconds, _rValue.HundredthSeconds ) + ::Time( _rValue.Hours, _rValue.Minutes, _rValue.Seconds, _rValue.NanoSeconds ) ); double fValue = 0; |