/*
 * Copyright (C) 2014-2026 CZ.NIC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#include <QDate>
#include <QDateTime>
#include <QString>
#include <QObject>
#include <QtTest/QtTest>

#include "src/datovka_shared/io/db_time.h"
#include "tests/test_db_time.h"

class TestDbTime : public QObject {
	Q_OBJECT

public:
	TestDbTime(void);

private slots:
	void dateToDb(void);

	void dateFromDb(void);

	void dateDbFormatConversion(void);

	void dateTimeToDb(void);

	void dateTimeFromDb(void);

	void dateTimeDbFormatConversion(void);

	void DateTimeToAndFromDB(void);

	void DateTimeFromAndToDB(void);

private:
	const QTimeZone utcTimeZone;
	const QTimeZone cetTimeZone;
	const QTimeZone localTimeZone; /* May shift because of daylight-saving time. */
};

TestDbTime::TestDbTime(void)
    : QObject(Q_NULLPTR),
    utcTimeZone(0),
    cetTimeZone(3600),
    localTimeZone(QDateTime::currentDateTime().offsetFromUtc())
{
}

void TestDbTime::dateToDb(void)
{
	/* Null date. */
	QCOMPARE(qDateToDbFormat(QDate()), QString());

	QCOMPARE(qDateToDbFormat(QDate(2025, 12, 18)), QString("2025-12-18"));

	QCOMPARE(qDateToDbFormat(QDate(2025, 9, 18)), QString("2025-09-18"));

	QCOMPARE(qDateToDbFormat(QDate(2025, 12, 9)), QString("2025-12-09"));

	QCOMPARE(qDateToDbFormat(QDate(2025, 9, 9)), QString("2025-09-09"));

	QCOMPARE(qDateToDbFormat(QDate(9, 12, 18)), QString("0009-12-18"));

	QCOMPARE(qDateToDbFormat(QDate(9, 9, 18)), QString("0009-09-18"));

	QCOMPARE(qDateToDbFormat(QDate(9, 12, 9)), QString("0009-12-09"));

	QCOMPARE(qDateToDbFormat(QDate(9, 9, 9)), QString("0009-09-09"));
}

void TestDbTime::dateFromDb(void)
{
	/* Null string. */
	QCOMPARE(dateFromDbFormat(QString()), QDate());

	/* Incomplete input. */
	QVERIFY(dateFromDbFormat(QString("-12-18")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString("12-18")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString("2025--18")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString("2025-12-")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString("2025-12")).isValid() == false);

	/* Garbage input. */
	//dateFromDbFormat(QString("-2025-12-18")) /* Qt 5.15 is invalid, Qt 6.8 is QDate(-2025, 12, 18) */
	QVERIFY(dateFromDbFormat(QString("2025-12-18-")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString("-2025-12-18-")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString(" 2025-12-18")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString("2025-12-18 ")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString(" 2025-12-18 ")).isValid() == false);
	QVERIFY(dateFromDbFormat(QString("a2398dfnsd 43 -043-fp -043")).isValid() == false);

	QCOMPARE(dateFromDbFormat(QString("2025-12-18")), QDate(2025, 12, 18));

	QCOMPARE(dateFromDbFormat(QString("2025-09-18")), QDate(2025, 9, 18));
	//dateFromDbFormat(QString("2025-9-18")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateFromDbFormat(QString("2025-12-09")), QDate(2025, 12, 9));
	//dateFromDbFormat(QString("2025-12-9")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateFromDbFormat(QString("2025-09-09")), QDate(2025, 9, 9));
	//dateFromDbFormat(QString("2025-9-9")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateFromDbFormat(QString("0009-12-18")), QDate(9, 12, 18));
	//dateFromDbFormat(QString("9-12-18")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateFromDbFormat(QString("0009-09-18")), QDate(9, 9, 18));
	//dateFromDbFormat(QString("9-9-18")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateFromDbFormat(QString("0009-12-09")), QDate(9, 12, 9));
	//dateFromDbFormat(QString("9-12-9")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateFromDbFormat(QString("0009-09-09")), QDate(9, 9, 9));
	//dateFromDbFormat(QString("9-9-9")) /* Qt 5.9 is valid, Qt 5.15 is invalid */
}

