diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp index 8f08b023bbb..aad8cead880 100644 --- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp +++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp @@ -263,16 +263,20 @@ static inline QDateTime fromTimeStampTz(const char *buffer) QByteArray timeZoneName = qFbTzIdToIanaIdMap()->value(fpTzID); if (!timeZoneName.isEmpty()) - return QDateTime(d, t, QTimeZone(timeZoneName)); + { + const auto utc = QDateTime(d, t, QTimeZone(QTimeZone::UTC)); + return utc.toTimeZone(QTimeZone(timeZoneName)); + } else return {}; } static inline ISC_TIMESTAMP_TZ toTimeStampTz(const QDateTime &dt) { + const auto dtUtc = dt.toUTC(); ISC_TIMESTAMP_TZ ts; - ts.utc_timestamp.timestamp_time = dt.time().msecsSinceStartOfDay() * 10; - ts.utc_timestamp.timestamp_date = s_ibaseBaseDate.daysTo(dt.date()); + ts.utc_timestamp.timestamp_time = dtUtc.time().msecsSinceStartOfDay() * 10; + ts.utc_timestamp.timestamp_date = s_ibaseBaseDate.daysTo(dtUtc.date()); ts.time_zone = qIanaIdToFbTzIdMap()->value(dt.timeZone().id().simplified(), 0); return ts; } diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index ee34995f8ee..653c898cbc7 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -259,6 +259,9 @@ private slots: void ibaseInt128_data() { generic_data("QIBASE"); } void ibaseInt128(); + void QTBUG_128493_data() { generic_data("QIBASE"); } + void QTBUG_128493(); + void psqlJsonOperator_data() { generic_data("QPSQL"); } void psqlJsonOperator(); @@ -4868,6 +4871,56 @@ void tst_QSqlQuery::ibaseDateTimeWithTZ() } } +void tst_QSqlQuery::QTBUG_128493() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + if (tst_Databases::getDatabaseType(db) != QSqlDriver::Interbase) + QSKIP("Implemented only for Interbase"); + + if (tst_Databases::getIbaseEngineVersion(db).majorVersion() < 4) + QSKIP("Time zone support only implemented for firebird engine version 4 and greater"); + + + QSqlQuery q{db}; + +#if QT_CONFIG(timezone) + const auto currentDateTime = QDateTime::currentDateTime().toTimeZone(QTimeZone("Europe/Vienna"_ba)); + //Set session time zone + QVERIFY_SQL(q, exec(u"set time zone 'Europe/Vienna'"_s)); +#else + const auto currentDateTime = QDateTime::currentDateTime(); +#endif // QT_CONFIG(timezone) + + QVERIFY_SQL(q, exec(u"select current_timestamp from rdb$database"_s)); + QVERIFY_SQL(q, isActive()); + QVERIFY_SQL(q, next()); + const auto currentDateTimeDB = q.value(0).toDateTime(); + + QCOMPARE(currentDateTime.date(), currentDateTimeDB.date()); + QCOMPARE(currentDateTime.offsetFromUtc(), currentDateTimeDB.offsetFromUtc()); + QCOMPARE(currentDateTime.isDaylightTime(), currentDateTimeDB.isDaylightTime()); + + QCOMPARE(currentDateTime.time().hour(), currentDateTimeDB.time().hour()); + + const QString tableName(qTableName(u"dateTimeTS"_s, __FILE__, db)); + QVERIFY_SQL(q, exec(u"CREATE TABLE "_s + tableName + u"(dt timestamp with time zone)"_s)); + + QVERIFY_SQL(q, prepare(u"INSERT INTO %1 values(:dt)"_s.arg(tableName))); + q.bindValue(":dt", currentDateTime ); + QVERIFY_SQL(q, exec()); + + QVERIFY_SQL(q, exec(u"SELECT cast(dt AS VARCHAR(50)) FROM "_s + tableName)); + QVERIFY_SQL(q, next()); + + const auto currentDateTimeFromDBString = q.value(0).toString(); + auto currentDateTimeFromDB = QDateTime::fromString(currentDateTimeFromDBString, + u"yyyy-MM-dd hh:mm:ss.zzz0 tttt"_s); + + QCOMPARE(currentDateTimeFromDB, currentDateTime); +} + void tst_QSqlQuery::sqliteVirtualTable() { // Virtual tables can behave differently when it comes to prepared