Use start of day when wrapping 24:00 to the next day

Previously we used 0:0 on the next day, which might fall in a
fall-back's gap.

[ChangeLog][QtCore][QDateTime] When fromString() reads 24:00 in ISO
format, it now uses the start of the next day, rather than 0:0 on the
next day. This only makes a difference if the next day's first hour is
skipped by a time-zone transition.

Change-Id: Ib81feca5dc09fa735321b6ab76d5d118d6db6fd2
Reviewed-by: Andreas Buhr <andreas.buhr@qt.io>
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Edward Welbourne 2020-09-30 12:51:18 +02:00
parent e1e61daf39
commit 6404084b9c
3 changed files with 24 additions and 18 deletions

View File

@ -704,22 +704,23 @@
\note For \c ISODate formats, each \c y, \c M and \c d represents a single
digit of the year, month, and day used to specify the date. Each \c H, \c m,
and \c s represents a single digit of the hour (up to 24), minute and second
used to specify the time. A \c{.zzz} stands for a fractional part suffix on
the preceding field, which may be separated from that field either by a
comma \c{','} or the dot \c{'.'} shown. Precision beyond milliseconds is
accepted but discarded, rounding to the nearest millisecond or, when
rounding fractional seconds up would change the second field, rounded
down. The presence of a literal \c T character is used to separate the date
and time when both are specified. For the \c TextDate and \c RFC2822Date
formats, \c{ddd} stands for the first three letters of the name of the day
of the week and \c{MMM} stands for the first three letters of the month
name. The names of days and months are always in English (C locale)
regardless of user preferences or system settings. The other format
characters have the same meaning as for the ISODate format. Parts of the
format enclosed in square brackets \c{[...]} are optional; the square
brackets do not form part of the format. The plus-or-minus character \c{'±'}
here stands for either sign character, \c{'-'} for minus or \c{'+'} for
plus.
used to specify the time. An hour of 24, with zero for all other time
fields, is understood as the start of the next day. A \c{.zzz} stands for a
fractional part suffix on the preceding field, which may be separated from
that field either by a comma \c{','} or the dot \c{'.'} shown. Precision
beyond milliseconds is accepted but discarded, rounding to the nearest
millisecond or, when rounding fractional seconds up would change the second
field, rounded down. The presence of a literal \c T character is used to
separate the date and time when both are specified. For the \c TextDate and
\c RFC2822Date formats, \c{ddd} stands for the first three letters of the
name of the day of the week and \c{MMM} stands for the first three letters
of the month name. The names of days and months are always in English (C
locale) regardless of user preferences or system settings. The other format
characters have the same meaning as for the ISODate format, except that 24
is not accepted as an hour. Parts of a format enclosed in square brackets
\c{[...]} are optional; the square brackets do not form part of the
format. The plus-or-minus character \c{'±'} here stands for either sign
character, \c{'-'} for minus or \c{'+'} for plus.
\sa QDate::toString(), QTime::toString(), QDateTime::toString(),
QDate::fromString(), QTime::fromString(), QDateTime::fromString()

View File

@ -4773,8 +4773,8 @@ QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
QTime time = fromIsoTimeString(isoString, format, &isMidnight24);
if (!time.isValid())
return QDateTime();
if (isMidnight24)
date = date.addDays(1);
if (isMidnight24) // time is 0:0, but we want the start of next day:
return date.addDays(1).startOfDay(spec, offset);
return QDateTime(date, time, spec, offset);
}
case Qt::TextDate: {

View File

@ -2297,6 +2297,11 @@ void tst_QDateTime::fromStringDateFormat_data()
// 24:00:00 Should be next day according to ISO 8601 section 4.2.3.
QTest::newRow("ISO 24:00") << QString::fromLatin1("2012-06-04T24:00:00")
<< Qt::ISODate << QDateTime(QDate(2012, 6, 5), QTime(0, 0), Qt::LocalTime);
QTest::newRow("ISO 24:00 in DST") // Only special if TZ=America/Sao_Paulo
<< QString::fromLatin1("2008-10-18T24:00") << Qt::ISODate
<< QDateTime(QDate(2008, 10, 19),
QTime(QTimeZone::systemTimeZoneId() == "America/Sao_Paulo" ? 1 : 0, 0),
Qt::LocalTime);
QTest::newRow("ISO 24:00 end of month") << QString::fromLatin1("2012-06-30T24:00:00")
<< Qt::ISODate << QDateTime(QDate(2012, 7, 1), QTime(0, 0), Qt::LocalTime);
QTest::newRow("ISO 24:00 end of year") << QString::fromLatin1("2012-12-31T24:00:00")