2017-08-04 2204 views
2

我最近寫了一個秒錶,並注意到一些奇怪的行爲QDateTime::secsTo。我不確定它是一個錯誤還是一個功能(或者我只做了一個糟糕的實現;-)。QDateTime :: secsTo爲不同的QDateTime返回相同的值

我的秒錶代碼可以被剝離下來,以該最小示例(使用Qt 5.7.1至少在Linux上)以產生可疑結果:

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輸出0爲同一QDateTime的前QDateTime一秒。

我工作圍繞這個做

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

,但我不明白的behavoir。爲什麼會這樣?

+2

舍入問題?也許你不會一秒鐘開始。 – drescherjm

+0

它總是一樣的。試試這段代碼 - 在添加解決方法之前,我經常運行它... –

+0

如果我有一個最好的猜測,那就是QDateTime :: secsTo()會用正整數/負整數做一些奇怪的事情。它看起來像是對負數做整數上限,對正數做整數平方。嘗試切換到mSecsTo並回報。 – user2836202

回答

4

查看源代碼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; 
} 

看起來它需要兩個是1000下的正整數,將其劃分由1000,然後從彼此中減去它們。如果你使用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);