Add ISO 8601 date+time with milliseconds format
NF_DATETIME_ISO_YYYYMMDDTHHMMSS000 YYYY-MM-DD"T"HH:MM:SS,000 using either ',' or '.' separator, '.' if Time100SecSep is '.' ',' else A prerequisite for tdf#88359 to not lose data when importing such, especially without "Detect special numbers" on. Change-Id: I02ab682636e6ddbcc4537183a3625ea61662f016 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122400 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Jenkins
This commit is contained in:
parent
e430d82ec5
commit
508f5b7767
5 changed files with 63 additions and 8 deletions
|
@ -247,11 +247,12 @@ enum NfIndexTableOffset
|
|||
|
||||
NF_DATETIME_ISO_YYYYMMDD_HHMMSS, // 1997-10-08 01:23:45 ISO (with blank instead of T)
|
||||
NF_DATETIME_ISO_YYYYMMDDTHHMMSS, // 1997-10-08T01:23:45 ISO
|
||||
NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, // 1997-10-08T01:23:45,678 ISO with milliseconds
|
||||
|
||||
// XXX When adding values here, follow the comment above about
|
||||
// svx/source/items/numfmtsh.cxx
|
||||
|
||||
NF_INDEX_TABLE_ENTRIES // == 60, reserved to not be used in i18npool locale data.
|
||||
NF_INDEX_TABLE_ENTRIES // == 61, reserved to not be used in i18npool locale data.
|
||||
|
||||
// XXX Adding values above may increment the reserved area that can't be
|
||||
// used by i18npool's locale data FormatCode definitions, see the
|
||||
|
|
|
@ -233,6 +233,7 @@ void Test::testNumberFormat()
|
|||
const char* pDateTimeExt2[] = {
|
||||
"YYYY-MM-DD HH:MM:SS",
|
||||
"YYYY-MM-DD\"T\"HH:MM:SS",
|
||||
"YYYY-MM-DD\"T\"HH:MM:SS.000",
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
@ -264,7 +265,7 @@ void Test::testNumberFormat()
|
|||
{ NF_TEXT, NF_TEXT, 1, pText },
|
||||
{ NF_DATETIME_SYS_DDMMYYYY_HHMM, NF_DATETIME_SYS_DDMMYYYY_HHMM, 1, pDateTimeExt1 },
|
||||
{ NF_FRACTION_3D, NF_FRACTION_100, 7, pFractionExt },
|
||||
{ NF_DATETIME_ISO_YYYYMMDD_HHMMSS, NF_DATETIME_ISO_YYYYMMDDTHHMMSS, 2, pDateTimeExt2 }
|
||||
{ NF_DATETIME_ISO_YYYYMMDD_HHMMSS, NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, 3, pDateTimeExt2 }
|
||||
};
|
||||
|
||||
SvNumberFormatter aFormatter(m_xContext, eLang);
|
||||
|
|
|
@ -169,7 +169,8 @@ sal_uInt32 const indexTable[NF_INDEX_TABLE_ENTRIES] = {
|
|||
ZF_STANDARD_FRACTION + 7, // NF_FRACTION_10
|
||||
ZF_STANDARD_FRACTION + 8, // NF_FRACTION_100
|
||||
ZF_STANDARD_DATETIME + 2, // NF_DATETIME_ISO_YYYYMMDD_HHMMSS
|
||||
ZF_STANDARD_DATETIME + 3 // NF_DATETIME_ISO_YYYYMMDDTHHMMSS
|
||||
ZF_STANDARD_DATETIME + 3, // NF_DATETIME_ISO_YYYYMMDDTHHMMSS
|
||||
ZF_STANDARD_DATETIME + 5 // NF_DATETIME_ISO_YYYYMMDDTHHMMSS000
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1273,11 +1274,18 @@ bool SvNumberFormatter::IsNumberFormat(const OUString& sString,
|
|||
// Preserve ISO 8601 input.
|
||||
if (pStringScanner->HasIso8601Tsep())
|
||||
{
|
||||
F_Index = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDDTHHMMSS, ActLnge );
|
||||
if (pStringScanner->GetDecPos())
|
||||
F_Index = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, ActLnge );
|
||||
else
|
||||
F_Index = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDDTHHMMSS, ActLnge );
|
||||
}
|
||||
else if (pStringScanner->CanForceToIso8601( DateOrder::Invalid))
|
||||
{
|
||||
F_Index = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDD_HHMMSS, ActLnge );
|
||||
/* TODO: add a millisecond format with space instead of 'T'? */
|
||||
if (pStringScanner->GetDecPos())
|
||||
F_Index = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, ActLnge );
|
||||
else
|
||||
F_Index = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDD_HHMMSS, ActLnge );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1639,6 +1647,8 @@ sal_uInt32 SvNumberFormatter::GetEditFormat( double fNumber, sal_uInt32 nFIndex,
|
|||
case SvNumFormatType::DATETIME :
|
||||
if (nFIndex == GetFormatIndex( NF_DATETIME_ISO_YYYYMMDDTHHMMSS, eLang))
|
||||
nKey = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDDTHHMMSS, eLang );
|
||||
else if (nFIndex == GetFormatIndex( NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, eLang))
|
||||
nKey = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, eLang );
|
||||
else if (nFIndex == GetFormatIndex( NF_DATETIME_ISO_YYYYMMDD_HHMMSS, eLang) || (pFormat && pFormat->IsIso8601( 0 )))
|
||||
nKey = GetFormatIndex( NF_DATETIME_ISO_YYYYMMDD_HHMMSS, eLang );
|
||||
else
|
||||
|
@ -2893,6 +2903,20 @@ void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset, bool bNoAdditio
|
|||
assert(pFormat);
|
||||
pFormat->SetComment("ISO 8601"); // not to be localized
|
||||
|
||||
// YYYY-MM-DD"T"HH:MM:SS,000 ISO with milliseconds and ',' or '.' decimal separator
|
||||
aSingleFormatCode.Code =
|
||||
rKeyword[NF_KEY_YYYY] + "-" +
|
||||
rKeyword[NF_KEY_MM] + "-" +
|
||||
rKeyword[NF_KEY_DD] + "\"T\"" +
|
||||
rKeyword[NF_KEY_HH] + ":" +
|
||||
rKeyword[NF_KEY_MMI] + ":" +
|
||||
rKeyword[NF_KEY_SS] + (GetLocaleData()->getTime100SecSep() == "." ? "." : ",") +
|
||||
"000";
|
||||
pFormat = ImpInsertFormat( aSingleFormatCode,
|
||||
CLOffset + ZF_STANDARD_DATETIME+5 /* NF_DATETIME_ISO_YYYYMMDDTHHMMSS000 */ );
|
||||
assert(pFormat);
|
||||
pFormat->SetComment("ISO 8601"); // not to be localized
|
||||
|
||||
|
||||
// Scientific number
|
||||
aFormatSeq = xNFC->getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER, aLocale );
|
||||
|
|
|
@ -1432,9 +1432,37 @@ sal_Int32 ImpSvNumberformatScan::ScanType()
|
|||
eNewType = SvNumFormatType::TEXT;
|
||||
break;
|
||||
default:
|
||||
if (pLoc->getTime100SecSep() == sStrArray[i])
|
||||
// Separator for SS,0
|
||||
if ((eScannedType & SvNumFormatType::TIME)
|
||||
&& 0 < i && (nTypeArray[i-1] == NF_KEY_S || nTypeArray[i-1] == NF_KEY_SS))
|
||||
{
|
||||
bDecSep = true; // for SS,0
|
||||
// For ISO 8601 only YYYY-MM-DD"T"HH:MM:SS,0 accept both
|
||||
// ',' and '.' regardless of locale's separator, and only
|
||||
// those.
|
||||
// XXX NOTE: this catches only known separators of
|
||||
// NF_SYMBOLTYPE_DEL as all NF_SYMBOLTYPE_STRING are
|
||||
// skipped during the loop. Meant to error out if the
|
||||
// Time100SecSep or decimal separator differ and were used.
|
||||
if ((eScannedType & SvNumFormatType::DATE)
|
||||
&& 11 <= i && i < nStringsCnt-1
|
||||
&& (nTypeArray[i-6] == NF_SYMBOLTYPE_STRING
|
||||
&& (sStrArray[i-6] == "\"T\"" || sStrArray[i-6] == "\\T"
|
||||
|| sStrArray[i-6] == "T"))
|
||||
&& (nTypeArray[i-11] == NF_KEY_YYYY)
|
||||
&& (nTypeArray[i-9] == NF_KEY_M || nTypeArray[i-9] == NF_KEY_MM)
|
||||
&& (nTypeArray[i-7] == NF_KEY_D || nTypeArray[i-7] == NF_KEY_DD)
|
||||
&& (nTypeArray[i-5] == NF_KEY_H || nTypeArray[i-5] == NF_KEY_HH)
|
||||
&& (nTypeArray[i-3] == NF_KEY_MI || nTypeArray[i-3] == NF_KEY_MMI)
|
||||
&& (nTypeArray[i+1] == NF_SYMBOLTYPE_DEL && sStrArray[i+1][0] == '0'))
|
||||
|
||||
{
|
||||
if (sStrArray[i].getLength() == 1 && (sStrArray[i][0] == ',' || sStrArray[i][0] == '.'))
|
||||
bDecSep = true;
|
||||
else
|
||||
return nPos; // Error
|
||||
}
|
||||
else if (pLoc->getTime100SecSep() == sStrArray[i])
|
||||
bDecSep = true;
|
||||
}
|
||||
eNewType = SvNumFormatType::UNDEFINED;
|
||||
break;
|
||||
|
|
|
@ -660,7 +660,7 @@ short SvxNumberFormatShell::FillEListWithDateTime_Impl(std::vector<OUString>& rL
|
|||
|
||||
// Always add the internally generated ISO formats.
|
||||
nSelPos = FillEListWithFormats_Impl(rList, nSelPos, NF_DATETIME_ISO_YYYYMMDD_HHMMSS,
|
||||
NF_DATETIME_ISO_YYYYMMDDTHHMMSS, false);
|
||||
NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, false);
|
||||
|
||||
return nSelPos;
|
||||
}
|
||||
|
@ -720,6 +720,7 @@ bool SvxNumberFormatShell::IsEssentialFormat_Impl(SvNumFormatType eType, sal_uIn
|
|||
case NF_DATETIME_SYS_DDMMYYYY_HHMMSS:
|
||||
case NF_DATETIME_ISO_YYYYMMDD_HHMMSS:
|
||||
case NF_DATETIME_ISO_YYYYMMDDTHHMMSS:
|
||||
case NF_DATETIME_ISO_YYYYMMDDTHHMMSS000:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue