diff --git a/dist/changes-5.4.0 b/dist/changes-5.4.0
index f9899044844be71a4efc4ddef3fa0218be14c978..fc3e3a546614a4c924dc06b142dd3605cbfff509 100644
--- a/dist/changes-5.4.0
+++ b/dist/changes-5.4.0
@@ -97,6 +97,11 @@ QtCore
 
  - Logging:
    * QT_MESSAGE_PATTERN can include a backtrace using %{backtrace}
+   * QT_MESSAGE_PATTERN can include a timestamp using %{time}. By
+     default, this shows the time in ISO format (YYYY-MM-DDTHH:mm:ss),
+     but a different format string can be specified in the tag (e.g.,
+     %{time YYYYMMDDHHmmsszzz}). If the format is "process", Qt will
+     display the elapsed time since the process started.
    * Added QtMsgType argument to QLoggingCategory constructor and
      Q_LOGGING_CATEGORY macro that controls the default category
      configuration.
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 39c5ac602eeaa02218cb4e1dd921c5960cbbf30f..843ec6b0ca7c84ceeede8bc6acece2c5365accd5 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1201,11 +1201,14 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
             }
 #endif
         } else if (token == timeTokenC) {
-            quint64 ms = pattern->timer.elapsed();
-            if (pattern->timeFormat.isEmpty())
+            if (pattern->timeFormat == QLatin1String("process")) {
+                quint64 ms = pattern->timer.elapsed();
                 message.append(QString().sprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000)));
-            else
-                message.append(pattern->startTime.addMSecs(ms).toString(pattern->timeFormat));
+            } else if (pattern->timeFormat.isEmpty()) {
+                message.append(QDateTime::currentDateTime().toString(Qt::ISODate));
+            } else {
+                message.append(QDateTime::currentDateTime().toString(pattern->timeFormat));
+            }
 #endif
         } else if (token == ifCategoryTokenC) {
             if (!context.category || (strcmp(context.category, "default") == 0))
@@ -1550,9 +1553,10 @@ void qErrnoWarning(int code, const char *msg, ...)
     \row \li \c %{pid} \li QCoreApplication::applicationPid()
     \row \li \c %{threadid} \li ID of current thread
     \row \li \c %{type} \li "debug", "warning", "critical" or "fatal"
-    \row \li \c %{time} \li time of the message, in seconds since the process started
-    \row \li \c %{time format} \li system time when the message occurred, formatted by
-        passing the \c format to \l QDateTime::toString()
+    \row \li \c %{time process} \li time of the message, in seconds since the process started (the token "process" is literal)
+    \row \li \c %{time [format]} \li system time when the message occurred, formatted by
+        passing the \c format to \l QDateTime::toString(). If the format is
+        not specified, the format of Qt::ISODate is used.
     \row \li \c{%{backtrace [depth=N] [separator="..."]}} \li A backtrace with the number of frames
         specified by the optional \c depth parameter (defaults to 5), and separated by the optional
         \c separator parameter (defaults to "|").
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
index 0a55da5b7e8f69e8a5044c8ec7c76b82b6ebb54a..749c7da78996777996bb029b9b0f305e08dcafb6 100644
--- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
+++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
@@ -765,7 +765,7 @@ void tst_qmessagehandler::qMessagePattern_data()
 
     // %{time}  should have a padding of 6 so if it takes less than 10 seconds to show
     // the first message, there should be 5 spaces
-    QTest::newRow("time") << "<%{time}>%{message}" << true << (QList<QByteArray>()
+    QTest::newRow("time-process") << "<%{time process}>%{message}" << true << (QList<QByteArray>()
             << "<     ");
 
 #ifdef __GLIBC__