##// END OF EJS Templates
Merge branch 'feature/DateTimeUTC' into develop
Alexandre Leroux -
r455:a774a1678512 merge
parent child
Show More
@@ -0,0 +1,19
1 #ifndef SCIQLOP_DATEUTILS_H
2 #define SCIQLOP_DATEUTILS_H
3
4 #include "CoreGlobal.h"
5
6 #include <QDateTime>
7
8 /**
9 * Utility class with methods for dates
10 */
11 struct SCIQLOP_CORE_EXPORT DateUtils {
12 /// Converts seconds (since epoch) to datetime. By default, the datetime is in UTC
13 static QDateTime dateTime(double secs, Qt::TimeSpec timeSpec = Qt::UTC) noexcept;
14
15 /// Converts datetime to seconds since epoch
16 static double secondsSinceEpoch(const QDateTime &dateTime) noexcept;
17 };
18
19 #endif // SCIQLOP_DATEUTILS_H
@@ -0,0 +1,13
1 #include "Common/DateUtils.h"
2
3 QDateTime DateUtils::dateTime(double secs, Qt::TimeSpec timeSpec) noexcept
4 {
5 // Uses msecs to be Qt 4 compatible
6 return QDateTime::fromMSecsSinceEpoch(secs * 1000., timeSpec);
7 }
8
9 double DateUtils::secondsSinceEpoch(const QDateTime &dateTime) noexcept
10 {
11 // Uses msecs to be Qt 4 compatible
12 return dateTime.toMSecsSinceEpoch() / 1000.;
13 }
@@ -36,7 +36,6
36 36
37 37 #include <QAction>
38 38 #include <QDate>
39 #include <QDateTime>
40 39 #include <QDir>
41 40 #include <QFileDialog>
42 41 #include <QToolBar>
@@ -23,7 +23,7 struct Unit {
23 23 inline bool operator!=(const Unit &other) const { return !(*this == other); }
24 24
25 25 QString m_Name; ///< Unit name
26 bool m_TimeUnit; ///< The unit is a unit of time
26 bool m_TimeUnit; ///< The unit is a unit of time (UTC)
27 27 };
28 28
29 29 /**
@@ -3,18 +3,18
3 3
4 4 #include <QObject>
5 5
6 #include <QDateTime>
7 6 #include <QDebug>
8 7
8 #include <Common/DateUtils.h>
9 9 #include <Common/MetaTypes.h>
10 10
11 11 /**
12 12 * @brief The SqpDateTime struct holds the information of time parameters
13 13 */
14 14 struct SqpDateTime {
15 /// Start time
15 /// Start time (UTC)
16 16 double m_TStart;
17 /// End time
17 /// End time (UTC)
18 18 double m_TEnd;
19 19
20 20 bool contains(const SqpDateTime &dateTime) const noexcept
@@ -30,10 +30,9 struct SqpDateTime {
30 30
31 31 inline QDebug operator<<(QDebug d, SqpDateTime obj)
32 32 {
33 auto tendDateTimeStart = QDateTime::fromMSecsSinceEpoch(obj.m_TStart * 1000);
34 auto tendDateTimeEnd = QDateTime::fromMSecsSinceEpoch(obj.m_TEnd * 1000);
33 auto tendDateTimeStart = DateUtils::dateTime(obj.m_TStart);
34 auto tendDateTimeEnd = DateUtils::dateTime(obj.m_TEnd);
35 35
36 // QDebug << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
37 36 d << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
38 37 return d;
39 38 }
@@ -8,7 +8,6
8 8 #include <Data/IDataSeries.h>
9 9 #include <Time/TimeController.h>
10 10
11 #include <QDateTime>
12 11 #include <QMutex>
13 12 #include <QThread>
14 13 #include <QUuid>
@@ -1,9 +1,10
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableModel.h>
3 3
4 #include <Common/DateUtils.h>
5
4 6 #include <Data/IDataSeries.h>
5 7
6 #include <QDateTime>
7 8 #include <QSize>
8 9 #include <unordered_map>
9 10
@@ -150,8 +151,8 QVariant VariableModel::data(const QModelIndex &index, int role) const
150 151 if (role == Qt::DisplayRole) {
151 152 if (auto variable = impl->m_Variables.at(index.row()).get()) {
152 153 /// Lambda function that builds the variant to return for a time value
153 auto dateTimeVariant = [](double time) {
154 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
154 auto dateTimeVariant = [](double secs) {
155 auto dateTime = DateUtils::dateTime(secs);
155 156 return dateTime.toString(DATETIME_FORMAT);
156 157 };
157 158
@@ -1,6 +1,7
1 1 #include "TimeWidget/TimeWidget.h"
2 2 #include "ui_TimeWidget.h"
3 3
4 #include <Common/DateUtils.h>
4 5 #include <SqpApplication.h>
5 6 #include <Time/TimeController.h>
6 7
@@ -22,13 +23,15 TimeWidget::TimeWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::TimeWidget
22 23 &TimeController::onTimeNotify);
23 24
24 25 // Initialisation
25 ui->startDateTimeEdit->setDateTime(
26 QDateTime::currentDateTime().addSecs(-3600)); // one hour berefore
27 ui->endDateTimeEdit->setDateTime(QDateTime::currentDateTime());
26 auto endDateTime = QDateTime::currentDateTimeUtc();
27 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
28
29 ui->startDateTimeEdit->setDateTime(startDateTime);
30 ui->endDateTimeEdit->setDateTime(endDateTime);
31
32 auto dateTime = SqpDateTime{DateUtils::secondsSinceEpoch(startDateTime),
33 DateUtils::secondsSinceEpoch(endDateTime)};
28 34
29 auto dateTime
30 = SqpDateTime{QDateTime::currentDateTime().addSecs(-3600).toMSecsSinceEpoch() / 1000.0,
31 QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000.0};
32 35 sqpApp->timeController().onTimeToUpdate(dateTime);
33 36 }
34 37
@@ -40,9 +43,8 TimeWidget::~TimeWidget()
40 43
41 44 void TimeWidget::onTimeUpdateRequested()
42 45 {
43 auto dateTime = SqpDateTime{
44 static_cast<double>(ui->startDateTimeEdit->dateTime().toMSecsSinceEpoch() / 1000.),
45 static_cast<double>(ui->endDateTimeEdit->dateTime().toMSecsSinceEpoch()) / 1000.};
46 auto dateTime = SqpDateTime{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
47 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
46 48
47 49 emit timeUpdated(std::move(dateTime));
48 50 }
@@ -25,6 +25,7 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
25 25 if (isTimeAxis) {
26 26 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 27 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28 dateTicker->setDateTimeSpec(Qt::UTC);
28 29
29 30 return dateTicker;
30 31 }
@@ -1,6 +1,8
1 1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
2 2 #include "Visualization/qcustomplot.h"
3 3
4 #include <Common/DateUtils.h>
5
4 6 namespace {
5 7
6 8 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
@@ -14,9 +16,12 const auto TRACER_TIMEOUT = 500;
14 16 QString formatValue(double value, const QCPAxis &axis)
15 17 {
16 18 // If the axis is a time axis, formats the value as a date
17 return qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())
18 ? QCPAxisTickerDateTime::keyToDateTime(value).toString(DATETIME_FORMAT)
19 : QString::number(value);
19 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
20 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
21 }
22 else {
23 return QString::number(value);
24 }
20 25 }
21 26
22 27 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
@@ -47,6 +47,9
47 47 <property name="calendarPopup">
48 48 <bool>true</bool>
49 49 </property>
50 <property name="timeSpec">
51 <enum>Qt::UTC</enum>
52 </property>
50 53 </widget>
51 54 </item>
52 55 <item>
@@ -76,6 +79,9
76 79 <property name="calendarPopup">
77 80 <bool>true</bool>
78 81 </property>
82 <property name="timeSpec">
83 <enum>Qt::UTC</enum>
84 </property>
79 85 </widget>
80 86 </item>
81 87 <item>
@@ -2,6 +2,7
2 2 #include "AmdaDefs.h"
3 3 #include "AmdaResultParser.h"
4 4
5 #include <Common/DateUtils.h>
5 6 #include <Data/DataProviderParameters.h>
6 7 #include <Network/NetworkController.h>
7 8 #include <SqpApplication.h>
@@ -31,7 +32,7 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
31 32 /// Formats a time to a date that can be passed in URL
32 33 QString dateFormat(double sqpDateTime) noexcept
33 34 {
34 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
35 auto dateTime = DateUtils::dateTime(sqpDateTime);
35 36 return dateTime.toString(AMDA_TIME_FORMAT);
36 37 }
37 38
@@ -1,5 +1,6
1 1 #include "AmdaResultParser.h"
2 2
3 #include <Common/DateUtils.h>
3 4 #include <Data/ScalarSeries.h>
4 5
5 6 #include <QDateTime>
@@ -33,10 +34,17 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.
33 34 double doubleDate(const QString &stringDate) noexcept
34 35 {
35 36 auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT);
36 return dateTime.isValid() ? (dateTime.toMSecsSinceEpoch() / 1000.)
37 dateTime.setTimeSpec(Qt::UTC);
38 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
37 39 : std::numeric_limits<double>::quiet_NaN();
38 40 }
39 41
42 /// Checks if a line is a comment line
43 bool isCommentLine(const QString &line)
44 {
45 return line.startsWith("#");
46 }
47
40 48 /**
41 49 * Reads stream to retrieve x-axis unit
42 50 * @param stream the stream to read
@@ -47,20 +55,16 Unit readXAxisUnit(QTextStream &stream)
47 55 {
48 56 QString line{};
49 57
50 if (stream.readLineInto(&line)) {
58 // Searches unit in the comment lines
59 while (stream.readLineInto(&line) && isCommentLine(line)) {
51 60 auto match = UNIT_REGEX.match(line);
52 61 if (match.hasMatch()) {
53 62 return Unit{match.captured(1), true};
54 63 }
55 else {
56 qCWarning(LOG_AmdaResultParser())
57 << QObject::tr("Can't read unit: invalid line %1").arg(line);
58 }
59 }
60 else {
61 qCWarning(LOG_AmdaResultParser()) << QObject::tr("Can't read unit: end of file");
62 64 }
63 65
66 qCWarning(LOG_AmdaResultParser()) << QObject::tr("The unit could not be found in the file");
67
64 68 // Error cases
65 69 return Unit{{}, true};
66 70 }
@@ -76,32 +80,36 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
76 80 auto valuesData = QVector<double>{};
77 81
78 82 QString line{};
83
79 84 while (stream.readLineInto(&line)) {
80 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
81 if (lineData.size() == 2) {
82 // X : the data is converted from date to double (in secs)
83 auto x = doubleDate(lineData.at(0));
84
85 // Value
86 bool valueOk;
87 auto value = lineData.at(1).toDouble(&valueOk);
88
89 // Adds result only if x and value are valid
90 if (!std::isnan(x) && !std::isnan(value) && valueOk) {
91 xData.push_back(x);
92 valuesData.push_back(value);
85 // Ignore comment lines
86 if (!isCommentLine(line)) {
87 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
88 if (lineData.size() == 2) {
89 // X : the data is converted from date to double (in secs)
90 auto x = doubleDate(lineData.at(0));
91
92 // Value
93 bool valueOk;
94 auto value = lineData.at(1).toDouble(&valueOk);
95
96 // Adds result only if x and value are valid
97 if (!std::isnan(x) && !std::isnan(value) && valueOk) {
98 xData.push_back(x);
99 valuesData.push_back(value);
100 }
101 else {
102 qCWarning(LOG_AmdaResultParser())
103 << QObject::tr(
104 "Can't retrieve results from line %1: x and/or value are invalid")
105 .arg(line);
106 }
93 107 }
94 108 else {
95 109 qCWarning(LOG_AmdaResultParser())
96 << QObject::tr(
97 "Can't retrieve results from line %1: x and/or value are invalid")
98 .arg(line);
110 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
99 111 }
100 112 }
101 else {
102 qCWarning(LOG_AmdaResultParser())
103 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
104 }
105 113 }
106 114
107 115 return qMakePair(std::move(xData), std::move(valuesData));
@@ -131,13 +139,12 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath)
131 139 return nullptr;
132 140 }
133 141
134 // Ignore comments lines
135 stream.readLine();
136
137 142 // Reads x-axis unit
143 stream.seek(0); // returns to the beginning of the file
138 144 auto xAxisUnit = readXAxisUnit(stream);
139 145
140 146 // Reads results
147 stream.seek(0); // returns to the beginning of the file
141 148 auto results = readResults(stream);
142 149
143 150 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
@@ -99,7 +99,7 void TestAmdaResultParser::testReadTxt_data()
99 99 // ////////// //
100 100
101 101 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
102 return QDateTime{{year, month, day}, {hours, minutes, seconds}};
102 return QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC};
103 103 };
104 104
105 105 // Valid file
@@ -5,7 +5,6
5 5
6 6 #include <cmath>
7 7
8 #include <QDateTime>
9 8 #include <QFuture>
10 9 #include <QThread>
11 10 #include <QtConcurrent/QtConcurrent>
General Comments 0
You need to be logged in to leave comments. Login now