aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-01-28 16:26:49 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2020-01-30 09:51:44 +0100
commitc5f78add12b7d33926631b6df79599df18f65068 (patch)
tree08a895aa76440a4b267b1f6f500ea11e2722e19d /src/qml/qml/v8/qqmlbuiltinfunctions.cpp
parente080f48f905be597b1a645f1641b2b06553df6a2 (diff)
Reduce Qt Declarative's use of QDateTime's locale-dependent APIs
[ChangeLog][QtQml] Qt.formatDateTime, Qt.formatDate and Qt.formatTime now support formatting according to a locale and an optional locale format type. If locale dependent formatting is desired, this method should be used instead of the locale-related DateFormat enum members. Fixes: QTBUG-81631 Change-Id: I971231644ebbeaccbf54dd8f036adf4d31547301 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/qml/qml/v8/qqmlbuiltinfunctions.cpp')
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp190
1 files changed, 109 insertions, 81 deletions
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index b1046b254b..70134bad35 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -728,70 +728,127 @@ ReturnedValue QtObject::method_tint(const FunctionObject *b, const Value *, cons
return scope.engine->fromVariant(QQml_colorProvider()->tint(v1, v2));
}
+namespace {
+template <typename T>
+QString formatDateTimeObjectUsingDateFormat(T formatThis, Qt::DateFormat format) {
+ switch (format) {
+ case Qt::TextDate:
+ case Qt::ISODate:
+ case Qt::RFC2822Date:
+ case Qt::ISODateWithMs:
+ return formatThis.toString(format);
+ // ### Qt 6: Remove all locale dependent cases
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ case Qt::SystemLocaleDate:
+ // case Qt::LocalDate: covered by SystemLocaleDate
+ return QLocale::system().toString(formatThis);
+ case Qt::LocaleDate:
+ case Qt::DefaultLocaleShortDate:
+ return QLocale().toString(formatThis, QLocale::ShortFormat);
+ case Qt::SystemLocaleShortDate:
+ return QLocale::system().toString(formatThis, QLocale::ShortFormat);
+ case Qt::SystemLocaleLongDate:
+ return QLocale::system().toString(formatThis, QLocale::LongFormat);
+ case Qt::DefaultLocaleLongDate:
+ return QLocale().toString(formatThis, QLocale::LongFormat);
+ }
+ QT_WARNING_POP
+ Q_UNREACHABLE();
+ return QString();
+}
+
+template <typename T>
+ReturnedValue formatDateTimeObject(const T &formatThis, const QV4::Scope &scope, const QString &functionName, int argc, const Value *argv) {
+
+ QString formatted;
+ if (argc >= 2) {
+ QV4::ScopedString s(scope, argv[1]);
+ if (s) {
+ if (argc == 3)
+ scope.engine->throwError(QLatin1String("%1(): Stay argument, third argument can only be used if second argument is a locale").arg(functionName));
+ QString format = s->toQString();
+ formatted = formatThis.toString(format);
+ } else if (argv[1].isNumber()) {
+ if (argc == 3)
+ scope.engine->throwError(QLatin1String("%1(): Stay argument, third argument can only be used if second argument is a locale").arg(functionName));
+ quint32 intFormat = argv[1].asDouble();
+ Qt::DateFormat format = Qt::DateFormat(intFormat);
+ formatted = formatDateTimeObjectUsingDateFormat(formatThis, format);
+ } else {
+ QLocale::FormatType formatOptions = QLocale::ShortFormat;
+ if (argc == 3) {
+ if (argv[2].isNumber())
+ formatOptions = QLocale::FormatType(quint32(argv[2].asDouble()));
+ else
+ scope.engine->throwError(QLatin1String("%1(): Third argument must be a Locale format option").arg(functionName));
+ }
+ auto enginePriv = QQmlEnginePrivate::get(scope.engine->qmlEngine());
+ auto localeMetaTypeId = qMetaTypeId<QLocale>();
+ QVariant locale = enginePriv->v4engine()->toVariant(argv[1], localeMetaTypeId);
+ if (!locale.canConvert(localeMetaTypeId))
+ scope.engine->throwError(QLatin1String("%1(): Bad second argument (must be either string, number or locale)").arg(functionName));
+ formatted = locale.value<QLocale>().toString(formatThis, formatOptions);
+ }
+ } else {
+ formatted = QLocale().toString(formatThis, QLocale::ShortFormat);
+ }
+
+ return Encode(scope.engine->newString(formatted));
+}
+
+}
+
/*!
-\qmlmethod string Qt::formatDate(datetime date, variant format)
+\qmlmethod string Qt::formatDate(datetime date, variant format, variant localeFormatOption)
-Returns a string representation of \a date, optionally formatted according
-to \a format.
+Returns a string representation of \a date, optionally formatted using \a format.
The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
-property, a QDate, or QDateTime value. The \a format parameter may be any of
-the possible format values as described for
+property, a QDate, or QDateTime value. The \a format and \a localeFormatOption
+parameter may be any of the possible format values as described for
\l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}.
If \a format is not specified, \a date is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
+\l {QLocale::FormatType::ShortFormat}{Locale.ShortFormat} using the
+default locale.
\sa Locale
*/
ReturnedValue QtObject::method_formatDate(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
QV4::Scope scope(b);
- if (argc < 1 || argc > 2)
- THROW_GENERIC_ERROR("Qt.formatDate(): Invalid arguments");
+ if (argc < 1)
+ THROW_GENERIC_ERROR("Qt.formatDate(): Missing argument");
+ if (argc > 3)
+ THROW_GENERIC_ERROR("Qt.formatDate(): Stray arguments; formatDate takes at most 3 arguments.");
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
QDate date = scope.engine->toVariant(argv[0], -1).toDateTime().date();
- QString formattedDate;
- if (argc == 2) {
- QV4::ScopedString s(scope, argv[1]);
- if (s) {
- QString format = s->toQString();
- formattedDate = date.toString(format);
- } else if (argv[1].isNumber()) {
- quint32 intFormat = argv[1].asDouble();
- Qt::DateFormat format = Qt::DateFormat(intFormat);
- formattedDate = date.toString(format);
- } else {
- THROW_GENERIC_ERROR("Qt.formatDate(): Invalid date format");
- }
- } else {
- formattedDate = date.toString(enumFormat);
- }
-
- return Encode(scope.engine->newString(formattedDate));
+ return formatDateTimeObject(date, scope, QLatin1String("Qt.formatDate"), argc, argv);
}
/*!
-\qmlmethod string Qt::formatTime(datetime time, variant format)
+\qmlmethod string Qt::formatTime(datetime time, variant format, variant localeFormatOption)
-Returns a string representation of \a time, optionally formatted according to
-\a format.
+Returns a string representation of \a time, optionally formatted using
+\a format, and, if provided, \a localeFormatOption.
The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
-value. The \a format parameter may be any of the possible format values as
-described for \l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}.
+value. The \a format and \a localeFormatOption parameter may be any of the
+possible format values as described for
+\l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}.
If \a format is not specified, \a time is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
+\l {QLocale::FormatType::ShortFormat}{Locale.ShortFormat} using the default locale.
\sa Locale
*/
ReturnedValue QtObject::method_formatTime(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
QV4::Scope scope(b);
- if (argc < 1 || argc > 2)
- THROW_GENERIC_ERROR("Qt.formatTime(): Invalid arguments");
+ if (argc < 1)
+ THROW_GENERIC_ERROR("Qt.formatTime(): Missing argument");
+ if (argc > 3)
+ THROW_GENERIC_ERROR("Qt.formatTime(): Stray arguments; formatTime takes at most 3 arguments.");
QVariant argVariant = scope.engine->toVariant(argv[0], -1);
QTime time;
@@ -799,47 +856,34 @@ ReturnedValue QtObject::method_formatTime(const FunctionObject *b, const Value *
time = argVariant.toDateTime().time();
else // if (argVariant.type() == QVariant::Time), or invalid.
time = argVariant.toTime();
-
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- QString formattedTime;
- if (argc == 2) {
- QV4::ScopedString s(scope, argv[1]);
- if (s) {
- QString format = s->toQString();
- formattedTime = time.toString(format);
- } else if (argv[1].isNumber()) {
- quint32 intFormat = argv[1].asDouble();
- Qt::DateFormat format = Qt::DateFormat(intFormat);
- formattedTime = time.toString(format);
- } else {
- THROW_GENERIC_ERROR("Qt.formatTime(): Invalid time format");
- }
- } else {
- formattedTime = time.toString(enumFormat);
- }
-
- return Encode(scope.engine->newString(formattedTime));
+ return formatDateTimeObject(time, scope, QLatin1String("Qt.formatTime"), argc, argv);
}
/*!
-\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
+\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format, variant localeFormatOption)
-Returns a string representation of \a dateTime, optionally formatted according to
+Returns a string representation of \a dateTime, optionally formatted using
\a format.
The \a dateTime parameter may be a JavaScript \c Date object, a \l{date}{date}
property, a QDate, QTime, or QDateTime value.
If \a format is not provided, \a dateTime is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
-\a format should be either:
+\l {QLocale::FormatType::ShortFormat}{Locale.ShortFormat} using the
+default locale. Otherwise, \a format should be either:
\list
\li One of the Qt::DateFormat enumeration values, such as
- \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
+ \c Qt.RFC2822Date or \c Qt.ISODate.
\li A string that specifies the format of the returned string, as detailed below.
+\li A \c locale object.
\endlist
+If \a format specifies a locale object, \dateTime is formatted
+with \li{QLocale::toString}. In this case, localeFormatType can hold a value
+of type \l {QLocale::FormatType} to further tune the formatting. If none is
+provided, \l {QLocale::FormatType::ShortFormat}{Locale.ShortFormat} is used.
+
If \a format specifies a format string, it should use the following expressions
to specify the date:
@@ -916,29 +960,13 @@ with the \a format values below to produce the following results:
ReturnedValue QtObject::method_formatDateTime(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
QV4::Scope scope(b);
- if (argc < 1 || argc > 2)
- THROW_GENERIC_ERROR("Qt.formatDateTime(): Invalid arguments");
+ if (argc < 1)
+ THROW_GENERIC_ERROR("Qt.formatDateTime(): Missing argument");
+ if (argc > 3)
+ THROW_GENERIC_ERROR("Qt.formatDateTime(): Stray arguments; formatDate takes at most 3 arguments.");
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
QDateTime dt = scope.engine->toVariant(argv[0], -1).toDateTime();
- QString formattedDt;
- if (argc == 2) {
- QV4::ScopedString s(scope, argv[1]);
- if (s) {
- QString format = s->toQString();
- formattedDt = dt.toString(format);
- } else if (argv[1].isNumber()) {
- quint32 intFormat = argv[1].asDouble();
- Qt::DateFormat format = Qt::DateFormat(intFormat);
- formattedDt = dt.toString(format);
- } else {
- THROW_GENERIC_ERROR("Qt.formatDateTime(): Invalid datetime format");
- }
- } else {
- formattedDt = dt.toString(enumFormat);
- }
-
- return Encode(scope.engine->newString(formattedDt));
+ return formatDateTimeObject(dt, scope, QLatin1String("Qt.formatDateTime"), argc, argv);
}
/*!