void TestDbTime::dateDbFormatConversion(void)
{
	const QString testDateFormat("yyyy MM dd");

	QCOMPARE(dateStrFromDbFormat(QString(), testDateFormat), QString());

	/* Incomplete input. */
	QCOMPARE(dateStrFromDbFormat(QString("-12-18"), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString("12-18"), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString("2025--18"), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString("2025-12-"), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString("2025-12"), testDateFormat), QString());

	/* Garbage input. */
	//dateStrFromDbFormat(QString("-2025-12-18"), testDateFormat) /* Qt 5.15 is null, Qt 6.8 is "-2025 12 18" */
	QCOMPARE(dateStrFromDbFormat(QString("2025-12-18-"), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString("-2025-12-18-"), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString(" 2025-12-18"), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString("2025-12-18 "), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString(" 2025-12-18 "), testDateFormat), QString());
	QCOMPARE(dateStrFromDbFormat(QString("a2398dfnsd 43 -043-fp -043"), testDateFormat), QString());

	QCOMPARE(dateStrFromDbFormat(QString("2025-12-18"), testDateFormat), QString("2025 12 18"));

	QCOMPARE(dateStrFromDbFormat(QString("2025-09-18"), testDateFormat), QString("2025 09 18"));
	//dateStrFromDbFormat(QString("2025-9-18"), testDateFormat) /* Qt 5.9 is "2025 09 18", Qt 5.15 is null */

	QCOMPARE(dateStrFromDbFormat(QString("2025-12-09"), testDateFormat), QString("2025 12 09"));
	//dateStrFromDbFormat(QString("2025-12-9"), testDateFormat) /* Qt 5.9 is "2025 12 09", Qt 5.15 is null */

	QCOMPARE(dateStrFromDbFormat(QString("2025-09-09"), testDateFormat), QString("2025 09 09"));
	//dateStrFromDbFormat(QString("2025-9-9"), testDateFormat) /* Qt 5.9 is "2025 09 09", Qt 5.15 is null */

	QCOMPARE(dateStrFromDbFormat(QString("0009-12-18"), testDateFormat), QString("0009 12 18"));
	//dateStrFromDbFormat(QString("9-12-18"), testDateFormat) /* Qt 5.9 is "0009 12 18", Qt 5.15 is null */

	QCOMPARE(dateStrFromDbFormat(QString("0009-09-18"), testDateFormat), QString("0009 09 18"));
	//dateStrFromDbFormat(QString("9-9-18"), testDateFormat) /* Qt 5.9 is "0009 09 18", Qt 5.15 is null */

	QCOMPARE(dateStrFromDbFormat(QString("0009-12-09"), testDateFormat), QString("0009 12 09"));
	//dateStrFromDbFormat(QString("9-12-9"), testDateFormat) /* Qt 5.9 is "0009 12 09", Qt 5.15 is null */

	QCOMPARE(dateStrFromDbFormat(QString("0009-09-09"), testDateFormat), QString("0009 09 09"));
	//dateStrFromDbFormat(QString("9-9-9"), testDateFormat) /* Qt 5.9 is "0009 09 09", Qt 5.15 is null */
}

void TestDbTime::dateTimeToDb(void)
{
	/* Null dateTime. */
	QCOMPARE(qDateTimeToDbFormat(QDateTime()), QString());

	QCOMPARE(qDateTimeToDbFormat(QDateTime(QDate(2025, 12, 18), QTime(16, 49, 26, 642), cetTimeZone)), QString("2025-12-18 15:49:26.642+00:00"));

#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
	QCOMPARE(qDateTimeToDbFormat(QDateTime(QDate(9, 12, 18), QTime(16, 49, 26, 642), cetTimeZone)), QString("0009-12-18 15:49:26.642+00:00")); /* Qt 5.5 is "0009-12-18 16:49:26.642+00:00" */
#else /* < Qt-5.6 */
#  warning "Skipping a test line."
#endif /* >= Qt-5.6 */

	QCOMPARE(qDateTimeToDbFormat(QDateTime(QDate(2025, 9, 18), QTime(16, 49, 26, 642), cetTimeZone)), QString("2025-09-18 15:49:26.642+00:00"));

	QCOMPARE(qDateTimeToDbFormat(QDateTime(QDate(2025, 12, 9), QTime(16, 49, 26, 642), cetTimeZone)), QString("2025-12-09 15:49:26.642+00:00"));

	QCOMPARE(qDateTimeToDbFormat(QDateTime(QDate(2025, 12, 18), QTime(9, 49, 26, 642), cetTimeZone)), QString("2025-12-18 08:49:26.642+00:00"));

	QCOMPARE(qDateTimeToDbFormat(QDateTime(QDate(2025, 12, 18), QTime(16, 9, 26, 642), cetTimeZone)), QString("2025-12-18 15:09:26.642+00:00"));

	QCOMPARE(qDateTimeToDbFormat(QDateTime(QDate(2025, 12, 18), QTime(16, 49, 9, 642), cetTimeZone)), QString("2025-12-18 15:49:09.642+00:00"));

	QCOMPARE(qDateTimeToDbFormat(QDateTime(QDate(2025, 12, 18), QTime(16, 49, 26, 9), cetTimeZone)), QString("2025-12-18 15:49:26.009+00:00"));
}

