Dealing with QDateTime and January 1 1970 at 00:00:00
-
@wavelike
Like I wrote:Forget your CSV file. Try a literal inputString, as per whatever you would get out of the file. Show us lines you try and the output, what works and what does not.
For example, I try this (Python/PySide2, but irrelevant, same will work from C++), and get correct result:
>>> from PySide2.QtCore import QDateTime >>> print(QDateTime.fromString("01/01/1970 00:00:00", "dd/MM/yyyy hh:mm:ss")) PySide2.QtCore.QDateTime(1970, 1, 1, 0, 0, 0, 0, 0) >>> print(QDateTime.fromString("31/12/1969 00:00:00", "dd/MM/yyyy hh:mm:ss")) PySide2.QtCore.QDateTime(1969, 12, 31, 0, 0, 0, 0, 0) >>>
Note that I am showing that even a datetime prior to 1/1/1970 still works too.
Show me where you get back "an invalid
QDateTime
"? -
@JonB said in Dealing with QDateTime and January 1 1970 at 00:00:00:
Like I wrote:
Forget your CSV file. Try a literal inputString, as per whatever you would get out of the file. Show us lines you try and the output, what works and what does not.
For example, I try this (Python/PySide2), and get correct result:
from PySide2.QtCore import QDateTime
QDateTime.fromString("01/01/1970 00:00:00", "dd/MM/yyyy hh:mm:ss")
PySide2.QtCore.QDateTime(1970, 1, 1, 0, 0, 0, 0, 0)I can confirm
int main(int argc, char *argv[]) { QApplication a(argc, argv); QString dtStr("01-01-1970 00:00:00"); QDateTime dt = QDateTime::fromString(dtStr,"MM-dd-yyyy hh:mm:ss"); qDebug() << dt; return a.exec(); }
results in a valid datetime
QDateTime(1970-01-01 00:00:00.000 CET Qt::LocalTime)
-
@J-Hilk said in Dealing with QDateTime and January 1 1970 at 00:00:00:
@JonB said in Dealing with QDateTime and January 1 1970 at 00:00:00:
Like I wrote:
Forget your CSV file. Try a literal inputString, as per whatever you would get out of the file. Show us lines you try and the output, what works and what does not.
For example, I try this (Python/PySide2), and get correct result:
from PySide2.QtCore import QDateTime
QDateTime.fromString("01/01/1970 00:00:00", "dd/MM/yyyy hh:mm:ss")
PySide2.QtCore.QDateTime(1970, 1, 1, 0, 0, 0, 0, 0)I can confirm
int main(int argc, char *argv[]) { QApplication a(argc, argv); QString dtStr("01-01-1970 00:00:00"); QDateTime dt = QDateTime::fromString(dtStr,"MM-dd-yyyy hh:mm:ss"); qDebug() << dt; return a.exec(); }
results in a valid datetime
QDateTime(1970-01-01 00:00:00.000 CET Qt::LocalTime)
Ok, I confirm this too.
I think I know where the problem is. I thought I had that covered, but now I will have to go back to the code and take a look. Anyway, here goes the same code as above, with addition.
#include <QApplication> #include <QString> #include <QDateTime> #include <QDebug> int main(int argc, char *argv[]) { QApplication a(argc,argv); QString dtFormat("MM-dd-yy hh:mm:ss"); QString dt1Str("01-01-70 00:00:00"); QString dt2Str("01-01-70 00:00:01"); QDateTime dt1 = QDateTime::fromString(dt1Str,dtFormat); QDateTime dt2 = QDateTime::fromString(dt2Str,dtFormat); qDebug()<<dt1<<dt2<<"\n"; qDebug()<<"dt1 is valid? "<<dt1.isValid()<<"\n"; qDebug()<<"dt1 is equal to QDateTime()? "<<(dt1 == QDateTime())<<"\n"; qDebug()<<"dt2 is valid? "<<dt2.isValid()<<"\n"; qDebug()<<"dt2 is equal to QDateTime()? "<<(dt2 == QDateTime())<<"\n"; return a.exec(); }
The output is true, true, true, false. Now I have to dive into the code and see where this is checked and how exactly it's done, but hopefully that is the culprit.
Thanks everyone.
P.S. From documentation:
QDateTime::QDateTime() Constructs a null datetime (i.e. null date and null time). A null datetime is invalid, since the date is invalid.
So, dt1 above is a null datetime, because it is equal to QDateTime(). But dt1.isValid() returns true. I am very, very tired these days, so this is probably obvious, but... uh?
-
@wavelike said in Dealing with QDateTime and January 1 1970 at 00:00:00:
So, dt1 above is a null datetime, because it is equal to QDateTime(). But dt1.isValid() returns true. I am very, very tired these days, so this is probably obvious, but... uh?
Hmm, yes this very confusing. But even if
QDateTime()
is an invalid instance, usingQDateTime()
to check if a QDateTime instance is invalid is a bad usage!
To check a QDateTime instance validity, you have to useQDateTime::isValid()
.
I suppose thatoperator==()
compare the unixtimestamp, and per default this value is probably '0' and your dt1 is unix time 0! -
@wavelike
I agree with your finding:>>> QDateTime.fromString("01/01/70 00:00:00", "dd/MM/yy hh:mm:ss") PySide2.QtCore.QDateTime(1970, 1, 1, 0, 0, 0, 0, 0) >>> QDateTime.fromString("01/01/70 00:00:01", "dd/MM/yy hh:mm:ss") PySide2.QtCore.QDateTime(1970, 1, 1, 0, 0, 1, 0, 0) >>> QDateTime() PySide2.QtCore.QDateTime(0, 0, 0, -1, -1, -1, -1, 0) >>> >>> QDateTime.fromString("01/01/70 00:00:00", "dd/MM/yy hh:mm:ss") == QDateTime() True >>> QDateTime.fromString("01/01/70 00:00:01", "dd/MM/yy hh:mm:ss") == QDateTime() False
I agree this is strange! Although
isValid()
returnsTrue
for both, it seems comparing (01/01/70 00:00:00
, only this) againstQDateTime()
for invalidity is not a good idea! You must stick withisValid()
.Only a Qt expert (not me) examining the above can explain behaviour.... ?
EDIT @KroMignon's reply crossed with mine. Somewhere his suspicion that
I suppose that operator==() compare the unixtimestamp, and per default this value is probably '0' and your dt1 is unix time 0!
Which exact Qt version are you using?
https://doc.qt.io/qt-5/qdatetime.html#operator-eq-eq
bool QDateTime::operator==(const QDateTime &other) const
Returns true if this datetime is equal to the other datetime; otherwise returns false.
Since 5.14, all invalid datetimes are equal to one another and differ from all other datetimes.
will doubtless indeed be the cause!
I think what you have found is a "bug", given the above! Your valid 1970 datetime does not differ from an invalid datetime....
I suspect Qt has always behaved like this, but I think this is indeed a nasty "gotcha" and worthy of being reported, I can see how it could bite others on the butt unexpectedly....
-
@KroMignon , @JonB
I agree that using isValid() seems like a much better programming practice. However, documentation is not always perfectly clear and can lead to wrong conclusions if not read thoroughly (which we usually don't do when facing deadlines...).On Linux, I am using Qt version 5.13.0, while on Windows it's 5.9.2.
-
@JonB said in Dealing with QDateTime and January 1 1970 at 00:00:00:
...
https://doc.qt.io/qt-5/qdatetime.html#operator-eq-eq
bool QDateTime::operator==(const QDateTime &other) const
Returns true if this datetime is equal to the other datetime; otherwise returns false.
Since 5.14, all invalid datetimes are equal to one another and differ from all other datetimes.
will doubtless indeed be the cause!
I think what you have found is a "bug", given the above! Your valid 1970 datetime does not differ from an invalid datetime....
I suspect Qt has always behaved like this, but I think this is indeed a nasty "gotcha" and worthy of being reported, I can see how it could bite others on the butt unexpectedly....
If you, or anyone else, have time and know where to report these kinds of things, please do it. If it is worth reporting, of course. I really don't have time, unfortunately.
Again, thank you for your help. :)
-
@wavelike
We are saying that you must change over your code to only use.isValid()
for this check, not== QDateTime()
. You have no choice as Qt stands.I am saying to you that this may be worthy of reporting to Qt bug site, because I feel it is clearly "wrong", in terms of documentation/expected behaviour. Whether they will do anything about it if Qt has always behaved like this on that date I cannot say....
EDIT FWIW, I have raised https://bugreports.qt.io/browse/QTBUG-82853
-
Up to 5.14, comparison between date-times was tacitly only defined for valid date-times; you needed to check .isValid() before comparing. In fact, it was quite possible to construct diverse invalid date-times, each of which would compare equal to some valid date-time. At 5.14, this is fixed so that all invalid date-times compare less than all valid date-times (and, in particular, equal to none of them).
So either check isValid() first, or upgrade to 5.14 (or later). -
... oh, and: yes, to determine validity, always use isValid() rather than comparison to an invalid value (not just for QDateTime): isValid() is authoritative, comparison might fail for types that may have more than one invalid value.
-
@EdwardWelbourne said in Dealing with QDateTime and January 1 1970 at 00:00:00:
Up to 5.14,
I only have 5.12.2, and I think the OP says he has 5.13. In those two
QDateTime.fromString("01/01/1970 00:00:00", "dd/MM/yyyy hh:mm:ss") == QDateTime() => true
Are you saying this now returns
false
at 5.14? Thanks.EDIT On the QTBUG @EdwardWelbourne has stated it is fixed at 5.14.