The constructors QQmlApplicationEngine and QSettings spoil the time zone (daylight)
-
I came across the strange behavior of the QQmlApplicationEngine constructor. The minimum code is main.cpp:
#include <QApplication> #include <QQmlApplicationEngine> #include <QDebug> int main(int argc, char *argv[]) { QApplication app(argc, argv); qDebug() << "1ST timezone=" << timezone << " daylight=" << daylight; tzset(); qDebug() << "2ND timezone=" << timezone << " daylight=" << daylight; QQmlApplicationEngine engine; qDebug() << "3ND timezone=" << timezone << " daylight=" << daylight; return app.exec(); }
Result of work:
1ST timezone= 0 daylight= 0 2ND timezone= -10800 daylight= 1 3ND timezone= -10800 daylight= 0
That is, after the QQmlApplicationEngine constructor is triggered, daylight spoils (switch to zero).
I was surprised, but it's necessary to work and therefore I tried to get around this case like this:
long saveTimezone=timezone; int saveDaylight=daylight; QQmlApplicationEngine engine; timezone=saveTimezone; daylight=saveDaylight;
It worked, but in the project I still found another one place in which the same behavior, after the QSettings constructor (but already in the heap). Looks like that:
qDebug() << "CURRENT timezone=" << timezone << " daylight=" << daylight; QSettings *config=new QSettings(fileName, QSettings::IniFormat, this); qDebug() << "CURRENT timezone=" << timezone << " daylight=" << daylight;
CURRENT timezone= -10800 daylight= 1 CURRENT timezone= -10800 daylight= 0
But in a minimal code, I could not repeat this.
Where else the variable daylight can spoil, I do not know, but I do not rule out such probabilities. The problem is that my project uses a legacy library that works with daylight, and because of these problems it gives the wrong time.
Questions: what kind of problem is this, why do some Qt classes spoil daylight, how is this thing guaranteed to work around?
PS: The project file that would quickly compile a minimal example (only the project file and main.cpp will be required):
CONFIG+=c++11 CONFIG+=qml_debug QT+=gui QT+=core QT+=quick QT+=widgets SOURCES += main.cpp DEFINES += QT_DEPRECATED_WARNINGS
-
Hi,
Intriguing !
What version of Qt are you using ?
On what platform ? -
@xintrea said in The constructors QQmlApplicationEngine and QSettings spoil the time zone (daylight):
Qt 5.10.1 by official site
You mean downloaded from qt.io, correct? Because debian doesn't provide that in stable, but the current Qt version for the testing flavor is exactly 5.10.1.
-
@kshegunov
Yes. I use Debian Stable 9 (64-bit) with all updates:> lsb_release -a No LSB modules are available. Distributor ID: Debian Description: Debian GNU/Linux 9.3 (stretch) Release: 9.3 Codename: stretch
I get Qt from qt.io as file qt-opensource-linux-x64-5.10.1.run.
-
Do you get the same behaviour if you use Debian's provided version of Qt ?
-
I not experiment with Qt version.
But i debug this situation. I set watchpoint to system global variable daylight. This is stack if run constructor QQmlApplicationEngine:
(gdb) where #0 update_vars () at tzset.c:156 #1 0x00007ffff3c8a569 in __tzset_parse_tz (tz=<optimized out>) at tzset.c:391 #2 0x00007ffff3c8c27b in __tzfile_compute (timer=<optimized out>, use_localtime=use_localtime@entry=1, leap_correct=leap_correct@entry=0x7fffffffd938, leap_hit=leap_hit@entry=0x7fffffffd934, tp=tp@entry=0x7fffffffd980) at tzfile.c:691 #3 0x00007ffff3c8ac44 in __tz_convert (timer=0x7fffffffd978, use_localtime=1, tp=0x7fffffffd980) at tzset.c:624 #4 0x00007ffff608230a in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5 #5 0x00007ffff608afab in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5 #6 0x00007ffff60692db in QV4::ExecutionEngine::ExecutionEngine(QV4::EvalISelFactory*) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5 #7 0x00007ffff61c949a in QV8Engine::QV8Engine(QJSEngine*) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5 #8 0x00007ffff5fffb14 in QJSEngine::QJSEngine(QJSEnginePrivate&, QObject*) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5 #9 0x00007ffff6127969 in QQmlEngine::QQmlEngine(QQmlEnginePrivate&, QObject*) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5 #10 0x00007ffff61b44e0 in QQmlApplicationEngine::QQmlApplicationEngine(QObject*) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5
And this is stack if run constructor QSettings:
(gdb) where #0 update_vars () at tzset.c:156 #1 0x00007ffff3c8a569 in __tzset_parse_tz (tz=<optimized out>) at tzset.c:391 #2 0x00007ffff3c8c27b in __tzfile_compute (timer=<optimized out>, use_localtime=use_localtime@entry=1, leap_correct=leap_correct@entry=0x7fffffffd3f8, leap_hit=leap_hit@entry=0x7fffffffd3f4, tp=tp@entry=0x7fffffffd4a0) at tzfile.c:691 #3 0x00007ffff3c8ac44 in __tz_convert (timer=0x7fffffffd498, use_localtime=1, tp=0x7fffffffd4a0) at tzset.c:624 #4 0x00007ffff4dc8709 in QDateTime::setMSecsSinceEpoch(long long) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5 #5 0x00007ffff4dcab4d in QDateTime::fromMSecsSinceEpoch(long long, Qt::TimeSpec, int) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5 #6 0x00007ffff4dcb00d in QDateTime::fromMSecsSinceEpoch(long long) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5 #7 0x00007ffff4e87226 in QFileInfo::fileTime(QFileDevice::FileTime) const () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5 #8 0x00007ffff4e8732e in QFileInfo::lastModified() const () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5 #9 0x00007ffff4ec90e1 in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5 #10 0x00007ffff4ec98cd in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5 #11 0x00007ffff4eca4b4 in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5 #12 0x00007ffff4eca57f in QSettings::QSettings(QString const&, QSettings::Format, QObject*)
Really, QQmlApplicationEngine and QSettings is change timezone and, therefore, daylight.
-
And function update_vars() is:
151 static void 152 internal_function 153 update_vars (void) 154 { 155 __daylight = tz_rules[0].offset != tz_rules[1].offset; 156 __timezone = -tz_rules[0].offset; 157 __tzname[0] = (char *) tz_rules[0].name; 158 __tzname[1] = (char *) tz_rules[1].name; 159 160 /* Keep __tzname_cur_max up to date. */ 161 size_t len0 = strlen (__tzname[0]); 162 size_t len1 = strlen (__tzname[1]); 163 if (len0 > __tzname_cur_max) 164 __tzname_cur_max = len0; 165 if (len1 > __tzname_cur_max) 166 __tzname_cur_max = len1; 167 }