void TestDbTime::dateTimeFromDb(void)
{
	/* Null string. */
	QCOMPARE(dateTimeFromDbFormat(QString()), QDateTime());

	/* Incomplete input. */
	QVERIFY(dateTimeFromDbFormat(QString("-12-18 15:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("12-18 15:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025--18 15:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12- 15:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12 15:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-1815:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 :49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15::26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:.642+00:00")).isValid() == false);
	//dateTimeFromDbFormat(QString("2025-12-18 15:49:26.+00:00")) /* Qt 5.15 is valid, Qt 6.8 is invalid */
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.64200:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642+:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642+00:")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642+00")).isValid() == true); /* Actually works. */
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642+")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642")).isValid() == true); /* Must work. */

	/* Garbage input. */
	//dateTimeFromDbFormat(QString("-2025-12-18 15:49:26.642+00:00")) /* Qt 5.15 is invalid, Qt 6.8 is valid */
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642+00:00-")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("-2025-12-18 15:49:26.642+00:00-")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString(" 2025-12-18 15:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642+00:00 ")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString(" 2025-12-18 15:49:26.642+00:00 ")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18-15:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-1815:49:26.642+00:00")).isValid() == false);
	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18T15:49:26.642+00:00")).isValid() == false);

	QCOMPARE(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642+00:00")), QDateTime(QDate(2025, 12, 18), QTime(15, 49, 26, 642), utcTimeZone));

	QCOMPARE(dateTimeFromDbFormat(QString("0009-12-18 15:49:26.642+00:00")), QDateTime(QDate(9, 12, 18), QTime(15, 49, 26, 642), utcTimeZone));
	//dateTimeFromDbFormat(QString("9-12-18 15:49:26.642+00:00")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateTimeFromDbFormat(QString("2025-09-18 15:49:26.642+00:00")), QDateTime(QDate(2025, 9, 18), QTime(15, 49, 26, 642), utcTimeZone));
	//dateTimeFromDbFormat(QString("2025-9-18 15:49:26.642+00:00")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateTimeFromDbFormat(QString("2025-12-09 15:49:26.642+00:00")), QDateTime(QDate(2025, 12, 9), QTime(15, 49, 26, 642), utcTimeZone));
	//dateTimeFromDbFormat(QString("2025-12-9 15:49:26.642+00:00")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateTimeFromDbFormat(QString("2025-12-18 09:49:26.642+00:00")), QDateTime(QDate(2025, 12, 18), QTime(9, 49, 26, 642), utcTimeZone));
	//dateTimeFromDbFormat(QString("2025-12-18 9:49:26.642+00:00")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateTimeFromDbFormat(QString("2025-12-18 15:09:26.642+00:00")), QDateTime(QDate(2025, 12, 18), QTime(15, 9, 26, 642), utcTimeZone));
	//dateTimeFromDbFormat(QString("2025-12-18 15:9:26.642+00:00")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateTimeFromDbFormat(QString("2025-12-18 15:49:09.642+00:00")), QDateTime(QDate(2025, 12, 18), QTime(15, 49, 9, 642), utcTimeZone));
	//dateTimeFromDbFormat(QString("2025-12-18 15:49:9.642+00:00")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QCOMPARE(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.009+00:00")), QDateTime(QDate(2025, 12, 18), QTime(15, 49, 26, 9), utcTimeZone));
	//dateTimeFromDbFormat(QString("2025-12-18 15:49:26.9+00:00")) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QVERIFY(dateTimeFromDbFormat(QString("2025-12-18 15:49:26.642+0:0")).isValid() == false);

	/*
	 * Current format.
	 * Should always end with '+00:00'.
	 */
	{
		const QDateTime readDateTime = dateTimeFromDbFormat(
		    QString("2025-12-18 15:49:26.642+00:00"));

		QCOMPARE(readDateTime, QDateTime(QDate(2025, 12, 18), QTime(15, 49, 26, 642), utcTimeZone));

		/* Time is returned in local time zone. */
		const QDateTime currentTime = QDateTime::currentDateTime();
		QCOMPARE((readDateTime.offsetFromUtc() - readDateTime.timeZone().daylightTimeOffset(readDateTime)),
		    (currentTime.offsetFromUtc() - currentTime.timeZone().daylightTimeOffset(currentTime)));
	}

	/*
	 * Historic format without time zone.
	 * Must be interpreted as stored in local time.
	 */
	{
		const QDateTime readDateTime = dateTimeFromDbFormat(
		    QString("2025-12-18 15:49:26.642"));

		/* Qt-5.15.3-8 (Ubuntu 22.04, Debian 12) has problems when using QTimeZone::systemTimeZone() here. */
		//QCOMPARE(readDateTime, QDateTime(QDate(2025, 12, 18), QTime(15, 49, 26, 642), QTimeZone::systemTimeZone()));
		QCOMPARE(readDateTime, QDateTime(QDate(2025, 12, 18), QTime(15, 49, 26, 642)));

		/* Time is returned in local time zone. */
		const QDateTime currentTime = QDateTime::currentDateTime();
		QCOMPARE((readDateTime.offsetFromUtc() - readDateTime.timeZone().daylightTimeOffset(readDateTime)),
		    (currentTime.offsetFromUtc() - currentTime.timeZone().daylightTimeOffset(currentTime)));
	}

	/* Faulty format originating from the Python application. */
	{
		const QDateTime readDateTime = dateTimeFromDbFormat(
		    QString("2025-12-18 15:49:26.000642"));

		/* Qt-5.15.3-8 (Ubuntu 22.04, Debian 12) has problems when using QTimeZone::systemTimeZone() here. */
		//QCOMPARE(readDateTime, QDateTime(QDate(2025, 12, 18), QTime(15, 49, 26, 642), QTimeZone::systemTimeZone()));
		QCOMPARE(readDateTime, QDateTime(QDate(2025, 12, 18), QTime(15, 49, 26, 642)));

		/* Time is returned in local time zone. */
		const QDateTime currentTime = QDateTime::currentDateTime();
		QCOMPARE((readDateTime.offsetFromUtc() - readDateTime.timeZone().daylightTimeOffset(readDateTime)),
		    (currentTime.offsetFromUtc() - currentTime.timeZone().daylightTimeOffset(currentTime)));
	}
}

