2

I use Qt 5.7.1 on Windows, 64 bits version. In my application, I manage some date time with different time zone.

I've recently seen some strange behaviour, and here is a simple code to test it :

QDateTime ParisDate(QDate(2016, 1, 20), QTime(2, 0, 0), QTimeZone("Europe/Paris"));
QDateTime PerthDate(QDate(2016, 1, 20), QTime(9, 0, 0), QTimeZone("Australia/Perth"));
QDateTime ParisConvertedToPerth = ParisDate.toTimeZone(QTimeZone("Australia/Perth"));

qDebug() << "                                ParisDate = " << ParisDate;
qDebug() << "                                PerthDate = " << PerthDate;
qDebug() << "                     delta Paris => Perth = " << ParisDate.secsTo(PerthDate) / 3600;
qDebug() << "     delta ParisConvertedToPerth => Perth = " << ParisConvertedToPerth.secsTo(PerthDate) / 3600;
qDebug() << "                         ParisDate to UTC = " << ParisDate.toUTC();
qDebug() << "                         PerthDate to UTC = " << PerthDate.toUTC();
qDebug() << "             ParisConvertedToPerth to UTC = " << ParisConvertedToPerth.toUTC();

This produce the following output :

                            ParisDate =  QDateTime(2016-01-20 02:00:00.000 Paris, Madrid Qt::TimeSpec(TimeZone) Europe/Paris)
                            PerthDate =  QDateTime(2016-01-20 09:00:00.000 Australie (Ouest) Qt::TimeSpec(TimeZone) Australia/Perth)
                delta  Paris => Perth =  8
delta  ParisConvertedToPerth => Perth =  0
                     ParisDate to UTC =  QDateTime(2016-01-20 01:00:00.000 UTC Qt::TimeSpec(UTC))
                     PerthDate to UTC =  QDateTime(2016-01-20 09:00:00.000 UTC Qt::TimeSpec(UTC))
         ParisConvertedToPerth to UTC =  QDateTime(2016-01-20 09:00:00.000 UTC Qt::TimeSpec(UTC))

I don't understand, because I thought that the 2 variables "ParisDate" and "PerthDate" should refer to the same point in time, exprimed with a different time zone.

So I believe the "delta Paris => Perth" should be 0 hours.

I can't believe the Qt5 code is broken, so what did I miss here ?

Aurelien
  • 1,032
  • 2
  • 10
  • 24

2 Answers2

3

This is a bug in Qt that has already been fixed, but the fix is not published. It seems like you will have to wait for Qt 5.9 or Qt 5.6.3.

Using Qt dev branch I have this output:

                            ParisDate =  QDateTime(2016-01-20 02:00:00.000 Paris, Madrid Qt::TimeSpec(TimeZone) Europe/Paris)
                            PerthDate =  QDateTime(2016-01-20 09:00:00.000 Australie (Ouest) Qt::TimeSpec(TimeZone) Australia/Perth)
                 delta Paris => Perth =  0
 delta ParisConvertedToPerth => Perth =  0
                     ParisDate to UTC =  QDateTime(2016-01-20 01:00:00.000 UTC Qt::TimeSpec(UTC))
                     PerthDate to UTC =  QDateTime(2016-01-20 01:00:00.000 UTC Qt::TimeSpec(UTC))
         ParisConvertedToPerth to UTC =  QDateTime(2016-01-20 01:00:00.000 UTC Qt::TimeSpec(UTC))
Benjamin T
  • 8,120
  • 20
  • 37
  • any link to the bug? When exactly does the bug happen? – Mike Jan 18 '17 at 01:50
  • This is bad news, but thanks ! Can you send a link to this bug, so I can follow its status ? – Aurelien Jan 18 '17 at 07:07
  • I do not know the bug report associated with this bug (not even which commit fixed it). However the bug seems specific to Windows, I was not abl to reproduc it on Ubuntu x64. – Benjamin T Jan 18 '17 at 09:20
  • I've found more info here : https://codereview.qt-project.org/#/c/162414/ – Aurelien Jan 18 '17 at 14:02
1

I can't speak to what is going on with Qt. However I thought it would be an interesting exercise to change the syntax of your test to use this free, open-source C++11/14 library, and compare both the test syntax and the output.

auto ParisDate = make_zoned("Europe/Paris", local_days{2016_y/1/20} + 2h);
auto PerthDate = make_zoned("Australia/Perth", local_days{2016_y/1/20} + 9h);
auto ParisConvertedToPerth = make_zoned("Australia/Perth", ParisDate);

cout << "                           ParisDate = " << ParisDate << '\n';
cout << "                           PerthDate = " << PerthDate << '\n';
cout << "                delta Paris => Perth = "
     << floor<hours>(PerthDate.get_sys_time() - ParisDate.get_sys_time()) << '\n';
cout << "delta ParisConvertedToPerth => Perth = "
     << floor<hours>(PerthDate.get_sys_time() - ParisConvertedToPerth.get_sys_time()) << '\n';
cout << "                    ParisDate to UTC = " << ParisDate.get_sys_time() << '\n';
cout << "                    PerthDate to UTC = " << PerthDate.get_sys_time() << '\n';
cout << "        ParisConvertedToPerth to UTC = " << ParisConvertedToPerth.get_sys_time() << '\n';

This produced the following output :

                           ParisDate = 2016-01-20 02:00:00 CET
                           PerthDate = 2016-01-20 09:00:00 AWST
                delta Paris => Perth = 0h
delta ParisConvertedToPerth => Perth = 0h
                    ParisDate to UTC = 2016-01-20 01:00:00
                    PerthDate to UTC = 2016-01-20 01:00:00
        ParisConvertedToPerth to UTC = 2016-01-20 01:00:00
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577