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 的偏移量还是通过数据系列传递给它的时间戳。我真希望是后者。
我正在使用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);
如果我 运行 没有数据,只是显示图表,我会得到:
我相信这是因为你在东海岸 (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 的偏移量还是通过数据系列传递给它的时间戳。我真希望是后者。