summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2012-01-10 16:42:01 +0100
committerEike Rathke <erack@redhat.com>2012-01-11 13:18:45 +0100
commit8298a4741d95034f65c648dddfae081f44cf9455 (patch)
tree64edd4bc021b92f2f1ae81c9b93a06e6bd4b4d4d
parent958cdbdcf5e35c04e259a69e972684060f1b3d12 (diff)
strict date recognition using locale's separator and ISO 8601
- Removed separators '-', '.' and '/' working in all combinations in all locales forcing a date even for 23/12.99 (if locale has DMY order) * Only the locale's date separator is accepted, plus '-' if the input may represent an ISO 8601 date yyyy-mm-dd, check is lax though on minimum digits, y-m-d is also accepted. * Additionally, accept yy-month-dd or dd-month-yy with month name. Year must be <1 or >31, 2-digit year magic for values 0,32..99 is applied, or has to be prefixed with leading zero.
-rw-r--r--svl/source/numbers/zforfind.cxx69
-rw-r--r--svl/source/numbers/zforfind.hxx19
2 files changed, 71 insertions, 17 deletions
diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx
index 3df9232c3b56..3cf61e17dc2e 100644
--- a/svl/source/numbers/zforfind.cxx
+++ b/svl/source/numbers/zforfind.cxx
@@ -145,6 +145,7 @@ void ImpSvNumberInputScan::Reset()
nMatchedAllStrings = nMatchedVirgin;
nMayBeIso8601 = 0;
nTimezonePos = 0;
+ nMayBeMonthDate = 0;
}
@@ -995,6 +996,44 @@ bool ImpSvNumberInputScan::MayBeIso8601()
}
//---------------------------------------------------------------------------
+
+bool ImpSvNumberInputScan::MayBeMonthDate()
+{
+ if (nMayBeMonthDate == 0)
+ {
+ nMayBeMonthDate = 1;
+ if (nAnzNums >= 2 && nNums[1] < nAnzStrings)
+ {
+ // "-Jan-"
+ const String& rM = sStrArray[nNums[0]+1];
+ if (rM.Len() >= 3 && rM.GetChar(0) == '-' && rM.GetChar( rM.Len()-1) == '-')
+ {
+ // Check year length assuming at least 3 digits (including
+ // leading zero). Two digit years 1..31 are out of luck here
+ // and may be taken as day of month.
+ bool bYear1 = (sStrArray[nNums[0]].Len() >= 3);
+ bool bYear2 = (sStrArray[nNums[1]].Len() >= 3);
+ sal_Int32 n;
+ bool bDay1 = (!bYear1 && (n = sStrArray[nNums[0]].ToInt32()) >= 1 && n <= 31);
+ bool bDay2 = (!bYear2 && (n = sStrArray[nNums[1]].ToInt32()) >= 1 && n <= 31);
+ if (bDay1 && !bDay2)
+ nMayBeMonthDate = 2; // dd-month-yy
+ else if (!bDay1 && bDay2)
+ nMayBeMonthDate = 3; // yy-month-dd
+ else if (bDay1 && bDay2)
+ {
+ if (bYear1 && !bYear2)
+ nMayBeMonthDate = 3; // yy-month-dd
+ else if (!bYear1 && bYear2)
+ nMayBeMonthDate = 2; // dd-month-yy
+ }
+ }
+ }
+ }
+ return nMayBeMonthDate > 1;
+}
+
+//---------------------------------------------------------------------------
// GetDateRef
bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
@@ -1283,10 +1322,11 @@ input for the following reasons:
}
break;
case 2: // month in the middle (10 Jan 94)
+ {
pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
- switch (DateFmt)
+ DateFormat eDF = (MayBeMonthDate() ? (nMayBeMonthDate == 2 ? DMY : YMD) : DateFmt);
+ switch (eDF)
{
- case MDY: // yes, "10-Jan-94" is valid
case DMY:
pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
@@ -1299,7 +1339,8 @@ input for the following reasons:
res = false;
break;
}
- break;
+ }
+ break;
default: // else, e.g. month at the end (94 10 Jan)
res = false;
break;
@@ -1687,13 +1728,10 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
const String& rDate = pFormatter->GetDateSep();
- const String& rTime = pLoc->getTimeSep();
- sal_Unicode cTime = rTime.GetChar(0);
SkipBlanks(rString, nPos);
- if ( SkipString(rDate, rString, nPos) // 10., 10-, 10/
- || ((cTime != '.') && SkipChar('.', rString, nPos)) // TRICKY:
- || ((cTime != '/') && SkipChar('/', rString, nPos)) // short boolean
- || ((cTime != '-') && SkipChar('-', rString, nPos)) ) // evaluation!
+ if (SkipString( rDate, rString, nPos) // 10. 10- 10/
+ || ((MayBeIso8601() || MayBeMonthDate())
+ && SkipChar( '-', rString, nPos)))
{
if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type
&& eScannedType != NUMBERFORMAT_DATE) // except date
@@ -1752,6 +1790,7 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
SkipBlanks(rString, nPos);
}
+ const String& rTime = pLoc->getTimeSep();
if ( SkipString(rTime, rString, nPos) ) // time separator?
{
if (nDecPos) // already . => maybe error
@@ -1945,7 +1984,6 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
}
const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
- const String& rDate = pFormatter->GetDateSep();
const String& rTime = pLoc->getTimeSep();
if ( SkipString(rTime, rString, nPos) ) // 10:
{
@@ -1968,11 +2006,10 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
nTimePos = nAnzStrings;
}
- sal_Unicode cTime = rTime.GetChar(0);
- if ( SkipString(rDate, rString, nPos) // 10., 10-, 10/
- || ((cTime != '.') && SkipChar('.', rString, nPos)) // TRICKY:
- || ((cTime != '/') && SkipChar('/', rString, nPos)) // short boolean
- || ((cTime != '-') && SkipChar('-', rString, nPos)) ) // evaluation!
+ const String& rDate = pFormatter->GetDateSep();
+ if (SkipString( rDate, rString, nPos) // 10. 10- 10/
+ || ((MayBeIso8601() || MayBeMonthDate())
+ && SkipChar( '-', rString, nPos)))
{
if (eScannedType != NUMBERFORMAT_UNDEFINED &&
eScannedType != NUMBERFORMAT_DATE) // already another type
@@ -2535,8 +2572,6 @@ void ImpSvNumberInputScan::ChangeIntl()
{
sal_Unicode cDecSep = pFormatter->GetNumDecimalSep().GetChar(0);
bDecSepInDateSeps = ( cDecSep == '-' ||
- cDecSep == '/' ||
- cDecSep == '.' ||
cDecSep == pFormatter->GetDateSep().GetChar(0) );
bTextInitialized = false;
aUpperCurrSymbol.Erase();
diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx
index 02e08d4b31a3..5d6cb85e00c5 100644
--- a/svl/source/numbers/zforfind.hxx
+++ b/svl/source/numbers/zforfind.hxx
@@ -78,6 +78,11 @@ public:
*/
bool MayBeIso8601();
+ /** Whether input may be a dd-month-yy format, with month name, not
+ number.
+ */
+ bool MayBeMonthDate();
+
private:
SvNumberFormatter* pFormatter;
String* pUpperMonthText; // Array of month names, uppercase
@@ -136,14 +141,28 @@ private:
sal_uInt16 nTimezonePos; // Index of timezone separator (+1)
/** State of ISO 8601 detection.
+
0:= don't know yet
1:= no
2:= yes, <=2 digits in year
3:= yes, 3 digits in year
4:= yes, >=4 digits in year
+
+ @see MayBeIso8601()
*/
sal_uInt8 nMayBeIso8601;
+ /** State of dd-month-yy or yy-month-dd detection, with month name.
+
+ 0:= don't know yet
+ 1:= no
+ 2:= yes, dd-month-yy
+ 3:= yes, yy-month-dd
+
+ @see MayBeMonthDate()
+ */
+ sal_uInt8 nMayBeMonthDate;
+
#ifdef _ZFORFIND_CXX // methods private to implementation
void Reset(); // Reset all variables before start of analysis