summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qdatetime.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qdatetime.cpp')
-rw-r--r--src/corelib/tools/qdatetime.cpp138
1 files changed, 98 insertions, 40 deletions
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 021053fc6d..d2064b3e84 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -52,6 +52,7 @@
#include <locale.h>
#endif
+#include <cmath>
#include <time.h>
#ifdef Q_OS_WIN
# include <qt_windows.h>
@@ -767,9 +768,10 @@ QString QDate::toString(Qt::DateFormat f) const
{
if (year() < 0 || year() > 9999)
return QString();
+ QString year(QString::number(y).rightJustified(4, QLatin1Char('0')));
QString month(QString::number(m).rightJustified(2, QLatin1Char('0')));
QString day(QString::number(d).rightJustified(2, QLatin1Char('0')));
- return QString::number(y) + QLatin1Char('-') + month + QLatin1Char('-') + day;
+ return year + QLatin1Char('-') + month + QLatin1Char('-') + day;
}
}
}
@@ -1763,60 +1765,115 @@ int QTime::msecsTo(const QTime &t) const
*/
#ifndef QT_NO_DATESTRING
-/*!
- \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
- Returns the time represented in the \a string as a QTime using the
- \a format given, or an invalid time if this is not possible.
+// These anonymous functions tidy up QDateTime::fromString()
+// and avoid confusion of reponsibility between it and QTime::fromString().
+namespace {
+inline bool isMidnight(int hour, int minute, int second, int msec)
+{
+ return hour == 24 && minute == 0 && second == 0 && msec == 0;
+}
- Note that fromString() uses a "C" locale encoded string to convert
- milliseconds to a float value. If the default locale is not "C",
- this may result in two conversion attempts (if the conversion
- fails for the default locale). This should be considered an
- implementation detail.
-*/
-QTime QTime::fromString(const QString& s, Qt::DateFormat f)
+QTime fromStringImpl(const QString &s, Qt::DateFormat f, bool &isMidnight24)
{
if (s.isEmpty()) {
- QTime t;
- t.mds = NullTime;
- return t;
+ // Return a null time.
+ return QTime();
}
switch (f) {
case Qt::SystemLocaleDate:
case Qt::SystemLocaleShortDate:
case Qt::SystemLocaleLongDate:
- return fromString(s, QLocale::system().timeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
- : QLocale::ShortFormat));
+ {
+ QLocale::FormatType formatType(Qt::SystemLocaleLongDate ? QLocale::LongFormat : QLocale::ShortFormat);
+ return QTime::fromString(s, QLocale::system().timeFormat(formatType));
+ }
case Qt::LocaleDate:
case Qt::DefaultLocaleShortDate:
case Qt::DefaultLocaleLongDate:
- return fromString(s, QLocale().timeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
- : QLocale::ShortFormat));
- default:
- {
- bool ok = true;
- const int hour(s.mid(0, 2).toInt(&ok));
- if (!ok)
- return QTime();
- const int minute(s.mid(3, 2).toInt(&ok));
- if (!ok)
- return QTime();
- if (f == Qt::ISODate && s.size() == 5) {
+ {
+ QLocale::FormatType formatType(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat : QLocale::ShortFormat);
+ return QTime::fromString(s, QLocale().timeFormat(formatType));
+ }
+ case Qt::TextDate:
+ case Qt::ISODate:
+ {
+ bool ok = true;
+ const int hour(s.mid(0, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ const int minute(s.mid(3, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ if (f == Qt::ISODate) {
+ if (s.size() == 5) {
// Do not need to specify seconds if using ISO format.
return QTime(hour, minute, 0, 0);
+ } else if ((s.size() > 6 && s[5] == QLatin1Char(',')) || s[5] == QLatin1Char('.')) {
+ // Possibly specifying fraction of a minute.
+
+ // We only want 5 digits worth of fraction of minute. This follows the existing
+ // behaviour that determines how milliseconds are read; 4 millisecond digits are
+ // read and then rounded to 3. If we read at most 5 digits for fraction of minute,
+ // the maximum amount of millisecond digits it will expand to once converted to
+ // seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
+ // will then be rounded up AND clamped to 999.
+ const QString minuteFractionStr(QLatin1String("0.") + s.mid(6, 5));
+ const float minuteFraction = minuteFractionStr.toFloat(&ok);
+ if (!ok)
+ return QTime();
+ const float secondWithMs = minuteFraction * 60;
+ const float second = std::floor(secondWithMs);
+ const float millisecond = 1000 * (secondWithMs - second);
+ const int millisecondRounded = qMin(qRound(millisecond), 999);
+
+ if (isMidnight(hour, minute, second, millisecondRounded)) {
+ isMidnight24 = true;
+ return QTime(0, 0, 0, 0);
+ }
+
+ return QTime(hour, minute, second, millisecondRounded);
+ }
+ }
+
+ const int second(s.mid(6, 2).toInt(&ok));
+ if (!ok)
+ return QTime();
+ const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
+ const double msec(msec_s.toDouble(&ok));
+ if (!ok)
+ return QTime(hour, minute, second, 0);
+
+ if (f == Qt::ISODate) {
+ if (isMidnight(hour, minute, second, msec)) {
+ isMidnight24 = true;
+ return QTime(0, 0, 0, 0);
}
- const int second(s.mid(6, 2).toInt(&ok));
- if (!ok)
- return QTime();
- const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
- const float msec(msec_s.toFloat(&ok));
- if (!ok)
- return QTime(hour, minute, second, 0);
- return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999));
}
+ return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999));
}
+ }
+}
+}
+
+
+/*!
+ \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
+
+ Returns the time represented in the \a string as a QTime using the
+ \a format given, or an invalid time if this is not possible.
+
+ Note that fromString() uses a "C" locale encoded string to convert
+ milliseconds to a float value. If the default locale is not "C",
+ this may result in two conversion attempts (if the conversion
+ fails for the default locale). This should be considered an
+ implementation detail.
+*/
+QTime QTime::fromString(const QString& s, Qt::DateFormat f)
+{
+ bool unused;
+ return fromStringImpl(s, f, unused);
}
/*!
@@ -3245,11 +3302,12 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
}
}
- QTime time(QTime::fromString(tmp, Qt::ISODate));
- if (!time.isValid() && tmp == QString::fromLatin1("24:00:00")) {
+ bool isMidnight24 = false;
+ // Might be end of day (24:00, including variants), which QTime considers invalid.
+ QTime time(fromStringImpl(tmp, Qt::ISODate, isMidnight24));
+ if (isMidnight24) {
// ISO 8601 (section 4.2.3) says that 24:00 is equivalent to 00:00 the next day.
date = date.addDays(1);
- // Don't need to correct time since QDateTime constructor will do it for us.
}
return QDateTime(date, time, ts);