diff options
Diffstat (limited to 'sax/source')
-rw-r--r-- | sax/source/tools/converter.cxx | 209 |
1 files changed, 155 insertions, 54 deletions
diff --git a/sax/source/tools/converter.cxx b/sax/source/tools/converter.cxx index c77e02aa402b..b5c9934636f4 100644 --- a/sax/source/tools/converter.cxx +++ b/sax/source/tools/converter.cxx @@ -1234,6 +1234,69 @@ void Converter::convertDate( convertDateTime(i_rBuffer, dt, pTimeZoneOffset, false); } +static void convertTime( + OUStringBuffer& i_rBuffer, + const com::sun::star::util::DateTime& i_rDateTime) +{ + if (i_rDateTime.Hours < 10) { + i_rBuffer.append(sal_Unicode('0')); + } + i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Hours) ) + .append(sal_Unicode(':')); + if (i_rDateTime.Minutes < 10) { + i_rBuffer.append(sal_Unicode('0')); + } + i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Minutes) ) + .append(sal_Unicode(':')); + if (i_rDateTime.Seconds < 10) { + i_rBuffer.append(sal_Unicode('0')); + } + i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) ); + if (i_rDateTime.NanoSeconds > 0) { + OSL_ENSURE(i_rDateTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999"); + i_rBuffer.append(sal_Unicode('.')); + std::ostringstream ostr; + ostr.fill('0'); + ostr.width(9); + ostr << i_rDateTime.NanoSeconds; + i_rBuffer.append(OUString::createFromAscii(ostr.str().c_str())); + } +} + +static void convertTimeZone( + OUStringBuffer& i_rBuffer, + const com::sun::star::util::DateTime& i_rDateTime, + sal_Int16 const* pTimeZoneOffset) +{ + if (pTimeZoneOffset) + { + lcl_AppendTimezone(i_rBuffer, *pTimeZoneOffset); + } + else if (i_rDateTime.IsUTC) + { + lcl_AppendTimezone(i_rBuffer, 0); + } +} + +/** convert util::DateTime to ISO "time" or "dateTime" string */ +void Converter::convertTimeOrDateTime( + OUStringBuffer& i_rBuffer, + const com::sun::star::util::DateTime& i_rDateTime, + sal_Int16 const* pTimeZoneOffset) +{ + if (i_rDateTime.Year == 0 || + i_rDateTime.Month < 1 || i_rDateTime.Month > 12 || + i_rDateTime.Day < 1 || i_rDateTime.Day > 31) + { + convertTime(i_rBuffer, i_rDateTime); + convertTimeZone(i_rBuffer, i_rDateTime, pTimeZoneOffset); + } + else + { + convertDateTime(i_rBuffer, i_rDateTime, pTimeZoneOffset, true); + } +} + /** convert util::DateTime to ISO "date" or "dateTime" string */ void Converter::convertDateTime( OUStringBuffer& i_rBuffer, @@ -1242,10 +1305,7 @@ void Converter::convertDateTime( bool i_bAddTimeIf0AM ) { const sal_Unicode dash('-'); - const sal_Unicode col (':'); - const sal_Unicode dot ('.'); const sal_Unicode zero('0'); - const sal_Unicode tee ('T'); sal_Int32 const nYear(abs(i_rDateTime.Year)); if (i_rDateTime.Year < 0) { @@ -1275,41 +1335,11 @@ void Converter::convertDateTime( i_rDateTime.Hours != 0 || i_bAddTimeIf0AM ) { - i_rBuffer.append(tee); - if( i_rDateTime.Hours < 10 ) { - i_rBuffer.append(zero); - } - i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Hours) ) - .append(col); - if( i_rDateTime.Minutes < 10 ) { - i_rBuffer.append(zero); - } - i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Minutes) ) - .append(col); - if( i_rDateTime.Seconds < 10 ) { - i_rBuffer.append(zero); - } - i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) ); - if( i_rDateTime.NanoSeconds > 0 ) { - OSL_ENSURE(i_rDateTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999"); - i_rBuffer.append(dot); - std::ostringstream ostr; - ostr.fill('0'); - ostr.width(9); - ostr << i_rDateTime.NanoSeconds; - i_rBuffer.append(OUString::createFromAscii(ostr.str().c_str())); - } + i_rBuffer.append(sal_Unicode('T')); + convertTime(i_rBuffer, i_rDateTime); } - if (pTimeZoneOffset) - { - lcl_AppendTimezone(i_rBuffer, *pTimeZoneOffset); - } - else if (i_rDateTime.IsUTC) - { - // append local time - lcl_AppendTimezone(i_rBuffer, 0); - } + convertTimeZone(i_rBuffer, i_rDateTime, pTimeZoneOffset); } /** convert ISO "date" or "dateTime" string to util::DateTime */ @@ -1362,11 +1392,17 @@ static void lcl_ConvertToUTC( { return; } + sal_Int16 nDayAdd(0); while (24 <= o_rHours) { o_rHours -= 24; - ++o_rDay; + ++nDayAdd; + } + if (o_rDay == 0) + { + return; // handle time without date - don't adjust what isn't there } + o_rDay += nDayAdd; sal_Int16 const nDaysInMonth(lcl_MaxDaysPerMonth(o_rMonth, o_rYear)); if (o_rDay <= nDaysInMonth) { @@ -1397,6 +1433,10 @@ static void lcl_ConvertToUTC( ++nDaySubtract; } o_rHours -= nOffsetHours; + if (o_rDay == 0) + { + return; // handle time without date - don't adjust what isn't there + } if (nDaySubtract < o_rDay) { o_rDay -= nDaySubtract; @@ -1436,20 +1476,17 @@ readDateTimeComponent(const OUString & rString, return true; } - - /** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */ -bool Converter::parseDateOrDateTime( - util::Date *const pDate, util::DateTime & rDateTime, - bool & rbDateTime, - boost::optional<sal_Int16> *const pTimeZoneOffset, - const OUString & rString ) +static bool lcl_parseDate( + bool & isNegative, + sal_Int32 & nYear, sal_Int32 & nMonth, sal_Int32 & nDay, + bool & bHaveTime, + sal_Int32 & nPos, + const OUString & string, + bool const bIgnoreInvalidOrMissingDate) { bool bSuccess = true; - bool isNegative(false); - const OUString string = rString.trim().toAsciiUpperCase(); - sal_Int32 nPos(0); if (string.getLength() > nPos) { if ('-' == string[nPos]) @@ -1459,13 +1496,15 @@ bool Converter::parseDateOrDateTime( } } - sal_Int32 nYear(0); { // While W3C XMLSchema specifies years with a minimum of 4 digits, be // leninent in what we accept for years < 1000. One digit is acceptable // if the remainders match. bSuccess = readDateTimeComponent(string, nPos, nYear, 1, false); - bSuccess &= (0 < nYear); + if (!bIgnoreInvalidOrMissingDate) + { + bSuccess &= (0 < nYear); + } bSuccess &= (nPos < string.getLength()); // not last token } if (bSuccess && ('-' != string[nPos])) // separator @@ -1477,11 +1516,14 @@ bool Converter::parseDateOrDateTime( ++nPos; } - sal_Int32 nMonth(0); if (bSuccess) { bSuccess = readDateTimeComponent(string, nPos, nMonth, 2, true); - bSuccess &= (0 < nMonth) && (nMonth <= 12); + if (!bIgnoreInvalidOrMissingDate) + { + bSuccess &= (0 < nMonth); + } + bSuccess &= (nMonth <= 12); bSuccess &= (nPos < string.getLength()); // not last token } if (bSuccess && ('-' != string[nPos])) // separator @@ -1493,14 +1535,16 @@ bool Converter::parseDateOrDateTime( ++nPos; } - sal_Int32 nDay(0); if (bSuccess) { bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true); - bSuccess &= (0 < nDay) && (nDay <= lcl_MaxDaysPerMonth(nMonth, nYear)); + if (!bIgnoreInvalidOrMissingDate) + { + bSuccess &= (0 < nDay); + } + bSuccess &= (nDay <= lcl_MaxDaysPerMonth(nMonth, nYear)); } - bool bHaveTime(false); if (bSuccess && (nPos < string.getLength())) { if ('T' == string[nPos]) // time separator @@ -1510,6 +1554,41 @@ bool Converter::parseDateOrDateTime( } } + return bSuccess; +} + +/** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */ +static bool lcl_parseDateTime( + util::Date *const pDate, util::DateTime & rDateTime, + bool & rbDateTime, + boost::optional<sal_Int16> *const pTimeZoneOffset, + const OUString & rString, + bool const bIgnoreInvalidOrMissingDate) +{ + bool bSuccess = true; + + const OUString string = rString.trim().toAsciiUpperCase(); + + bool isNegative(false); + sal_Int32 nYear(0); + sal_Int32 nMonth(0); + sal_Int32 nDay(0); + sal_Int32 nPos(0); + bool bHaveTime(false); + + if ( !bIgnoreInvalidOrMissingDate + || string.indexOf(':') == -1 // no time? + || (string.indexOf('-') != -1 + && string.indexOf('-') < string.indexOf(':'))) + { + bSuccess &= lcl_parseDate(isNegative, nYear, nMonth, nDay, + bHaveTime, nPos, string, bIgnoreInvalidOrMissingDate); + } + else + { + bHaveTime = true; + } + sal_Int32 nHours(0); sal_Int32 nMinutes(0); sal_Int32 nSeconds(0); @@ -1708,6 +1787,28 @@ bool Converter::parseDateOrDateTime( return bSuccess; } +/** convert ISO "time" or "dateTime" string to util::DateTime */ +bool Converter::parseTimeOrDateTime( + util::DateTime & rDateTime, + boost::optional<sal_Int16> * pTimeZoneOffset, + const OUString & rString) +{ + bool dummy; + return lcl_parseDateTime( + 0, rDateTime, dummy, pTimeZoneOffset, rString, true); +} + +/** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */ +bool Converter::parseDateOrDateTime( + util::Date *const pDate, util::DateTime & rDateTime, + bool & rbDateTime, + boost::optional<sal_Int16> *const pTimeZoneOffset, + const OUString & rString ) +{ + return lcl_parseDateTime( + pDate, rDateTime, rbDateTime, pTimeZoneOffset, rString, false); +} + /** gets the position of the first comma after npos in the string rStr. Commas inside '"' pairs are not matched */ |