QDateTimeAxis (QtCharts) 中的错误值

Bad Values in QDateTimeAxis (QtCharts)

我正在使用QtCharts 来显示模拟数据。模拟从零时间开始,但我的图表轴似乎总是从 19 小时开始。这让我很困惑。图表的设置很简单:

std::vector<SimData> data;

// ... Populate data

auto series = new QLineSeries();

for(auto i : data)
{
  // Append time in milliseconds and a value
  series->append(i.msTime, i.value);
}

this->legend()->hide();

this->addSeries(series);

this->axisX = new QDateTimeAxis;
this->axisX->setTickCount(10);
this->axisX->setFormat("HH:mm:ss");
this->axisX->setTitleText("Sim Time");
this->axisX->setMin(QDateTime());
this->addAxis(this->axisX, Qt::AlignBottom);
series->attachAxis(this->axisX);

this->axisY = new QValueAxis;
this->axisY->setLabelFormat("%i");
this->axisY->setTitleText(x->getID().c_str());
this->addAxis(this->axisY, Qt::AlignLeft);
series->attachAxis(this->axisY);

如果我 运行 没有数据,只是显示图表,我会得到:

如果我添加数据,从时间零开始,数据总量是正确的,但时间仍然从 19:00:00 开始。为什么时间不是从 00:00:00 开始?

我相信这是因为你在东海岸 (UTC-5),所以 0 代表凌晨 12 点 (2400) 在 UTC-5 0ms 代表提前 5 小时(前一天 1900)。我遇到了同样的问题,将我的时区设置为 UTC(在 ubuntu 下)并且 voila 轴从 0 小时而不是 19 开始。

确认确实是UTC偏移的问题。 SO 有一个很好的例子来说明如何获取 UTC 偏移量,然后我用它来偏移进入图表的数据:

Easy way to convert a struct tm (expressed in UTC) to time_t type

我从中创建了一个实用函数,用于 QDateTimeAxis 系列数据。

double GetUTCOffsetForQDateTimeAxis()
{
  time_t zero = 24 * 60 * 60L;
  struct tm* timeptr;
  int gmtime_hours;

  // get the local time for Jan 2, 1900 00:00 UTC
  timeptr = localtime(&zero);
  gmtime_hours = timeptr->tm_hour;

  // if the local time is the "day before" the UTC, subtract 24 hours
  // from the hours to get the UTC offset
  if(timeptr->tm_mday < 2)
  {
    gmtime_hours -= 24;
  }

  return 24.0 + gmtime_hours;
}

那么数据转换就简单了

std::vector<SimData> data;

// ... Populate data

auto series = new QLineSeries();

const auto utcOffset = sec2ms(hours2sec(GetUTCOffsetForQDateTimeAxis()));

for(auto i : data)
{
  // Append time in milliseconds and a value
  series->append(i.msTime - utcOffset, i.value);
}

// ...

献给可能到此结束的孤独流浪者。

我的 KISS 解决方案实际上是设置时间,然后是一秒钟,最后添加一个新数据点:

for(int i = 0; i <= points; i++) {
    QDateTime timeStamp;
    timeStamp.setDate(QDate(1980, 1, 1));
    timeStamp.setTime(QTime(0, 0, 0));
    timeStamp = timeStamp.addSecs(i);
    data->append(timeStamp.toMSecsSinceEpoch(), /* your y here */);
}

稍后绘制图表的地方我使用了:

QSplineSeries *temps1 = /* wherever you get your series */;
QChart *chTemp = new QChart();

tempAxisX->setTickCount(5);
tempAxisX->setFormat(QString("hh:mm:ss"));
tempAxisX->setTitleText("Time");
chTemp->addAxis(tempAxisX, Qt::AlignBottom);
temps1->attachAxis(tempAxisX);

希望这对未来的访问者(包括我自己)有帮助。

对于孤独的流浪者等等。由于 Tillo Reilly 的解决方案对我不起作用,我做了自己的(有效)。此外,我的代码将时间戳转换为特定时区。问题是——QtCharts 对时区一无所知(但最好应该知道),但以一种奇怪的方式知道 force-uses 本地 PC 时区。因此,如果您想将图表上显示的 date/time 更改为指定时区 - 您唯一能做的就是修改数据集。

原问题的答案

    auto temp_time = QDateTime::fromSecsSinceEpoch( timestamp );
    auto local_offset = temp_time.offsetFromUtc();
    auto fixed_timestamp = timestamp - local_offset;

指定时区

    auto temp_time = QDateTime::fromSecsSinceEpoch( timestamp );
    auto local_offset = temp_time.offsetFromUtc();

    temp_time.setTimeSpec( Qt::TimeZone );
    temp_time.setTimeZone( QTimeZone("Europe/Moscow") ); //for example
    auto timezone_offset =  temp_time.offsetFromUtc();

    auto fixed_timestamp = timestamp + timezone_offset - local_offset;

重要通知 1: 你不应该创建任何 random QDateTime 对象来计算偏移量,例如使用像 [=35 这样的函数=]() 或 QDateTime::fromSecsSinceEpoch(0) - 与 UTC 的偏移量取决于时间点!因此,使用上面的函数您将获得 QDateTime 对象,但它与 UTC 的偏移量可能与您期望的不同。

出于同样的原因,您不应该计算一次偏移量并将其用于所有数据集,尤其是对于具有重要时间范围的数据集。你的数据集越大——你就越有可能在中间的某个地方遇到意外的夏令时问题。

重要通知2:我不知道QtCharts 计算的是当前时间的本地时区与UTC 的偏移量还是通过数据系列传递给它的时间戳。我真希望是后者。