Make 'zz' format an alias for 'z' in time format strings

Also document the (seldom helpful) handling of over-long repeats of a
format. Add test to QDateTime and amend QLocale test.

[ChangeLog][QtCore][QDateTime] Doubling the 'z' format in a date-time
or time format string now produces the same output as a single 'z'.
Previously, this would have produced two copies of the milliseconds
field (eliding any trailing zeros in each). Contrast with 'zzz', which
produces the full milliseconds field, including any trailing zeros.

Change-Id: I4c60462b062fee4079370096d745c191c1939506
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Edward Welbourne 2022-07-15 15:59:40 +02:00
parent effd6f63f1
commit 0a36a7c1db
4 changed files with 54 additions and 10 deletions

View File

@ -3484,13 +3484,13 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
case 'z':
used = true;
repeat = (repeat >= 3) ? 3 : 1;
repeat = qMin(repeat, 3);
// note: the millisecond component is treated like the decimal part of the seconds
// so ms == 2 is always printed as "002", but ms == 200 can be either "2" or "200"
result.append(locale.d->m_data->longLongToString(time.msec(), -1, 10, 3,
QLocaleData::ZeroPadded));
if (repeat == 1) {
if (repeat != 3) {
if (result.endsWith(locale.zeroDigit()))
result.chop(1);
if (result.endsWith(locale.zeroDigit()))

View File

@ -1147,6 +1147,13 @@ QString QDate::toString(Qt::DateFormat format) const
\note Day and month names are given in English (C locale). To get localized
month and day names, use QLocale::system().toString().
\note If a format character is repeated more times than the longest
expression in the table above using it, this part of the format will be read
as several expressions with no separator between them; the longest above,
possibly repeated as many times as there are copies of it, ending with a
residue that may be a shorter expression. Thus \c{'MMMMMMMMMM'} for a date
in May will contribute \c{"MayMay05"} to the output.
\sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
*/
@ -1611,6 +1618,14 @@ QDate QDate::fromString(QStringView string, Qt::DateFormat format)
\snippet code/src_corelib_time_qdatetime.cpp 3
\note If a format character is repeated more times than the longest
expression in the table above using it, this part of the format will be read
as several expressions with no separator between them; the longest above,
possibly repeated as many times as there are copies of it, ending with a
residue that may be a shorter expression. Thus \c{'MMMMMMMMMM'} would match
\c{"MayMay05"} and set the month to May. Likewise, \c{'MMMMMM'} would match
\c{"May08"} and find it inconsistent, leading to an invalid date.
\sa toString(), QDateTime::fromString(), QTime::fromString(),
QLocale::toDate()
*/
@ -1912,12 +1927,14 @@ QString QTime::toString(Qt::DateFormat format) const
\row \li mm \li The minute with a leading zero (00 to 59)
\row \li s \li The whole second, without any leading zero (0 to 59)
\row \li ss \li The whole second, with a leading zero where applicable (00 to 59)
\row \li z \li The fractional part of the second, to go after a decimal
point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
reports the seconds to full available (millisecond) precision
without trailing zeroes.
\row \li zzz \li The fractional part of the second, to millisecond
precision, including trailing zeroes where applicable (000 to 999).
\row \li z or zz
\li The fractional part of the second, to go after a decimal point,
without trailing zeroes. Thus "\c{s.z}" reports the seconds to
full available (millisecond) precision without trailing zeroes (0
to 999).
\row \li zzz
\li The fractional part of the second, to millisecond precision,
including trailing zeroes where applicable (000 to 999).
\row \li AP or A
\li Use AM/PM display. \c A/AP will be replaced by 'AM' or 'PM'. In
localized forms (only relevant to \l{QLocale::toString()}), the
@ -1960,8 +1977,16 @@ QString QTime::toString(Qt::DateFormat format) const
\note To get localized forms of AM or PM (the AP, ap, A, a, aP or Ap
formats), use QLocale::system().toString().
\note If a format character is repeated more times than the longest
expression in the table above using it, this part of the format will be read
as several expressions with no separator between them; the longest above,
possibly repeated as many times as there are copies of it, ending with a
residue that may be a shorter expression. Thus \c{'HHHHH'} for the time
08:00 will contribute \c{"08088"} to the output.
\sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
*/
// ### Qt 7 The 't' format specifiers should be specific to QDateTime (compare fromString).
QString QTime::toString(QStringView format) const
{
return QLocale::c().toString(*this, format);
@ -2342,6 +2367,15 @@ QTime QTime::fromString(QStringView string, Qt::DateFormat format)
\note If localized forms of am or pm (the AP, ap, Ap, aP, A or a formats)
are to be recognized, use QLocale::system().toTime().
\note If a format character is repeated more times than the longest
expression in the table above using it, this part of the format will be read
as several expressions with no separator between them; the longest above,
possibly repeated as many times as there are copies of it, ending with a
residue that may be a shorter expression. Thus \c{'HHHHH'} would match
\c{"08088"} or \c{"080808"} and set the hour to 8; if the time string
contained "070809" it would "match" but produce an inconsistent result,
leading to an invalid time.
\sa toString(), QDateTime::fromString(), QDate::fromString(),
QLocale::toTime(), QLocale::toDateTime()
*/
@ -5061,6 +5095,15 @@ QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
English (C locale). If localized month and day names or localized forms of
AM/PM are to be recognized, use QLocale::system().toDateTime().
\note If a format character is repeated more times than the longest
expression in the table above using it, this part of the format will be read
as several expressions with no separator between them; the longest above,
possibly repeated as many times as there are copies of it, ending with a
residue that may be a shorter expression. Thus \c{'tttttt'} would match
\c{"Europe/BerlinEurope/Berlin"} and set the zone to Berlin time; if the
date-time string contained "Europe/BerlinZ" it would "match" but produce an
inconsistent result, leading to an invalid date-time.
\sa toString(), QDate::fromString(), QTime::fromString(),
QLocale::toDateTime()
*/

View File

@ -1664,7 +1664,7 @@ void tst_QLocale::formatTime_data()
QTest::newRow("C-quote-dquote-H") << QTime(1, 2, 3) << "C" << "'\"H\"'" << "\"H\"";
QTest::newRow("C-H:m:s.z") << QTime(1, 2, 3, 456) << "C" << "H:m:s.z" << "1:2:3.456";
QTest::newRow("C-H:m:s.zz") << QTime(1, 2, 3, 456) << "C" << "H:m:s.zz" << "1:2:3.456456";
QTest::newRow("C-H:m:s.zz") << QTime(1, 2, 3, 456) << "C" << "H:m:s.zz" << "1:2:3.456";
QTest::newRow("C-H:m:s.zzz") << QTime(1, 2, 3, 456) << "C" << "H:m:s.zzz" << "1:2:3.456";
QTest::newRow("C-H:m:s.z=400") << QTime(1, 2, 3, 400) << "C" << "H:m:s.z" << "1:2:3.4";
QTest::newRow("C-H:m:s.zzz=400") << QTime(1, 2, 3, 400) << "C" << "H:m:s.zzz" << "1:2:3.400";

View File

@ -1098,10 +1098,11 @@ void tst_QDateTime::toString_strformat()
{
// Most tests are in QLocale, just test that the api works.
QDate testDate(2013, 1, 1);
QTime testTime(1, 2, 3);
QTime testTime(1, 2, 3, 456);
QDateTime testDateTime(testDate, testTime, Qt::UTC);
QCOMPARE(testDate.toString("yyyy-MM-dd"), QString("2013-01-01"));
QCOMPARE(testTime.toString("hh:mm:ss"), QString("01:02:03"));
QCOMPARE(testTime.toString("hh:mm:ss.zz"), QString("01:02:03.456"));
QCOMPARE(testDateTime.toString("yyyy-MM-dd hh:mm:ss t"), QString("2013-01-01 01:02:03 UTC"));
// TODO QTBUG-95966: find better ways to use repeated 't'
QCOMPARE(testDateTime.toString("yyyy-MM-dd hh:mm:ss tt"), QString("2013-01-01 01:02:03 UTCUTC"));