summaryrefslogtreecommitdiff
path: root/svl/source/numbers
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2021-09-21 19:26:51 +0200
committerEike Rathke <erack@redhat.com>2021-09-21 21:00:45 +0200
commit508f5b7767210318f1a23efc6db928c87a5eca6f (patch)
treec793dbeb52d869a9606c198b0a78a0d4429dd961 /svl/source/numbers
parente430d82ec56f34fb5ae45a50eb12cd03c7e40ba3 (diff)
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
Diffstat (limited to 'svl/source/numbers')
-rw-r--r--svl/source/numbers/zforlist.cxx30
-rw-r--r--svl/source/numbers/zforscan.cxx32
2 files changed, 57 insertions, 5 deletions
diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx
index e623a0239743..dca678d81abd 100644
--- a/svl/source/numbers/zforlist.cxx
+++ b/svl/source/numbers/zforlist.cxx
@@ -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 );
diff --git a/svl/source/numbers/zforscan.cxx b/svl/source/numbers/zforscan.cxx
index f6cdfdb5b339..a5f25637678a 100644
--- a/svl/source/numbers/zforscan.cxx
+++ b/svl/source/numbers/zforscan.cxx
@@ -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;