2017-08-04 46 views
2

私は最近ストップウォッチを書いて、QDateTime::secsToという奇妙な振る舞いに気付きました。私はそれがバグか機能かどうか分からない(あるいは恐らく私はほんとうの実装しかしなかった;-)。QDateTime :: secsToは異なるQDateTimeに同じ値を返します

マイストップウォッチコードが疑わしい結果を生成するために、この最小の例まで除去することができる

(少なくともLinux上のQt 5.7.1を使用して):

StopWatch.h

#ifndef STOPWATCH_H 
#define STOPWATCH_H 

#include <QDialog> 
#include <QDateTime> 

class QTimer; 

class StopWatch : public QDialog 
{ 
    Q_OBJECT 

public: 
    explicit StopWatch(QWidget *parent); 

private slots: 
    void update(); 

private: 
    QTimer *m_timer; 
    QDateTime m_targetTime; 
}; 

#endif // STOPWATCH_H 

ストップウォッチ.cppファイル

#include "StopWatch.h" 
#include <QDebug> 
#include <QTimer> 

StopWatch::StopWatch(QWidget *parent) : QDialog(parent) 
{ 
    m_timer = new QTimer(this); 
    m_timer->setTimerType(Qt::PreciseTimer); 
    connect(m_timer, &QTimer::timeout, this, &StopWatch::update); 
    m_targetTime = QDateTime::currentDateTime().addSecs(10); 
    m_timer->start(1000); 
} 

void StopWatch::update() 
{ 
    QDateTime currentDateTime = QDateTime::currentDateTime(); 
    qint64 secondsLeft = currentDateTime.secsTo(m_targetTime); 
    qDebug() << secondsLeft; 
} 

そして、ここでのアウトプット(の一部):

4 
3 
2 
1 
0 
0 
-1 
-2 
-3 
-4 

は、そこでここでは、次のとおりです。QDateTime::secsTo出力前QDateTime 1秒間同じQDateTimeため0

私は

if (currentDateTime <= m_targetTime) { 
    secondsLeft++; 
} 

を行うことによってこの問題を回避働いていたが、私はbehavoirを理解していません。これはなぜですか?

+2

丸めの問題?たぶん1秒で正確に始まるわけではありません。 – drescherjm

+0

いつも同じです。コードを試してください - 回避策を追加する前にこれを頻繁に実行しました... –

+0

もし私が推測したことがあったなら、QDateTime :: secsTo()はpostive/negative整数で変わったことをしています。それは、負の数の場合は整数の上限を、正の数の場合は整数のフロアを実行しているように見えます。 mSecsToに切り替えて報告してください。 – user2836202

答えて

4

それはそれは1000年の下にある2つの正の整数を取るように見える、1000でそれらを分割し、各他からそれらを減算し、ソースコードhttp://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/tools/qdatetime.cpp

int QTime::secsTo(const QTime &t) const 
{ 
    if (!isValid() || !t.isValid()) 
     return 0; 

    // Truncate milliseconds as we do not want to consider them. 
    int ourSeconds = ds()/1000; 
    int theirSeconds = t.ds()/1000; 
    return theirSeconds - ourSeconds; 
} 

を見てみます。 mSecsTo()を使用すると、この問題は発生しません。

2

丸めの問題です。 secsTo機能は、最も近い整数にラウンドしませんが、ちょうど(これは、コンパイラは、デフォルトでは何をすべきかです)小数部分を削除します。

int QTime::secsTo(const QTime &t) const 
{ 
    if (!isValid() || !t.isValid()) 
     return 0; 

    // Truncate milliseconds as we do not want to consider them. 
    int ourSeconds = ds()/1000; 
    int theirSeconds = t.ds()/1000; 
    return theirSeconds - ourSeconds; 
} 

または4.xバージョン:

int QTime::secsTo(const QTime &t) const 
{ 
    return (t.ds() - ds())/1000; 
} 

だから何おそらく見ている:

4.8 -> 4 
3.8 -> 3 
2.8 -> 2 
1.8 -> 1 
0.8 -> 0 
-0.2 -> 0 
-1.2 -> -1 
-2.2 -> -2 
-3.2 -> -3 
-4.2 -> -4 

予想される結果については、のようなものを使用します。

qint64 secondsLeft = qRound64(currentDateTime.msecsTo(m_targetTime)/1000.0); 
関連する問題