void TestDbTime::dateTimeDbFormatConversion(void)
{
	/* Generated strings depend on local time zone.  */
	const QString testDateFormat("yyyy MM dd HH mm ss zzz");

	QCOMPARE(dateStrFromDbFormat(QString(), testDateFormat), QString());

	/* Incomplete input. */
	QCOMPARE(dateTimeStrFromDbFormat(QString("-12-18 15:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("12-18 15:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025--18 15:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12- 15:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12 15:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-1815:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 :49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15::26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:.642+00:00"), testDateFormat), QString());
	//dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.+00:00"), testDateFormat) /* Qt 5.15 is valid, Qt 6.8 is invalid */
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.64200:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642+:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642+00:"), testDateFormat), QString());
	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642+00"), testDateFormat).isEmpty() == false); /* Actually works. */
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642+"), testDateFormat), QString());
	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642"), testDateFormat).isEmpty() == false); /* Must work. */

	/* Garbage input. */
	//dateTimeStrFromDbFormat(QString("-2025-12-18 15:49:26.642+00:00"), testDateFormat) /* Qt 5.15 is invalid, Qt 6.8 is valid */
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642+00:00-"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("-2025-12-18 15:49:26.642+00:00-"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString(" 2025-12-18 15:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642+00:00 "), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString(" 2025-12-18 15:49:26.642+00:00 "), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18-15:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-1815:49:26.642+00:00"), testDateFormat), QString());
	QCOMPARE(dateTimeStrFromDbFormat(QString("2025-12-18T15:49:26.642+00:00"), testDateFormat), QString());

	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642+00:00"), testDateFormat).isEmpty() == false);

	QVERIFY(dateTimeStrFromDbFormat(QString("0009-12-18 15:49:26.642+00:00"), testDateFormat).isEmpty() == false);
	//dateTimeStrFromDbFormat(QString("9-12-18 15:49:26.642+00:00"), testDateFormat) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QVERIFY(dateTimeStrFromDbFormat(QString("2025-09-18 15:49:26.642+00:00"), testDateFormat).isEmpty() == false);
	//dateTimeStrFromDbFormat(QString("2025-9-18 15:49:26.642+00:00"), testDateFormat) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-09 15:49:26.642+00:00"), testDateFormat).isEmpty() == false);
	//dateTimeStrFromDbFormat(QString("2025-12-9 15:49:26.642+00:00"), testDateFormat) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 09:49:26.642+00:00"), testDateFormat).isEmpty() == false);
	//dateTimeStrFromDbFormat(QString("2025-12-18 9:49:26.642+00:00"), testDateFormat) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:09:26.642+00:00"), testDateFormat).isEmpty() == false);
	//dateTimeStrFromDbFormat(QString("2025-12-18 15:9:26.642+00:00"), testDateFormat) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:09.642+00:00"), testDateFormat).isEmpty() == false);
	//dateTimeStrFromDbFormat(QString("2025-12-18 15:49:9.642+00:00"), testDateFormat) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.009+00:00"), testDateFormat).isEmpty() == false);
	//dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.9+00:00"), testDateFormat) /* Qt 5.9 is valid, Qt 5.15 is invalid */

	/*
	 * Current format.
	 * Should always end with '+00:00'.
	 */
	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642+00:00"), testDateFormat).isEmpty() == false);

	/*
	 * Historic format without time zone.
	 * Must be interpreted as stored in local time.
	 */
	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.642"), testDateFormat).isEmpty() == false);

	/*
	 * Faulty format originating from the Python application.
	 */
	QVERIFY(dateTimeStrFromDbFormat(QString("2025-12-18 15:49:26.000642"), testDateFormat).isEmpty() == false);
}

