aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp5
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h1
-rw-r--r--src/qml/qml/qqmlbuiltinfunctions.cpp146
-rw-r--r--src/qml/qml/qqmlbuiltinfunctions_p.h16
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp60
5 files changed, 212 insertions, 16 deletions
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 98d930eece..ed64493d9a 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -719,6 +719,11 @@ QString DateObject::dateTimeToString(const QDateTime &dateTime, ExecutionEngine
return ToString(TimeClip(dateTime.toMSecsSinceEpoch()), engine->localTZA);
}
+QDateTime DateObject::stringToDateTime(const QString &string, ExecutionEngine *engine)
+{
+ return ToDateTime(ParseString(string, engine->localTZA), QTimeZone::LocalTime);
+}
+
QDate DateObject::dateTimeToDate(const QDateTime &dateTime)
{
// If the Date object was parse()d from a string with no time part
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 147638744d..ad5b51f063 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -207,6 +207,7 @@ struct DateObject: ReferenceObject {
static QString dateTimeToString(const QDateTime &dateTime, ExecutionEngine *engine);
static QDate dateTimeToDate(const QDateTime &dateTime);
+ static QDateTime stringToDateTime(const QString &string, ExecutionEngine *engine);
};
template<>
diff --git a/src/qml/qml/qqmlbuiltinfunctions.cpp b/src/qml/qml/qqmlbuiltinfunctions.cpp
index 2ae58f2178..3807db7456 100644
--- a/src/qml/qml/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/qqmlbuiltinfunctions.cpp
@@ -757,6 +757,11 @@ QString formatDateTimeObjectUsingDateFormat(T formatThis, Qt::DateFormat format)
}
}
+static QTime dateTimeToTime(const QDateTime &dateTime)
+{
+ return dateTime.toLocalTime().time();
+}
+
/*!
\qmlmethod string Qt::formatDate(datetime date, variant format, variant localeFormatOption)
@@ -773,6 +778,36 @@ default locale.
\sa Locale
*/
+static std::optional<QDate> dateFromString(const QString &string, QV4::ExecutionEngine *engine)
+{
+ {
+ const QDate date = QDate::fromString(string, Qt::ISODate);
+ if (date.isValid())
+ return date;
+ }
+
+ {
+ // For historical reasons, the string argument is parsed as datetime, not as only date
+ const QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
+ if (dateTime.isValid()) {
+ qCWarning(lcRootProperties())
+ << string << "is a date/time string being passed to formatDate()."
+ << "You should only pass date strings to formatDate().";
+ return dateTime.date();
+ }
+ }
+
+ {
+ // Since we can coerce QDate to QString, allow the resulting string format here.
+ const QDateTime dateTime = DateObject::stringToDateTime(string, engine);
+ if (dateTime.isValid())
+ return DateObject::dateTimeToDate(dateTime);
+ }
+
+ engine->throwError(QStringLiteral("Invalid argument passed to formatDate(): %1").arg(string));
+ return std::nullopt;
+}
+
QString QtObject::formatDate(const QDate &date, const QString &format) const
{
return date.toString(format);
@@ -783,12 +818,53 @@ QString QtObject::formatDate(const QDate &date, Qt::DateFormat format) const
return formatDateTimeObjectUsingDateFormat(date, format);
}
+QString QtObject::formatDate(const QDateTime &dateTime, const QString &format) const
+{
+ return DateObject::dateTimeToDate(dateTime).toString(format);
+}
+
+QString QtObject::formatDate(const QString &string, const QString &format) const
+{
+ if (const auto qDate = dateFromString(string, v4Engine()))
+ return formatDate(qDate.value(), format);
+
+ return QString();
+}
+
+QString QtObject::formatDate(const QDateTime &dateTime, Qt::DateFormat format) const
+{
+ return formatDateTimeObjectUsingDateFormat(DateObject::dateTimeToDate(dateTime), format);
+}
+
+QString QtObject::formatDate(const QString &string, Qt::DateFormat format) const
+{
+ if (const auto qDate = dateFromString(string, v4Engine()))
+ return formatDate(qDate.value(), format);
+
+ return QString();
+}
+
#if QT_CONFIG(qml_locale)
QString QtObject::formatDate(const QDate &date, const QLocale &locale,
QLocale::FormatType formatType) const
{
return locale.toString(date, formatType);
}
+
+QString QtObject::formatDate(const QDateTime &dateTime, const QLocale &locale,
+ QLocale::FormatType formatType) const
+{
+ return locale.toString(DateObject::dateTimeToDate(dateTime), formatType);
+}
+
+QString QtObject::formatDate(const QString &string, const QLocale &locale,
+ QLocale::FormatType formatType) const
+{
+ if (const auto qDate = dateFromString(string, v4Engine()))
+ return locale.toString(qDate.value(), formatType);
+
+ return QString();
+}
#endif
/*!
@@ -826,6 +902,13 @@ static std::optional<QTime> timeFromString(const QString &string, QV4::Execution
}
}
+ {
+ // Since we can coerce QTime to QString, allow the resulting string format here.
+ const QDateTime dateTime = DateObject::stringToDateTime(string, engine);
+ if (dateTime.isValid())
+ return dateTimeToTime(dateTime);
+ }
+
engine->throwError(QStringLiteral("Invalid argument passed to formatTime(): %1").arg(string));
return std::nullopt;
}
@@ -835,6 +918,11 @@ QString QtObject::formatTime(const QTime &time, const QString &format) const
return time.toString(format);
}
+QString QtObject::formatTime(const QDateTime &dateTime, const QString &format) const
+{
+ return dateTimeToTime(dateTime).toString(format);
+}
+
QString QtObject::formatTime(const QString &time, const QString &format) const
{
@@ -849,6 +937,11 @@ QString QtObject::formatTime(const QTime &time, Qt::DateFormat format) const
return formatDateTimeObjectUsingDateFormat(time, format);
}
+QString QtObject::formatTime(const QDateTime &dateTime, Qt::DateFormat format) const
+{
+ return formatDateTimeObjectUsingDateFormat(dateTimeToTime(dateTime), format);
+}
+
QString QtObject::formatTime(const QString &time, Qt::DateFormat format) const
{
if (auto qTime = timeFromString(time, v4Engine()))
@@ -864,6 +957,12 @@ QString QtObject::formatTime(const QTime &time, const QLocale &locale,
return locale.toString(time, formatType);
}
+QString QtObject::formatTime(const QDateTime &dateTime, const QLocale &locale,
+ QLocale::FormatType formatType) const
+{
+ return locale.toString(dateTimeToTime(dateTime), formatType);
+}
+
QString QtObject::formatTime(const QString &time, const QLocale &locale,
QLocale::FormatType formatType) const
{
@@ -972,22 +1071,69 @@ with the \a format values below to produce the following results:
\sa Locale
*/
+static std::optional<QDateTime> dateTimeFromString(const QString &string, QV4::ExecutionEngine *engine)
+{
+ {
+ const QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
+ if (dateTime.isValid())
+ return dateTime;
+ }
+
+ {
+ // Since we can coerce QDateTime to QString, allow the resulting string format here.
+ const QDateTime dateTime = DateObject::stringToDateTime(string, engine);
+ if (dateTime.isValid())
+ return dateTime;
+ }
+
+ engine->throwError(QStringLiteral("Invalid argument passed to formatDateTime(): %1").arg(string));
+ return std::nullopt;
+}
+
QString QtObject::formatDateTime(const QDateTime &dateTime, const QString &format) const
{
return dateTime.toString(format);
}
+QString QtObject::formatDateTime(const QString &string, const QString &format) const
+{
+
+ if (const auto qDateTime = dateTimeFromString(string, v4Engine()))
+ return formatDateTime(qDateTime.value(), format);
+
+ return QString();
+}
+
QString QtObject::formatDateTime(const QDateTime &dateTime, Qt::DateFormat format) const
{
return formatDateTimeObjectUsingDateFormat(dateTime, format);
}
+QString QtObject::formatDateTime(const QString &string, Qt::DateFormat format) const
+{
+
+ if (const auto qDateTime = dateTimeFromString(string, v4Engine()))
+ return formatDateTime(qDateTime.value(), format);
+
+ return QString();
+}
+
#if QT_CONFIG(qml_locale)
QString QtObject::formatDateTime(const QDateTime &dateTime, const QLocale &locale,
QLocale::FormatType formatType) const
{
return locale.toString(dateTime, formatType);
}
+
+QString QtObject::formatDateTime(const QString &string, const QLocale &locale,
+ QLocale::FormatType formatType) const
+{
+
+ if (const auto qDateTime = dateTimeFromString(string, v4Engine()))
+ return formatDateTime(qDateTime.value(), locale, formatType);
+
+ return QString();
+}
#endif
/*!
diff --git a/src/qml/qml/qqmlbuiltinfunctions_p.h b/src/qml/qml/qqmlbuiltinfunctions_p.h
index 2739524516..46c4f415e3 100644
--- a/src/qml/qml/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/qqmlbuiltinfunctions_p.h
@@ -86,25 +86,41 @@ public:
Q_INVOKABLE QVariant tint(const QJSValue &baseColor, const QJSValue &tintColor) const;
Q_INVOKABLE QString formatDate(const QDate &date, const QString &format) const;
+ Q_INVOKABLE QString formatDate(const QDateTime &dateTime, const QString &format) const;
+ Q_INVOKABLE QString formatDate(const QString &string, const QString &format) const;
Q_INVOKABLE QString formatDate(const QDate &date, Qt::DateFormat format) const;
+ Q_INVOKABLE QString formatDate(const QDateTime &dateTime, Qt::DateFormat format) const;
+ Q_INVOKABLE QString formatDate(const QString &string, Qt::DateFormat format) const;
Q_INVOKABLE QString formatTime(const QTime &time, const QString &format) const;
+ Q_INVOKABLE QString formatTime(const QDateTime &dateTime, const QString &format) const;
Q_INVOKABLE QString formatTime(const QString &time, const QString &format) const;
Q_INVOKABLE QString formatTime(const QTime &time, Qt::DateFormat format) const;
+ Q_INVOKABLE QString formatTime(const QDateTime &dateTime, Qt::DateFormat format) const;
Q_INVOKABLE QString formatTime(const QString &time, Qt::DateFormat format) const;
Q_INVOKABLE QString formatDateTime(const QDateTime &date, const QString &format) const;
+ Q_INVOKABLE QString formatDateTime(const QString &string, const QString &format) const;
Q_INVOKABLE QString formatDateTime(const QDateTime &date, Qt::DateFormat format) const;
+ Q_INVOKABLE QString formatDateTime(const QString &string, Qt::DateFormat format) const;
#if QT_CONFIG(qml_locale)
Q_INVOKABLE QString formatDate(const QDate &date, const QLocale &locale = QLocale(),
QLocale::FormatType formatType = QLocale::ShortFormat) const;
+ Q_INVOKABLE QString formatDate(const QDateTime &dateTime, const QLocale &locale = QLocale(),
+ QLocale::FormatType formatType = QLocale::ShortFormat) const;
+ Q_INVOKABLE QString formatDate(const QString &string, const QLocale &locale = QLocale(),
+ QLocale::FormatType formatType = QLocale::ShortFormat) const;
Q_INVOKABLE QString formatTime(const QTime &time, const QLocale &locale = QLocale(),
QLocale::FormatType formatType = QLocale::ShortFormat) const;
+ Q_INVOKABLE QString formatTime(const QDateTime &dateTime, const QLocale &locale = QLocale(),
+ QLocale::FormatType formatType = QLocale::ShortFormat) const;
Q_INVOKABLE QString formatTime(const QString &time, const QLocale &locale = QLocale(),
QLocale::FormatType formatType = QLocale::ShortFormat) const;
Q_INVOKABLE QString formatDateTime(const QDateTime &date, const QLocale &locale = QLocale(),
QLocale::FormatType formatType = QLocale::ShortFormat) const;
+ Q_INVOKABLE QString formatDateTime(const QString &string, const QLocale &locale = QLocale(),
+ QLocale::FormatType formatType = QLocale::ShortFormat) const;
Q_INVOKABLE QLocale locale() const;
Q_INVOKABLE QLocale locale(const QString &name) const;
#endif
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 40f7a28d3e..73f8a0c81c 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -909,7 +909,10 @@ void tst_qqmlqt::dateTimeFormattingVariants()
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(warning));
warnings.clear();
- if (method == QStringLiteral("formatTime") && variant.typeId() == QMetaType::QString) {
+
+ if (method == QStringLiteral("formatTime")
+ && variant.typeId() == QMetaType::QString
+ && QByteArrayView(QTest::currentDataTag()).endsWith("ISO")) {
for (int i = 0; i < 4; ++i) {
QTest::ignoreMessage(QtWarningMsg,
"\"2011/05/31 11:16:39.755\" is a "
@@ -925,13 +928,18 @@ void tst_qqmlqt::dateTimeFormattingVariants()
QtWarningMsg,
QRegularExpression("formatting.qml:19: Error: Invalid argument passed to "
"formatTime"));
- } else {
- QTest::ignoreMessage(QtWarningMsg,
- QRegularExpression("Could not convert argument 0 at"));
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression(method + "@"));
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression(
- "TypeError: Passing incompatible arguments to "
- "C.. functions from JavaScript is not allowed."));
+ } else if (method == "formatDate") {
+ // formatDate has special error handling as it parses the strings itself.
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ QRegularExpression("formatting.qml:10: Error: Invalid argument passed to "
+ "formatDate"));
+ } else if (method == "formatDateTime") {
+ // formatDateTime has special error handling as it parses the strings itself.
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ QRegularExpression("formatting.qml:29: Error: Invalid argument passed to "
+ "formatDateTime"));
}
}
@@ -1010,27 +1018,47 @@ void tst_qqmlqt::dateTimeFormattingVariants_data()
<< temporary.time().toString("H:m:s a")
<< temporary.time().toString("hh:mm:ss.zzz"));
- QString string(QLatin1String("2011/05/31 11:16:39.755"));
- temporary = QDateTime::fromString(string, "yyyy/MM/dd HH:mm:ss.zzz");
- QTest::newRow("formatDate, qstring")
- << "formatDate" << QVariant::fromValue(string)
+ const QString isoString(QLatin1String("2011/05/31 11:16:39.755"));
+ temporary = QDateTime::fromString(isoString, "yyyy/MM/dd HH:mm:ss.zzz");
+ const QString jsString = engine.coerceValue<QDateTime, QString>(temporary);
+ QTest::newRow("formatDate, qstring, ISO")
+ << "formatDate" << QVariant::fromValue(isoString)
<< (QStringList()
<< QLocale().toString(temporary.date(), QLocale::ShortFormat)
<< QLocale().toString(temporary.date(), QLocale::LongFormat)
<< temporary.date().toString("ddd MMMM d yy"));
- QTest::newRow("formatDateTime, qstring")
- << "formatDateTime" << QVariant::fromValue(string)
+ QTest::newRow("formatDate, qstring, JS")
+ << "formatDate" << QVariant::fromValue(jsString)
+ << (QStringList()
+ << QLocale().toString(temporary.date(), QLocale::ShortFormat)
+ << QLocale().toString(temporary.date(), QLocale::LongFormat)
+ << temporary.date().toString("ddd MMMM d yy"));
+ QTest::newRow("formatDateTime, qstring, ISO")
+ << "formatDateTime" << QVariant::fromValue(isoString)
+ << (QStringList()
+ << QLocale().toString(temporary, QLocale::ShortFormat)
+ << QLocale().toString(temporary, QLocale::LongFormat)
+ << temporary.toString("M/d/yy H:m:s a"));
+ QTest::newRow("formatDateTime, qstring, JS")
+ << "formatDateTime" << QVariant::fromValue(jsString)
<< (QStringList()
<< QLocale().toString(temporary, QLocale::ShortFormat)
<< QLocale().toString(temporary, QLocale::LongFormat)
<< temporary.toString("M/d/yy H:m:s a"));
- QTest::newRow("formatTime, qstring")
- << "formatTime" << QVariant::fromValue(string)
+ QTest::newRow("formatTime, qstring, ISO")
+ << "formatTime" << QVariant::fromValue(isoString)
<< (QStringList()
<< QLocale().toString(temporary.time(), QLocale::ShortFormat)
<< QLocale().toString(temporary.time(), QLocale::LongFormat)
<< temporary.time().toString("H:m:s a")
<< temporary.time().toString("hh:mm:ss.zzz"));
+ QTest::newRow("formatTime, qstring, JS")
+ << "formatTime" << QVariant::fromValue(jsString)
+ << (QStringList()
+ << QLocale().toString(temporary.time(), QLocale::ShortFormat)
+ << QLocale().toString(temporary.time(), QLocale::LongFormat)
+ << temporary.time().toString("H:m:s a")
+ << temporary.time().toString("hh:mm:ss.000")); // JS Date to string coercion drops milliseconds
QColor color(Qt::red);
temporary = QVariant::fromValue(color).toDateTime();