diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp index 959327551b..c3867f50ec 100644 --- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp @@ -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("locale"); + QTest::addColumn("result"); + QTest::addColumn("format"); + QTest::addColumn("string"); + // No non-format letters in format string: + QTest::addColumn("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("locale"); + QTest::addColumn("result"); + QTest::addColumn("format"); + QTest::addColumn("string"); + // No non-format letters in format string: + QTest::addColumn("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") + <("localeName");