Add tests of QLocale's toDate() and toTime()

Previously only toDateTime() was tested. Adding a test-case for
toTime() provoked adding full testing for both it and toDate(), based
on toDateTime() tests.

Pick-to: 6.6 6.5
Task-number: QTBUG-114909
Change-Id: I5c24b3869b3deefc36a7125133822e8f41cd24ba
Reviewed-by: Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>
This commit is contained in:
Edward Welbourne 2023-07-06 14:16:35 +02:00
parent e8a68b556c
commit 95a74de486

View File

@ -78,6 +78,10 @@ private slots:
void formatTimeZone();
void toDateTime_data();
void toDateTime();
void toDate_data();
void toDate();
void toTime_data();
void toTime();
void doubleRoundTrip_data();
void doubleRoundTrip();
void integerRoundTrip_data();
@ -2203,6 +2207,293 @@ void tst_QLocale::toDateTime()
QCOMPARE(l.toDateTime(string, QLocale::ShortFormat), result);
}
void tst_QLocale::toDate_data()
{
QTest::addColumn<QLocale>("locale");
QTest::addColumn<QDate>("result");
QTest::addColumn<QString>("format");
QTest::addColumn<QString>("string");
// No non-format letters in format string:
QTest::addColumn<bool>("clean");
const auto C = QLocale::c();
QTest::newRow("C-d/M/yyyy")
<< C << QDate(1974, 12, 1) << u"d/M/yyyy"_s << u"1/12/1974"_s << true;
QTest::newRow("C-d/M/yyyyy")
<< C << QDate(1974, 12, 1) << u"d/M/yyyyy"_s << u"1/12/1974y"_s << false;
QTest::newRow("C-dd/MM/yyy")
<< C << QDate(1974, 1, 1) << u"dd/MM/yyy"_s << u"01/01/74y"_s << false;
QTest::newRow("C-ddddd/MMMMM/yy")
<< C << QDate(1974, 12, 2) << u"ddddd/MMMMM/yy"_s << u"Monday2/December12/74"_s
<< true;
QTest::newRow("C-'dddd'/MMMM/yy")
<< C << QDate(1974, 12, 1) << u"'dddd'/MMMM/yy"_s << u"dddd/December/74"_s << false;
QTest::newRow("C-d'dd'd/MMMM/yyy")
<< C << QDate(1974, 12, 1) << u"d'dd'd/MMMM/yyy"_s << u"1dd1/December/74y"_s << false;
QTest::newRow("C-d'dd'd/MMM'M'/yy")
<< C << QDate(1974, 12, 1) << u"d'dd'd/MMM'M'/yy"_s << u"1dd1/DecM/74"_s << false;
QTest::newRow("C-d'd'dd/M/yy")
<< C << QDate(1974, 12, 1) << u"d'd'dd/M/yy"_s << u"1d01/12/74"_s << false;
// Unpadded value for fixed-width field is wrong:
QTest::newRow("bad-day-C")
<< C << QDate() << u"dd-MMM-yy"_s << u"4-Jun-11"_s << true;
QTest::newRow("bad-month-C")
<< C << QDate() << u"d-MM-yy"_s << u"4-6-11"_s << true;
QTest::newRow("bad-year-C")
<< C << QDate() << u"d-MMM-yyyy"_s << u"4-Jun-11"_s << true;
QTest::newRow("ok-C")
<< C << QDate(1911, 6, 4) << u"d-MMM-yy"_s << u"4-Jun-11"_s << true;
// Locale-specific details frozen to avoid CLDR update breakage.
// However, updating to match CLDR from time to time would be constructive.
const QLocale norsk{QLocale::NorwegianBokmal, QLocale::Norway};
QTest::newRow("no_NO-d/M/yyyy")
<< norsk << QDate(1974, 12, 1) << u"d/M/yyyy"_s << u"1/12/1974"_s << true;
QTest::newRow("no_NO-d/M/yyyyy")
<< norsk << QDate(1974, 12, 1) << u"d/M/yyyyy"_s << u"1/12/1974y"_s << false;
QTest::newRow("no_NO-dd/MM/yyy")
<< norsk << QDate(1974, 1, 1) << u"dd/MM/yyy"_s << u"01/01/74y"_s << false;
QTest::newRow("no_NO-ddddd/MMMMM/yy")
<< norsk << QDate(1974, 12, 2) << u"ddddd/MMMMM/yy"_s << u"mandag2/desember12/74"_s
<< true;
QTest::newRow("no_NO-'dddd'/MMMM/yy")
<< norsk << QDate(1974, 12, 1) << u"'dddd'/MMMM/yy"_s << u"dddd/desember/74"_s
<< false;
QTest::newRow("no_NO-d'dd'd/MMMM/yyy")
<< norsk << QDate(1974, 12, 1) << u"d'dd'd/MMMM/yyy"_s << u"1dd1/desember/74y"_s
<< false;
QTest::newRow("no_NO-d'dd'd/MMM'M'/yy")
<< norsk << QDate(1974, 12, 1) << u"d'dd'd/MMM'M'/yy"_s << u"1dd1/des.M/74"_s
<< false;
QTest::newRow("no_NO-d'd'dd/M/yy")
<< norsk << QDate(1974, 12, 1) << u"d'd'dd/M/yy"_s << u"1d01/12/74"_s << false;
QTest::newRow("RFC-1123")
<< C << QDate(2007, 11, 1) << u"ddd, dd MMM yyyy 'GMT'"_s << u"Thu, 01 Nov 2007 GMT"_s
<< false;
const QLocale usa{QLocale::English, QLocale::UnitedStates};
QTest::newRow("longFormat")
<< usa << QDate(2009, 1, 5) << u"dddd, MMMM d, yyyy"_s
<< u"Monday, January 5, 2009"_s << true;
QTest::newRow("shortFormat") // Use of two-digit year considered harmful.
<< usa << QDate(1909, 1, 5) << u"M/d/yy"_s << u"1/5/09"_s << true;
const QDate date(2017, 02, 25);
QTest::newRow("C:long")
<< C << date << "dddd, d MMMM yyyy" << u"Saturday, 25 February 2017"_s << true;
QTest::newRow("C:short")
<< C << date << u"d MMM yyyy"_s << u"25 Feb 2017"_s << true;
QTest::newRow("C:narrow")
<< C << date << u"d MMM yyyy"_s << u"25 Feb 2017"_s << true;
// Test the same again with unicode and emoji.
QTest::newRow("C:long with emoji")
<< C << date << u8"dddd, d💪MMMM yyyy" << u8"Saturday, 25💪February 2017" << true;
QTest::newRow("C:short with emoji")
<< C << date << u8"d📞MMM📞yyyy" << u8"25📞Feb📞2017" << true;
QTest::newRow("C:narrow with emoji")
<< C << date << u8"🇬🇧d MMM yyyy🇬🇧"
<< u8"🇬🇧25 Feb 2017🇬🇧" << true;
const QLocale fr{QLocale::French};
QTest::newRow("fr:long")
<< fr << date << "dddd d MMMM yyyy" << u"Samedi 25 février 2017"_s << true;
QTest::newRow("fr:short")
<< fr << date << u"dd/MM/yyyy"_s << u"25/02/2017"_s << true;
// In Turkish, the word for Friday ("Cuma") is a prefix for the word for
// Saturday ("Cumartesi")
const QLocale turk(QLocale::Turkish);
QTest::newRow("tr:long-Cumartesi")
<< turk << date << u"d MMMM yyyy dddd"_s << u"25 Şubat 2017 Cumartesi"_s << true;
QTest::newRow("tr:long-Cuma")
<< turk << date.addDays(-1) << "d MMMM yyyy dddd" << u"24 Şubat 2017 Cuma"_s << true;
QTest::newRow("tr:mashed-Cumartesi")
<< turk << date << u"d MMMMyyyydddd"_s << u"25 Şubat2017Cumartesi"_s << true;
QTest::newRow("tr:mashed-Cuma")
<< turk << date.addDays(-1) << "ddddd MMMMyyyy" << u"Cuma24 Şubat2017"_s << true;
QTest::newRow("tr:short")
<< turk << date << u"d.MM.yyyy"_s << u"25.02.2017"_s << true;
const QLocale chakma{QLocale::Chakma};
QTest::newRow("ccp:short")
<< chakma << date << "dd/M/yy"
// "𑄸𑄻/𑄸/𑄷𑄽"
<< QString::fromUcs4(U"\U00011138\U0001113b/\U00011138/\U00011137\U0001113d") << true;
QTest::newRow("ccp:long")
<< chakma << date << "dddd, d MMMM, yyyy"
// "𑄥𑄧𑄚𑄨𑄝𑄢𑄴, 𑄸𑄻 𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨, 𑄸𑄶𑄷𑄽"
<< QString::fromUcs4(U"\U00011125\U00011127\U0001111a\U00011128\U0001111d\U00011122"
U"\U00011134, \U00011138\U0001113b \U0001111c\U0001112c\U0001111b"
U"\U00011134\U0001111d\U00011133\U00011122\U0001112a\U00011120"
U"\U00011122\U00011128, \U00011138\U00011136\U00011137\U0001113d")
<< true;
}
void tst_QLocale::toDate()
{
QFETCH(const QLocale, locale);
QFETCH(const QDate, result);
QFETCH(const QString, format);
QFETCH(const QString, string);
QFETCH(const bool, clean);
QEXPECT_FAIL("ccp:short", "QTBUG-87111: Handling of code points outside BMP is broken", Abort);
QEXPECT_FAIL("ccp:long", "QTBUG-87111: Handling of code points outside BMP is broken", Abort);
QCOMPARE(locale.toDate(string, format), result);
if (clean) {
QCOMPARE(locale.toDate(string.toLower(), format), result);
QCOMPARE(locale.toDate(string.toUpper(), format), result);
}
if (locale.dateFormat(QLocale::LongFormat) == format)
QCOMPARE(locale.toDate(string, QLocale::LongFormat), result);
if (locale.dateFormat(QLocale::ShortFormat) == format)
QCOMPARE(locale.toDate(string, QLocale::ShortFormat), result);
}
void tst_QLocale::toTime_data()
{
QTest::addColumn<QLocale>("locale");
QTest::addColumn<QTime>("result");
QTest::addColumn<QString>("format");
QTest::addColumn<QString>("string");
// No non-format letters in format string:
QTest::addColumn<bool>("clean");
const auto C = QLocale::c();
QTest::newRow("C-hh:h:mm")
<< C << QTime(5, 14) << u"hh:h:mm"_s << u"05:5:14"_s << true;
QTest::newRow("C-h")
<< C << QTime(15, 0) << u"h"_s << u"15"_s << true;
QTest::newRow("C-zzz")
<< C << QTime(0, 0, 0, 1) << u"zzz"_s << u"001"_s << true;
QTest::newRow("C-z/001")
<< C << QTime(0, 0, 0, 1) << u"z"_s << u"001"_s << true;
QTest::newRow("C-z/1")
<< C << QTime(0, 0, 0, 100) << u"z"_s << u"1"_s << true;
QTest::newRow("C-ss")
<< C << QTime(0, 0, 13) << u"ss"_s << u"13"_s << true;
QTest::newRow("C-s")
<< C << QTime(0, 0, 13) << u"s"_s << u"13"_s << true;
QTest::newRow("C-m'm'mm")
<< C << QTime(0, 4) << u"m'm'mm"_s << u"4m04"_s << false;
QTest::newRow("C-hhmmsss")
<< C << QTime(0, 0, 3) << u"hhmmsss"_s << u"0000033"_s << true;
// Unpadded value for fixed-width field is wrong:
QTest::newRow("bad-hour-C")
<< C << QTime() << u"hh:m"_s << u"1:2"_s << true;
QTest::newRow("bad-min-C")
<< C << QTime() << u"h:mm"_s << u"1:2"_s << true;
QTest::newRow("bad-sec-C")
<< C << QTime() << u"d-MMM-yy h:m:ss"_s << u"4-Jun-11 1:2:3"_s << true;
QTest::newRow("bad-milli-C")
<< C << QTime() << u"h:m:s.zzz"_s << u"1:2:3.4"_s << true;
QTest::newRow("ok-C")
<< C << QTime(1, 2, 3, 400) << u"h:m:s.z"_s << u"1:2:3.4"_s << true;
// Locale-specific details frozen to avoid CLDR update breakage.
// However, updating to match CLDR from time to time would be constructive.
const QLocale norsk{QLocale::NorwegianBokmal, QLocale::Norway};
QTest::newRow("nb_NO-hh:h:mm")
<< norsk << QTime(5, 14) << u"hh:h:mm"_s << u"05:5:14"_s << true;
QTest::newRow("nb_NO-h")
<<norsk << QTime(15, 0) << u"h"_s << u"15"_s << true;
QTest::newRow("nb_NO-zzz")
<<norsk << QTime(0, 0) << u"zzz"_s << u"000"_s << true;
QTest::newRow("nb_NO-z")
<<norsk << QTime(0, 0) << u"z"_s << u"0"_s << true;
QTest::newRow("nb_NO-ss")
<<norsk << QTime(0, 0, 13) << u"ss"_s << u"13"_s << true;
QTest::newRow("nb_NO-s")
<<norsk << QTime(0, 0, 13) << u"s"_s << u"13"_s << true;
QTest::newRow("nb_NO-m'm'mm")
<<norsk << QTime(0, 4) << u"m'm'mm"_s << u"4m04"_s << false;
QTest::newRow("nb_NO-hhmmsss")
<<norsk << QTime(0, 0, 3) << u"hhmmsss"_s << u"0000033"_s << true;
QTest::newRow("short-ss") // Single-digit seconds does not match ss format.
<< C << QTime() << u"HH:mm:ss"_s << u"02:26:3"_s << true;
QTest::newRow("RFC-1123")
<< C << QTime(18, 8, 30) << u"hh:mm:ss 'GMT'"_s << u"18:08:30 GMT"_s << false;
const QLocale usa{QLocale::English, QLocale::UnitedStates};
QTest::newRow("longFormat-AM")
<< usa << QTime(4, 43, 32) << u"h:mm:ss AP "_s << u"4:43:32 AM "_s << true;
QTest::newRow("shortFormat-AM")
<< usa << QTime(4, 43) << u"h:mm AP "_s << u"4:43 AM "_s << true;
QTest::newRow("longFormat-PM")
<< usa << QTime(16, 43, 32) << u"h:mm:ss AP "_s << u"4:43:32 PM "_s << true;
QTest::newRow("shortFormat-PM")
<< usa << QTime(16, 43) << u"h:mm AP "_s << u"4:43 PM "_s << true;
// Parsing am/pm indicators case-insensitively:
const QLocale czech{QLocale::Czech, QLocale::Czechia};
QTest::newRow("am-cs_CZ")
<< czech << QTime(8, 15, 44, 400) << u"hh:mm:ss.z aP"_s << u"08:15:44.4 dOp."_s
<< true;
QTest::newRow("pm-cs_CZ")
<< czech << QTime(12, 0) << u"hh:mm aP"_s << u"12:00 OdP."_s << true;
const QTime time(17, 21, 25);
QTest::newRow("C:long")
<< C << time << "HH:mm:ss" << u"17:21:25"_s << true;
QTest::newRow("C:short")
<< C << time << u"HH:mm:ss"_s << u"17:21:25"_s << true;
QTest::newRow("C:narrow")
<< C << time << u"HH:mm:ss"_s << u"17:21:25"_s << true;
// Test the same again with unicode and emoji.
QTest::newRow("C:long with emoji")
<< C << time << u8"HH💪mm💪ss" << u8"17💪21💪25" << true;
QTest::newRow("C:short with emoji")
<< C << time << u8"HH📞mm📞ss" << u8"17📞21📞25" << true;
QTest::newRow("C:narrow with emoji")
<< C << time << u8"🇬🇧HH:mm:ss🇬🇧"
<< u8"🇬🇧17:21:25🇬🇧" << true;
const QLocale fr{QLocale::French};
QTest::newRow("fr:long")
<< fr << time << "HH:mm:ss" << u"17:21:25"_s << true;
QTest::newRow("fr:short")
<< fr << time.addSecs(-25) << u"HH:mm"_s << u"17:21"_s << true;
QTest::newRow("tr:short")
<< QLocale(QLocale::Turkish) << time.addSecs(-25) << u"HH:mm"_s << u"17:21"_s << true;
const QLocale chakma{QLocale::Chakma};
QTest::newRow("ccp:short")
<< chakma << time << "h:mm AP"
// "𑄸𑄻/𑄸/𑄷𑄽 𑄻:𑄸𑄷 PM"
<< QString::fromUcs4(U"\U0001113b:\U00011138\U00011137 PM") << true;
QTest::newRow("ccp:long")
<< chakma << time << "h:mm:ss AP"
// "𑄻:𑄸𑄷:𑄸𑄻 PM"
<< QString::fromUcs4(U"\U0001113b:\U00011138\U00011137:\U00011138\U0001113b PM") << true;
}
void tst_QLocale::toTime()
{
QFETCH(const QLocale, locale);
QFETCH(const QTime, result);
QFETCH(const QString, format);
QFETCH(const QString, string);
QFETCH(const bool, clean);
QEXPECT_FAIL("ccp:short", "QTBUG-87111: Handling of code points outside BMP is broken", Abort);
QEXPECT_FAIL("ccp:long", "QTBUG-87111: Handling of code points outside BMP is broken", Abort);
QCOMPARE(locale.toTime(string, format), result);
if (clean) {
QCOMPARE(locale.toTime(string.toLower(), format), result);
QCOMPARE(locale.toTime(string.toUpper(), format), result);
}
if (locale.timeFormat(QLocale::LongFormat) == format)
QCOMPARE(locale.toTime(string, QLocale::LongFormat), result);
if (locale.timeFormat(QLocale::ShortFormat) == format)
QCOMPARE(locale.toTime(string, QLocale::ShortFormat), result);
}
void tst_QLocale::doubleRoundTrip_data()
{
QTest::addColumn<QString>("localeName");