void TestDbTime::DateTimeToAndFromDB(void)
{
	/* Null dateTime. */
	{
		const QDateTime dateTime;
		QCOMPARE(dateTimeFromDbFormat(qDateTimeToDbFormat(dateTime)), dateTime);
	}

	{
		const QDateTime dateTime(QDate(2025, 12, 18), QTime(16, 49, 26, 642), utcTimeZone);
		QCOMPARE(dateTimeFromDbFormat(qDateTimeToDbFormat(dateTime)), dateTime);
	}

	{
		const QDateTime dateTime(QDate(2025, 12, 18), QTime(16, 49, 26, 642), cetTimeZone);
		QCOMPARE(dateTimeFromDbFormat(qDateTimeToDbFormat(dateTime)), dateTime);
	}

	{
		const QDateTime dateTime(QDate(2025, 12, 18), QTime(16, 49, 26, 642), localTimeZone);
		QCOMPARE(dateTimeFromDbFormat(qDateTimeToDbFormat(dateTime)), dateTime);
	}

	{
		const QDateTime dateTime(QDate(2025, 12, 18), QTime(16, 49, 26, 642));
		QCOMPARE(dateTimeFromDbFormat(qDateTimeToDbFormat(dateTime)), dateTime);
	}
}

void TestDbTime::DateTimeFromAndToDB(void)
{
	/* Invalid input. */
	{
		const QString timeStr;
		QVERIFY(qDateTimeToDbFormat(dateTimeFromDbFormat(timeStr)).isNull());
	}
	{
		const QString timeStr("");
		QVERIFY(qDateTimeToDbFormat(dateTimeFromDbFormat(timeStr)).isNull());
	}
	{
		const QString timeStr(" ");
		QVERIFY(qDateTimeToDbFormat(dateTimeFromDbFormat(timeStr)).isNull());
	}

	{
		const QString timeStr("2025-12-18 15:49:26.642+00:00");
		QCOMPARE(qDateTimeToDbFormat(dateTimeFromDbFormat(timeStr)), timeStr);
	}
	{
		const QString timeStr("2025-06-18 15:49:26.642+00:00");
		QCOMPARE(qDateTimeToDbFormat(dateTimeFromDbFormat(timeStr)), timeStr);
	}
	{
		const QString timeStr("2006-12-18 15:49:26.642+00:00");
		QCOMPARE(qDateTimeToDbFormat(dateTimeFromDbFormat(timeStr)), timeStr);
	}
	{
		const QString timeStr("1986-12-18 15:49:26.642+00:00");
		QCOMPARE(qDateTimeToDbFormat(dateTimeFromDbFormat(timeStr)), timeStr);
	}
}

QObject *newTestDbTime(void)
{
	return new (::std::nothrow) TestDbTime();
}

//QTEST_MAIN(TestDbTime)
#include "test_db_time.moc"
