diff options
author | Vladimir Glazunov <vg@openoffice.org> | 2010-03-23 11:22:15 +0100 |
---|---|---|
committer | Vladimir Glazunov <vg@openoffice.org> | 2010-03-23 11:22:15 +0100 |
commit | 8be36a8d06699746062540e461f64eec4faeb0a1 (patch) | |
tree | e545ee1e21c4717eaf2c9d2e2fc0547c035a82ba /sax | |
parent | 51b401061b70d699c34f30a21cf6a9fde80dfd75 (diff) | |
parent | 78b9de424c513d36ed8deb63f488df6f875599a2 (diff) |
CWS-TOOLING: integrate CWS sw33bf02
Diffstat (limited to 'sax')
-rw-r--r-- | sax/source/tools/converter.cxx | 580 |
1 files changed, 443 insertions, 137 deletions
diff --git a/sax/source/tools/converter.cxx b/sax/source/tools/converter.cxx index 9bdd91f4b5e4..35bfba29c904 100644 --- a/sax/source/tools/converter.cxx +++ b/sax/source/tools/converter.cxx @@ -909,10 +909,10 @@ void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer, rBuffer.append(static_cast<sal_Int32>(rDuration.Days)); rBuffer.append(sal_Unicode('D')); } - const sal_Int32 nHSecs(static_cast<sal_Int32>(rDuration.Seconds) - + static_cast<sal_Int32>(rDuration.HundredthSeconds)); + const sal_Int32 nMSecs(static_cast<sal_Int32>(rDuration.Seconds) + + static_cast<sal_Int32>(rDuration.MilliSeconds)); if (static_cast<sal_Int32>(rDuration.Hours) + - static_cast<sal_Int32>(rDuration.Minutes) + nHSecs) + static_cast<sal_Int32>(rDuration.Minutes) + nMSecs) { rBuffer.append(sal_Unicode('T')); // time separator if (rDuration.Hours) @@ -925,20 +925,37 @@ void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer, rBuffer.append(static_cast<sal_Int32>(rDuration.Minutes)); rBuffer.append(sal_Unicode('M')); } - if (nHSecs) + if (nMSecs) { // seconds must not be omitted (i.e. ".42S" is not valid) rBuffer.append(static_cast<sal_Int32>(rDuration.Seconds)); - if (rDuration.HundredthSeconds) + if (rDuration.MilliSeconds) { rBuffer.append(sal_Unicode('.')); - const sal_Int32 nHundredthSeconds( - rDuration.HundredthSeconds % 100); - if (nHundredthSeconds < 10) + const sal_Int32 nMilliSeconds(rDuration.MilliSeconds % 1000); + if (nMilliSeconds < 100) { rBuffer.append(sal_Unicode('0')); } - rBuffer.append(nHundredthSeconds); + if (nMilliSeconds < 10) + { + rBuffer.append(sal_Unicode('0')); + } + if (0 == (nMilliSeconds % 10)) + { + if (0 == (nMilliSeconds % 100)) + { + rBuffer.append(nMilliSeconds / 100); + } + else + { + rBuffer.append(nMilliSeconds / 10); + } + } + else + { + rBuffer.append(nMilliSeconds); + } } rBuffer.append(sal_Unicode('S')); } @@ -959,8 +976,9 @@ readUnsignedNumber(const ::rtl::OUString & rString, { bool bOverflow(false); sal_Int32 nTemp(0); + sal_Int32 nPos(io_rnPos); - for (sal_Int32 nPos = io_rnPos; (nPos < rString.getLength()); ++nPos) + while (nPos < rString.getLength()) { const sal_Unicode c = rString[nPos]; if ((sal_Unicode('0') <= c) && (c <= sal_Unicode('9'))) @@ -974,25 +992,20 @@ readUnsignedNumber(const ::rtl::OUString & rString, } else { - if (io_rnPos != nPos) // read something? - { - io_rnPos = nPos; - if (bOverflow) - { - return R_OVERFLOW; - } - else - { - o_rNumber = nTemp; - return R_SUCCESS; - } - } - else break; + break; } + ++nPos; + } + + if (io_rnPos == nPos) // read something? + { + o_rNumber = -1; + return R_NOTHING; } - o_rNumber = -1; - return R_NOTHING; + io_rnPos = nPos; + o_rNumber = nTemp; + return (bOverflow) ? R_OVERFLOW : R_SUCCESS; } static bool @@ -1069,7 +1082,7 @@ bool Converter::convertDuration(util::Duration& rDuration, sal_Int32 nHours(0); sal_Int32 nMinutes(0); sal_Int32 nSeconds(0); - sal_Int32 nHundredthSeconds(0); + sal_Int32 nMilliSeconds(0); bTimePart = readDurationT(string, nPos); bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp)); @@ -1123,30 +1136,39 @@ bool Converter::convertDuration(util::Duration& rDuration, nTemp = -1; const sal_Int32 nStart(nPos); bSuccess = - (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp)); + (R_NOTHING != readUnsignedNumber(string, nPos, nTemp)); if ((nPos < string.getLength()) && bSuccess) { - if (sal_Unicode('S') == string[nPos]) + if (-1 != nTemp) { - ++nPos; - if (-1 != nTemp) + nTemp = -1; + const sal_Int32 nDigits = nPos - nStart; + OSL_ENSURE(nDigits > 0, "bad code monkey"); + const sal_Unicode cZero('0'); + nMilliSeconds = 100 * (string[nStart] - cZero); + if (nDigits >= 2) { - nTemp = -1; - const sal_Int32 nDigits = nPos - nStart; - OSL_ENSURE(nDigits > 0, "bad code monkey"); - nHundredthSeconds = 10 * - (string[nStart] - sal_Unicode('0')); - if (nDigits >= 2) + nMilliSeconds += 10 * + (string[nStart+1] - cZero); + if (nDigits >= 3) { - nHundredthSeconds += - (string[nStart+1] - sal_Unicode('0')); + nMilliSeconds += (string[nStart+2] - cZero); } } + + if (sal_Unicode('S') == string[nPos]) + { + ++nPos; + } else { bSuccess = false; } } + else + { + bSuccess = false; + } } } else @@ -1182,14 +1204,14 @@ bool Converter::convertDuration(util::Duration& rDuration, if (bSuccess) { - rDuration.Negative = bIsNegativeDuration; - rDuration.Years = static_cast<sal_Int16>(nYears); - rDuration.Months = static_cast<sal_Int16>(nMonths); - rDuration.Days = static_cast<sal_Int16>(nDays); - rDuration.Hours = static_cast<sal_Int16>(nHours); - rDuration.Minutes = static_cast<sal_Int16>(nMinutes); - rDuration.Seconds = static_cast<sal_Int16>(nSeconds); - rDuration.HundredthSeconds = static_cast<sal_Int16>(nHundredthSeconds); + rDuration.Negative = bIsNegativeDuration; + rDuration.Years = static_cast<sal_Int16>(nYears); + rDuration.Months = static_cast<sal_Int16>(nMonths); + rDuration.Days = static_cast<sal_Int16>(nDays); + rDuration.Hours = static_cast<sal_Int16>(nHours); + rDuration.Minutes = static_cast<sal_Int16>(nMinutes); + rDuration.Seconds = static_cast<sal_Int16>(nSeconds); + rDuration.MilliSeconds = static_cast<sal_Int16>(nMilliSeconds); } return bSuccess; @@ -1202,24 +1224,26 @@ struct Test { return a.Years == b.Years && a.Months == b.Months && a.Days == b.Days && a.Hours == b.Hours && a.Minutes == b.Minutes && a.Seconds == b.Seconds - && a.HundredthSeconds == b.HundredthSeconds + && a.MilliSeconds == b.MilliSeconds && a.Negative == b.Negative; } - static void doTest(util::Duration const & rid, const char * pis) + static void doTest(util::Duration const & rid, char const*const pis, + char const*const i_pos = 0) { - bool bSuccess(false); - ::rtl::OUStringBuffer buf; - Converter::convertDuration(buf, rid); - ::rtl::OUString os(buf.makeStringAndClear()); - OSL_TRACE(::rtl::OUStringToOString(os.getStr(), RTL_TEXTENCODING_UTF8)); - OSL_ASSERT(os.equalsAscii(pis)); + char const*const pos((i_pos) ? i_pos : pis); util::Duration od; - bSuccess = Converter::convertDuration(od, os); - OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dH", + ::rtl::OUString is(::rtl::OUString::createFromAscii(pis)); + bool bSuccess = Converter::convertDuration(od, is); + OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dm", od.Negative, od.Years, od.Months, od.Days, - od.Hours, od.Minutes, od.Seconds, od.HundredthSeconds); + od.Hours, od.Minutes, od.Seconds, od.MilliSeconds); OSL_ASSERT(bSuccess); OSL_ASSERT(eqDuration(rid, od)); + ::rtl::OUStringBuffer buf; + Converter::convertDuration(buf, od); + OSL_TRACE( + ::rtl::OUStringToOString(buf.getStr(), RTL_TEXTENCODING_UTF8)); + OSL_ASSERT(buf.makeStringAndClear().equalsAscii(pos)); } static void doTestF(const char * pis) { @@ -1228,7 +1252,7 @@ struct Test { ::rtl::OUString::createFromAscii(pis)); OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dH", od.Negative, od.Years, od.Months, od.Days, - od.Hours, od.Minutes, od.Seconds, od.HundredthSeconds); + od.Hours, od.Minutes, od.Seconds, od.MilliSeconds); OSL_ASSERT(!bSuccess); } Test() { @@ -1239,24 +1263,27 @@ struct Test { doTest( util::Duration(false, 0, 0, 0, 52, 0, 0, 0), "PT52H" ); doTest( util::Duration(false, 0, 0, 0, 0, 717, 0, 0), "PT717M" ); doTest( util::Duration(false, 0, 0, 0, 0, 0, 121, 0), "PT121S" ); - doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 19), "PT0.19S" ); - doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 9), "PT0.09S" ); + doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 190), "PT0.19S" ); + doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 90), "PT0.09S" ); + doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 9), "PT0.009S" ); + doTest( util::Duration(false, 0, 0, 0, 0, 0, 9, 999), + "PT9.999999999999999999999999999999S", "PT9.999S" ); doTest( util::Duration(true , 0, 0, 9999, 0, 0, 0, 0), "-P9999D" ); - doTest( util::Duration(true , 7, 6, 5, 4, 3, 2, 1), + doTest( util::Duration(true , 7, 6, 5, 4, 3, 2, 10), "-P7Y6M5DT4H3M2.01S" ); doTest( util::Duration(false, 0, 6, 0, 0, 3, 0, 0), "P6MT3M" ); doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 0), "P0D" ); - doTestF("1Y1M"); - doTestF("P-1Y1M"); - doTestF("P1M1Y"); - doTestF("PT1Y"); - doTestF("P1Y1M1M"); - doTestF("P1YT1MT1M"); - doTestF("P1YT"); - doTestF("P99999999999Y"); - doTestF("PT.1S"); - doTestF("PT5M.134S"); - doTestF("PT1.S"); + doTestF("1Y1M"); // invalid: no ^P + doTestF("P-1Y1M"); // invalid: - after P + doTestF("P1M1Y"); // invalid: Y after M + doTestF("PT1Y"); // invalid: Y after T + doTestF("P1Y1M1M"); // invalid: M twice, no T + doTestF("P1YT1MT1M"); // invalid: T twice + doTestF("P1YT"); // invalid: T but no H,M,S + doTestF("P99999999999Y"); // cannot parse so many Ys + doTestF("PT.1S"); // invalid: no 0 preceding . + doTestF("PT5M.134S"); // invalid: no 0 preceding . + doTestF("PT1.S"); // invalid: no digit following . OSL_TRACE("\nSAX CONVERTER TEST END\n"); } }; @@ -1285,6 +1312,15 @@ void Converter::convertDateTime( const sal_Unicode zero('0'); const sal_Unicode tee ('T'); + if (i_rDateTime.Year < 1000) { + i_rBuffer.append(zero); + } + if (i_rDateTime.Year < 100) { + i_rBuffer.append(zero); + } + if (i_rDateTime.Year < 10) { + i_rBuffer.append(zero); + } i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Year) ).append(dash); if( i_rDateTime.Month < 10 ) { i_rBuffer.append(zero); @@ -1352,6 +1388,46 @@ bool Converter::convertDateTime( util::DateTime& rDateTime, } } +static bool +readDateTimeComponent(const ::rtl::OUString & rString, + sal_Int32 & io_rnPos, sal_Int32 & o_rnTarget, + const sal_Int32 nMinLength, const bool bExactLength) +{ + const sal_Int32 nOldPos(io_rnPos); + sal_Int32 nTemp(0); + if (R_SUCCESS != readUnsignedNumber(rString, io_rnPos, nTemp)) + { + return false; + } + const sal_Int32 nTokenLength(io_rnPos - nOldPos); + if ((nTokenLength < nMinLength) || + (bExactLength && (nTokenLength > nMinLength))) + { + return false; // bad length + } + o_rnTarget = nTemp; + return true; +} + +static bool lcl_isLeapYear(const sal_uInt32 nYear) +{ + return ((nYear % 4) == 0) + && !(((nYear % 100) == 0) || ((nYear % 400) == 0)); +} + +static sal_uInt16 +lcl_MaxDaysPerMonth(const sal_Int32 nMonth, const sal_Int32 nYear) +{ + static sal_uInt16 s_MaxDaysPerMonth[12] = + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + OSL_ASSERT(0 < nMonth && nMonth <= 12); + if ((2 == nMonth) && lcl_isLeapYear(nYear)) + { + return 29; + } + return s_MaxDaysPerMonth[nMonth - 1]; +} + /** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */ bool Converter::convertDateOrDateTime( util::Date & rDate, util::DateTime & rDateTime, @@ -1359,97 +1435,233 @@ bool Converter::convertDateOrDateTime( { bool bSuccess = true; - rtl::OUString aDateStr, aTimeStr, sDoubleStr; - sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' ); - sal_Int32 nPos2 = rString.indexOf( (sal_Unicode) ',' ); - if (nPos2 < 0) - nPos2 = rString.indexOf( (sal_Unicode) '.' ); - if ( nPos >= 0 ) + const ::rtl::OUString string = rString.trim().toAsciiUpperCase(); + sal_Int32 nPos(0); + bool bNegative(false); + if ((string.getLength() > nPos) && (sal_Unicode('-') == string[nPos])) { - aDateStr = rString.copy( 0, nPos ); - if ( nPos2 >= 0 ) - { - aTimeStr = rString.copy( nPos + 1, nPos2 - nPos - 1 ); - sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.")); - sDoubleStr += rString.copy( nPos2 + 1 ); - } - else - { - aTimeStr = rString.copy(nPos + 1); - sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0")); - } + ++nPos; + bNegative = true; } - else - aDateStr = rString; // no separator: only date part - sal_Int32 nYear = 1899; - sal_Int32 nMonth = 12; - sal_Int32 nDay = 30; - sal_Int32 nHour = 0; - sal_Int32 nMin = 0; - sal_Int32 nSec = 0; + sal_Int32 nYear(0); + { + bSuccess = readDateTimeComponent(string, nPos, nYear, 4, false); + bSuccess &= (0 < nYear); + bSuccess &= (nPos < string.getLength()); // not last token + } + if (bSuccess && (sal_Unicode('-') != string[nPos])) // separator + { + bSuccess = false; + } + if (bSuccess) + { + ++nPos; + } - const sal_Unicode* pStr = aDateStr.getStr(); - sal_Int32 nDateTokens = 1; - while ( *pStr ) + sal_Int32 nMonth(0); + if (bSuccess) { - if ( *pStr == '-' ) - nDateTokens++; - pStr++; + bSuccess = readDateTimeComponent(string, nPos, nMonth, 2, true); + bSuccess &= (0 < nMonth) && (nMonth <= 12); + bSuccess &= (nPos < string.getLength()); // not last token } - if ( nDateTokens > 3 || aDateStr.getLength() == 0 ) + if (bSuccess && (sal_Unicode('-') != string[nPos])) // separator + { bSuccess = false; - else + } + if (bSuccess) + { + ++nPos; + } + + sal_Int32 nDay(0); + if (bSuccess) + { + bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true); + bSuccess &= (0 < nDay) && (nDay <= lcl_MaxDaysPerMonth(nMonth, nYear)); + } + + bool bHaveTime(false); + if (bSuccess && (nPos < string.getLength())) { - sal_Int32 n = 0; - if ( !convertNumber( nYear, aDateStr.getToken( 0, '-', n ), 0, 9999 ) ) + if (sal_Unicode('T') == string[nPos]) // time separator + { + bHaveTime = true; + ++nPos; + } + } + + sal_Int32 nHours(0); + sal_Int32 nMinutes(0); + sal_Int32 nSeconds(0); + sal_Int32 nMilliSeconds(0); + if (bSuccess && bHaveTime) + { + { + bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true); + bSuccess &= (0 <= nHours) && (nHours <= 24); + bSuccess &= (nPos < string.getLength()); // not last token + } + if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator + { bSuccess = false; - if ( nDateTokens >= 2 ) - if ( !convertNumber( nMonth, aDateStr.getToken( 0, '-', n ), 0, 12 ) ) - bSuccess = false; - if ( nDateTokens >= 3 ) - if ( !convertNumber( nDay, aDateStr.getToken( 0, '-', n ), 0, 31 ) ) + } + if (bSuccess) + { + ++nPos; + } + + if (bSuccess) + { + bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true); + bSuccess &= (0 <= nMinutes) && (nMinutes < 60); + bSuccess &= (nPos < string.getLength()); // not last token + } + if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator + { + bSuccess = false; + } + if (bSuccess) + { + ++nPos; + } + + if (bSuccess) + { + bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true); + bSuccess &= (0 <= nSeconds) && (nSeconds < 60); + } + if (bSuccess && (nPos < string.getLength()) && + (sal_Unicode('.') == string[nPos])) // fraction separator + { + ++nPos; + const sal_Int32 nStart(nPos); + sal_Int32 nTemp(0); + if (R_NOTHING == readUnsignedNumber(string, nPos, nTemp)) + { bSuccess = false; + } + if (bSuccess) + { + // cannot use nTemp because of possible leading zeros + // and possible overflow => read digits directly + const sal_Int32 nDigits(nPos - nStart); + OSL_ENSURE(nDigits > 0, "bad code monkey"); + const sal_Unicode cZero('0'); + nMilliSeconds = 100 * (string[nStart] - cZero); + if (nDigits >= 2) + { + nMilliSeconds += 10 * (string[nStart+1] - cZero); + if (nDigits >= 3) + { + nMilliSeconds += (string[nStart+2] - cZero); + } + } + } + } + + if (bSuccess && (nHours == 24)) + { + if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nMilliSeconds))) + { + bSuccess = false; // only 24:00:00 is valid + } +#if 0 + else + { + nHours = 0; // normalize 24:00:00 to 00:00:00 of next day + lcl_addDay(bNegative, nYear, nMonth, nDay, 1); + } +#endif + } } - if ( aTimeStr.getLength() > 0 ) // time is optional + bool bHaveTimezone(false); + bool bHaveTimezonePlus(false); + bool bHaveTimezoneMinus(false); + if (bSuccess && (nPos < string.getLength())) { - pStr = aTimeStr.getStr(); - sal_Int32 nTimeTokens = 1; - while ( *pStr ) + const sal_Unicode c(string[nPos]); + if (sal_Unicode('+') == c) { - if ( *pStr == ':' ) - nTimeTokens++; - pStr++; + bHaveTimezone = true; + bHaveTimezonePlus = true; + ++nPos; + } + else if (sal_Unicode('-') == c) + { + bHaveTimezone = true; + bHaveTimezoneMinus = true; + ++nPos; + } + else if (sal_Unicode('Z') == c) + { + bHaveTimezone = true; + ++nPos; } - if ( nTimeTokens > 3 ) - bSuccess = false; else { - sal_Int32 n = 0; - if ( !convertNumber( nHour, aTimeStr.getToken( 0, ':', n ), 0, 23 ) ) - bSuccess = false; - if ( nTimeTokens >= 2 ) - if ( !convertNumber( nMin, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) - bSuccess = false; - if ( nTimeTokens >= 3 ) - if ( !convertNumber( nSec, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) - bSuccess = false; + bSuccess = false; + } + } + sal_Int32 nTimezoneHours(0); + sal_Int32 nTimezoneMinutes(0); + if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus)) + { + bSuccess = readDateTimeComponent( + string, nPos, nTimezoneHours, 2, true); + bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14); + bSuccess &= (nPos < string.getLength()); // not last token + if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator + { + bSuccess = false; + } + if (bSuccess) + { + ++nPos; + } + if (bSuccess) + { + bSuccess = readDateTimeComponent( + string, nPos, nTimezoneMinutes, 2, true); + bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60); + } + if (bSuccess && (nTimezoneHours == 14)) + { + if (0 != nTimezoneMinutes) + { + bSuccess = false; // only +-14:00 is valid + } } } + bSuccess &= (nPos == string.getLength()); // trailing junk? + + if (bSuccess && bHaveTimezone) + { + // util::DateTime does not support timezones! +#if 0 + // do not add timezone, just strip it (as suggested by er) + lcl_addTimezone(bNegative, nYear, nMonth, nDay, nHours, nMinutes, + !bHaveTimezoneMinus, nTimezoneHours, nTimezoneMinutes); +#endif + } + if (bSuccess) { - if ( aTimeStr.getLength() > 0 ) // time is optional + if (bHaveTime) // time is optional { + // util::DateTime does not support negative years! rDateTime.Year = static_cast<sal_uInt16>(nYear); rDateTime.Month = static_cast<sal_uInt16>(nMonth); rDateTime.Day = static_cast<sal_uInt16>(nDay); - rDateTime.Hours = static_cast<sal_uInt16>(nHour); - rDateTime.Minutes = static_cast<sal_uInt16>(nMin); - rDateTime.Seconds = static_cast<sal_uInt16>(nSec); + rDateTime.Hours = static_cast<sal_uInt16>(nHours); + rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes); + rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds); + // util::DateTime does not support 3 decimal digits of precision! rDateTime.HundredthSeconds = - static_cast<sal_uInt16>((sDoubleStr).toDouble() * 100); + static_cast<sal_uInt16>(nMilliSeconds / 10); rbDateTime = true; } else @@ -1463,6 +1675,100 @@ bool Converter::convertDateOrDateTime( return bSuccess; } +#if 0 +struct Test { + static bool eqDateTime(util::DateTime a, util::DateTime b) { + return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day + && a.Hours == b.Hours && a.Minutes == b.Minutes + && a.Seconds == b.Seconds + && a.HundredthSeconds == b.HundredthSeconds; + } + static void doTest(util::DateTime const & rdt, char const*const pis, + char const*const i_pos = 0) + { + char const*const pos((i_pos) ? i_pos : pis); + ::rtl::OUString is(::rtl::OUString::createFromAscii(pis)); + util::DateTime odt; + bool bSuccess( Converter::convertDateTime(odt, is) ); + OSL_TRACE("Y:%d M:%d D:%d H:%d M:%d S:%d H:%d", + odt.Year, odt.Month, odt.Day, + odt.Hours, odt.Minutes, odt.Seconds, odt.HundredthSeconds); + OSL_ASSERT(bSuccess); + OSL_ASSERT(eqDateTime(rdt, odt)); + ::rtl::OUStringBuffer buf; + Converter::convertDateTime(buf, odt, true); + OSL_TRACE( + ::rtl::OUStringToOString(buf.getStr(), RTL_TEXTENCODING_UTF8)); + OSL_ASSERT(buf.makeStringAndClear().equalsAscii(pos)); + } + static void doTestF(const char * pis) + { + util::DateTime odt; + bool bSuccess = Converter::convertDateTime(odt, + ::rtl::OUString::createFromAscii(pis)); + OSL_TRACE("Y:%d M:%d D:%d H:%dH M:%d S:%d H:%d", + odt.Year, odt.Month, odt.Day, + odt.Hours, odt.Minutes, odt.Seconds, odt.HundredthSeconds); + OSL_ASSERT(!bSuccess); + } + Test() { + OSL_TRACE("\nSAX CONVERTER TEST BEGIN\n"); + doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1), "0001-01-01T00:00:00" ); + doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1), + "0001-01-01T00:00:00Z", "0001-01-01T00:00:00" ); +// doTest( util::DateTime(0, 0, 0, 0, 1, 1, -1), "-0001-01-01T00:00:00" ); +// doTest( util::DateTime(0, 0, 0, 0, 1, 1, -1), "-0001-01-01T00:00:00Z" ); + doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1), + "0001-01-01T00:00:00-00:00", "0001-01-01T00:00:00" ); + doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1), + "0001-01-01T00:00:00+00:00", "0001-01-01T00:00:00" ); + doTest( util::DateTime(0, 0, 0, 0, 2, 1, 1)/*(0, 0, 12, 0, 2, 1, 1)*/, + "0001-01-02T00:00:00-12:00", "0001-01-02T00:00:00" ); +// "0001-02-01T12:00:00" ); + doTest( util::DateTime(0, 0, 0, 0, 2, 1, 1)/*(0, 0, 12, 0, 1, 1, 1)*/, + "0001-01-02T00:00:00+12:00", "0001-01-02T00:00:00" ); +// "0001-01-01T12:00:00" ); + doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999), + "9999-12-31T23:59:59.99" ); + doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999), + "9999-12-31T23:59:59.99Z", "9999-12-31T23:59:59.99" ); + doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999), + "9999-12-31T23:59:59.9999999999999999999999999999999999999", + "9999-12-31T23:59:59.99" ); + doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999), + "9999-12-31T23:59:59.9999999999999999999999999999999999999Z", + "9999-12-31T23:59:59.99" ); + doTest( util::DateTime(0, 0, 0, 24, 1, 1, 333) + /*(0, 0, 0, 0, 2, 1, 333)*/, + "0333-01-01T24:00:00"/*, "0333-01-02T00:00:00"*/ ); + doTestF( "+0001-01-01T00:00:00" ); // invalid: ^+ + doTestF( "1-01-01T00:00:00" ); // invalid: < 4 Y + doTestF( "0001-1-01T00:00:00" ); // invalid: < 2 M + doTestF( "0001-01-1T00:00:00" ); // invalid: < 2 D + doTestF( "0001-01-01T0:00:00" ); // invalid: < 2 H + doTestF( "0001-01-01T00:0:00" ); // invalid: < 2 M + doTestF( "0001-01-01T00:00:0" ); // invalid: < 2 S + doTestF( "0001-01-01T00:00:00." ); // invalid: .$ + doTestF( "0001-01-01T00:00:00+1:00" ); // invalid: < 2 TZ H + doTestF( "0001-01-01T00:00:00+00:1" ); // invalid: < 2 TZ M + doTestF( "0001-13-01T00:00:00" ); // invalid: M > 12 + doTestF( "0001-01-32T00:00:00" ); // invalid: D > 31 + doTestF( "0001-01-01T25:00:00" ); // invalid: H > 24 + doTestF( "0001-01-01T00:60:00" ); // invalid: H > 59 + doTestF( "0001-01-01T00:00:60" ); // invalid: S > 59 + doTestF( "0001-01-01T24:01:00" ); // invalid: H=24, but M != 0 + doTestF( "0001-01-01T24:00:01" ); // invalid: H=24, but S != 0 + doTestF( "0001-01-01T24:00:00.1" ); // invalid: H=24, but H != 0 + doTestF( "0001-01-02T00:00:00+15:00" ); // invalid: TZ > +14:00 + doTestF( "0001-01-02T00:00:00+14:01" ); // invalid: TZ > +14:00 + doTestF( "0001-01-02T00:00:00-15:00" ); // invalid: TZ < -14:00 + doTestF( "0001-01-02T00:00:00-14:01" ); // invalid: TZ < -14:00 + OSL_TRACE("\nSAX CONVERTER TEST END\n"); + } +}; +static Test test; +#endif + /** gets the position of the first comma after npos in the string rStr. Commas inside '"' pairs are not matched */ sal_Int32 Converter::indexOfComma( const OUString& rStr, |