Kaydet (Commit) 51478cef authored tarafından Eike Rathke's avatar Eike Rathke

Resolves: tdf#107012 follow date order of the target locale

... when converting format codes between locales, so en-US MM/DD/YYYY
correctly ends up as de-DE DD.MM.YYYY instead of MM.DD.YYYY

Change-Id: Iccfdd4787fc05462f47266c77cc9e95d14dae60d
üst e2d3e936
...@@ -1520,6 +1520,17 @@ int ImpSvNumberformatScan::FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i, ...@@ -1520,6 +1520,17 @@ int ImpSvNumberformatScan::FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i,
return 0; return 0;
} }
bool ImpSvNumberformatScan::IsDateFragment( size_t nPos1, size_t nPos2 ) const
{
return nPos2 - nPos1 == 2 && nTypeArray[nPos1+1] == NF_SYMBOLTYPE_DATESEP;
}
void ImpSvNumberformatScan::SwapArrayElements( size_t nPos1, size_t nPos2 )
{
std::swap( nTypeArray[nPos1], nTypeArray[nPos2]);
std::swap( sStrArray[nPos1], sStrArray[nPos2]);
}
sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString ) sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
{ {
const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData(); const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
...@@ -1535,6 +1546,9 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString ) ...@@ -1535,6 +1546,9 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
sal_Unicode cOldKeyH = sKeyword[NF_KEY_H][0]; sal_Unicode cOldKeyH = sKeyword[NF_KEY_H][0];
sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI][0]; sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI][0];
sal_Unicode cOldKeyS = sKeyword[NF_KEY_S][0]; sal_Unicode cOldKeyS = sKeyword[NF_KEY_S][0];
DateOrder eOldDateOrder = pLoc->getDateOrder();
sal_uInt16 nDayPos, nMonthPos, nYearPos;
nDayPos = nMonthPos = nYearPos = SAL_MAX_UINT16;
// If the group separator is a No-Break Space (French) continue with a // If the group separator is a No-Break Space (French) continue with a
// normal space instead so queries on space work correctly. // normal space instead so queries on space work correctly.
...@@ -1546,6 +1560,7 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString ) ...@@ -1546,6 +1560,7 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
{ {
sOldThousandSep = " "; sOldThousandSep = " ";
} }
bool bNewDateOrder = false;
// change locale data et al // change locale data et al
if (bConvertMode) if (bConvertMode)
{ {
...@@ -1554,6 +1569,7 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString ) ...@@ -1554,6 +1569,7 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
pLoc = pFormatter->GetLocaleData(); pLoc = pFormatter->GetLocaleData();
//! init new keywords //! init new keywords
InitKeywords(); InitKeywords();
bNewDateOrder = (eOldDateOrder != pLoc->getDateOrder());
} }
const CharClass* pChrCls = pFormatter->GetCharClass(); const CharClass* pChrCls = pFormatter->GetCharClass();
...@@ -2318,6 +2334,37 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString ) ...@@ -2318,6 +2334,37 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
case NF_KEY_RR : // RR case NF_KEY_RR : // RR
sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
nPos = nPos + sStrArray[i].getLength(); nPos = nPos + sStrArray[i].getLength();
if (bNewDateOrder)
{
// For simple numeric date formats record date order and
// later rearrange.
switch (nTypeArray[i])
{
case NF_KEY_M:
case NF_KEY_MM:
if (nMonthPos == SAL_MAX_UINT16)
nMonthPos = i;
else
bNewDateOrder = false;
break;
case NF_KEY_D:
case NF_KEY_DD:
if (nDayPos == SAL_MAX_UINT16)
nDayPos = i;
else
bNewDateOrder = false;
break;
case NF_KEY_YY:
case NF_KEY_YYYY:
if (nYearPos == SAL_MAX_UINT16)
nYearPos = i;
else
bNewDateOrder = false;
break;
default:
; // nothing
}
}
i++; i++;
break; break;
default: // Other keywords default: // Other keywords
...@@ -2613,6 +2660,37 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString ) ...@@ -2613,6 +2660,37 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
bTimePart = false; bTimePart = false;
sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
nPos = nPos + sStrArray[i].getLength(); nPos = nPos + sStrArray[i].getLength();
if (bNewDateOrder)
{
// For simple numeric date formats record date order and
// later rearrange.
switch (nTypeArray[i])
{
case NF_KEY_M:
case NF_KEY_MM:
if (nMonthPos == SAL_MAX_UINT16)
nMonthPos = i;
else
bNewDateOrder = false;
break;
case NF_KEY_D:
case NF_KEY_DD:
if (nDayPos == SAL_MAX_UINT16)
nDayPos = i;
else
bNewDateOrder = false;
break;
case NF_KEY_YY:
case NF_KEY_YYYY:
if (nYearPos == SAL_MAX_UINT16)
nYearPos = i;
else
bNewDateOrder = false;
break;
default:
; // nothing
}
}
i++; i++;
break; break;
case NF_KEY_THAI_T : case NF_KEY_THAI_T :
...@@ -2652,6 +2730,110 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString ) ...@@ -2652,6 +2730,110 @@ sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
} }
if ( bConvertMode ) if ( bConvertMode )
{ {
if (bNewDateOrder && sOldDateSep == "-")
{
// Keep ISO formats Y-M-D, Y-M and M-D
if (IsDateFragment( nYearPos, nMonthPos))
{
nTypeArray[nYearPos+1] = NF_SYMBOLTYPE_STRING;
sStrArray[nYearPos+1] = sOldDateSep;
bNewDateOrder = false;
}
if (IsDateFragment( nMonthPos, nDayPos))
{
nTypeArray[nMonthPos+1] = NF_SYMBOLTYPE_STRING;
sStrArray[nMonthPos+1] = sOldDateSep;
bNewDateOrder = false;
}
}
if (bNewDateOrder)
{
// Rearrange date order to the target locale if the original order
// includes date separators and is adjacent.
/* TODO: for incomplete dates trailing separators need to be
* handled according to the locale's usage, e.g. en-US M/D should
* be converted to de-DE D.M. and vice versa. As is, it's
* M/D -> D.M and D.M. -> M/D/ where specifically the latter looks
* odd. Check accepted date patterns and append/remove? */
switch (eOldDateOrder)
{
case DateOrder::DMY:
switch (pLoc->getDateOrder())
{
case DateOrder::MDY:
if (IsDateFragment( nDayPos, nMonthPos))
SwapArrayElements( nDayPos, nMonthPos);
break;
case DateOrder::YMD:
if (nYearPos != SAL_MAX_UINT16)
{
if (IsDateFragment( nDayPos, nMonthPos) && IsDateFragment( nMonthPos, nYearPos))
SwapArrayElements( nDayPos, nYearPos);
}
else
{
if (IsDateFragment( nDayPos, nMonthPos))
SwapArrayElements( nDayPos, nMonthPos);
}
break;
default:
; // nothing
}
break;
case DateOrder::MDY:
switch (pLoc->getDateOrder())
{
case DateOrder::DMY:
if (IsDateFragment( nMonthPos, nDayPos))
SwapArrayElements( nMonthPos, nDayPos);
break;
case DateOrder::YMD:
if (nYearPos != SAL_MAX_UINT16)
{
if (IsDateFragment( nMonthPos, nDayPos) && IsDateFragment( nDayPos, nYearPos))
{
SwapArrayElements( nYearPos, nMonthPos); // YDM
SwapArrayElements( nYearPos, nDayPos); // YMD
}
}
break;
default:
; // nothing
}
break;
case DateOrder::YMD:
switch (pLoc->getDateOrder())
{
case DateOrder::DMY:
if (nYearPos != SAL_MAX_UINT16)
{
if (IsDateFragment( nYearPos, nMonthPos) && IsDateFragment( nMonthPos, nDayPos))
SwapArrayElements( nYearPos, nDayPos);
}
else
{
if (IsDateFragment( nMonthPos, nDayPos))
SwapArrayElements( nMonthPos, nDayPos);
}
break;
case DateOrder::MDY:
if (nYearPos != SAL_MAX_UINT16)
{
if (IsDateFragment( nYearPos, nMonthPos) && IsDateFragment( nMonthPos, nDayPos))
{
SwapArrayElements( nYearPos, nDayPos); // DMY
SwapArrayElements( nYearPos, nMonthPos); // MDY
}
}
break;
default:
; // nothing
}
break;
default:
; // nothing
}
}
// strings containing keywords of the target locale must be quoted, so // strings containing keywords of the target locale must be quoted, so
// the user sees the difference and is able to edit the format string // the user sees the difference and is able to edit the format string
for ( i=0; i < nAnzStrings; i++ ) for ( i=0; i < nAnzStrings; i++ )
......
...@@ -241,6 +241,15 @@ private: // Private section ...@@ -241,6 +241,15 @@ private: // Private section
reused instead of shifting all one up and nPos is decremented! */ reused instead of shifting all one up and nPos is decremented! */
bool InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr ); bool InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr );
/** Whether two key symbols are adjacent separated by date separator.
This can only be used at the end of FinalScan() after
NF_SYMBOLTYPE_DATESEP has already been set.
*/
bool IsDateFragment( size_t nPos1, size_t nPos2 ) const;
/** Swap nTypeArray and sStrArray elements at positions. */
void SwapArrayElements( size_t nPos1, size_t nPos2 );
static bool StringEqualsChar( const OUString& rStr, sal_Unicode ch ) static bool StringEqualsChar( const OUString& rStr, sal_Unicode ch )
{ return rStr.getLength() == 1 && rStr[0] == ch; } { return rStr.getLength() == 1 && rStr[0] == ch; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment