swift
timestampbased.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "misc/timestampbased.h"
5 
6 #include <QByteArray>
7 #include <QDateTime>
8 
10 #include "misc/stringutils.h"
11 #include "misc/verify.h"
12 
13 namespace swift::misc
14 {
16 
17  ITimestampBased::ITimestampBased(qint64 msSincePoch) : m_timestampMSecsSinceEpoch(msSincePoch) {}
18 
19  ITimestampBased::ITimestampBased(const QDateTime &timestamp)
20  : m_timestampMSecsSinceEpoch(timestamp.toMSecsSinceEpoch())
21  {}
22 
24  {
25  if (m_timestampMSecsSinceEpoch < 0) { return QDateTime(); }
26  return QDateTime::fromMSecsSinceEpoch(m_timestampMSecsSinceEpoch);
27  }
28 
30 
31  void ITimestampBased::setByYearMonthDayHourMinute(const QString &yyyyMMddhhmmsszzz)
32  {
33  // yyyy MM dd hh mm ss zzz
34  // 0123 45 67 89 01 23 456
35  // 1234 56 78 90 12 34 567
36 
37  const QString s(removeDateTimeSeparators(yyyyMMddhhmmsszzz));
38  const QDateTime dt = parseDateTimeStringOptimized(s);
39  this->setUtcTimestamp(dt);
40  }
41 
42  void ITimestampBased::setUtcTimestamp(const QDateTime &timestamp)
43  {
44  m_timestampMSecsSinceEpoch = timestamp.isValid() ? timestamp.toMSecsSinceEpoch() : -1;
45  }
46 
47  bool ITimestampBased::isNewerThan(const ITimestampBased &otherTimestampObj) const
48  {
49  return m_timestampMSecsSinceEpoch > otherTimestampObj.m_timestampMSecsSinceEpoch;
50  }
51 
52  bool ITimestampBased::isNewerThan(qint64 mSecsSinceEpoch) const
53  {
54  return m_timestampMSecsSinceEpoch > mSecsSinceEpoch;
55  }
56 
57  bool ITimestampBased::isOlderThan(const ITimestampBased &otherTimestampObj) const
58  {
59  return m_timestampMSecsSinceEpoch < otherTimestampObj.m_timestampMSecsSinceEpoch;
60  }
61 
62  bool ITimestampBased::isOlderThan(qint64 mSecsSinceEpoch) const
63  {
64  return m_timestampMSecsSinceEpoch < mSecsSinceEpoch;
65  }
66 
68  {
69  if (offsetMs <= 0) { return false; }
70  return m_timestampMSecsSinceEpoch < (QDateTime::currentMSecsSinceEpoch() - offsetMs);
71  }
72 
73  bool ITimestampBased::isSame(const ITimestampBased &otherTimestampObj) const
74  {
75  return m_timestampMSecsSinceEpoch == otherTimestampObj.m_timestampMSecsSinceEpoch;
76  }
77 
78  qint64 ITimestampBased::msecsTo(const ITimestampBased &otherTimestampObj) const
79  {
80  return otherTimestampObj.m_timestampMSecsSinceEpoch - m_timestampMSecsSinceEpoch;
81  }
82 
83  qint64 ITimestampBased::absMsecsTo(const ITimestampBased &otherTimestampObj) const
84  {
85  qint64 dt = this->msecsTo(otherTimestampObj);
86  return dt > 0 ? dt : dt * -1;
87  }
88 
90  {
91  if (m_timestampMSecsSinceEpoch < 0) return QDateTime::currentMSecsSinceEpoch();
92  return QDateTime::currentMSecsSinceEpoch() - m_timestampMSecsSinceEpoch;
93  }
94 
95  void ITimestampBased::setCurrentUtcTime() { m_timestampMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); }
96 
98 
100  {
101  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("MM-dd hh:mm:ss") : "";
102  }
103 
105  {
106  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("MM-dd hh:mm:ss.zzz") : "";
107  }
108 
110  {
111  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("dd hh:mm:ss") : "";
112  }
113 
115  {
116  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("hh:mm:ss") : "";
117  }
118 
120  {
121  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("hh:mm:ss.zzz") : "";
122  }
123 
125  {
126  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("hh::mm") : "";
127  }
128 
130  {
131  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("yyyy-MM-dd HH:mm:ss") : "";
132  }
133 
135  {
136  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("yyyy-MM-dd HH:mm:ss.zzz") : "";
137  }
138 
140 
142  {
143  return (index >= static_cast<int>(IndexUtcTimestamp)) && (index <= static_cast<int>(IndexMSecsSinceEpoch));
144  }
145 
147  {
148  if (index.isEmpty()) { return false; }
149  const int i = index.frontCasted<int>();
150  return isAnyTimestampIndex(i);
151  }
152 
154  {
155  if (!index.isEmpty())
156  {
157  const ColumnIndex i = index.frontCasted<ColumnIndex>();
158  switch (i)
159  {
160  case IndexUtcTimestamp: return QVariant::fromValue(this->getUtcTimestamp());
161  case IndexMSecsSinceEpoch: return QVariant::fromValue(this->getMSecsSinceEpoch());
162  case IndexUtcTimestampFormattedDhms: return QVariant::fromValue(this->getFormattedUtcTimestampDhms());
163  case IndexUtcTimestampFormattedHm: return QVariant::fromValue(this->getFormattedUtcTimestampHm());
164  case IndexUtcTimestampFormattedHms: return QVariant::fromValue(this->getFormattedUtcTimestampHms());
165  case IndexUtcTimestampFormattedYmdhms: return QVariant::fromValue(this->getFormattedUtcTimestampYmdhms());
166  case IndexUtcTimestampFormattedYmdhmsz: return QVariant::fromValue(this->getFormattedUtcTimestampYmdhmsz());
167  case IndexUtcTimestampFormattedMdhms: return QVariant::fromValue(this->getFormattedUtcTimestampMdhms());
168  case IndexUtcTimestampFormattedMdhmsz: return QVariant::fromValue(this->getFormattedUtcTimestampMdhmsz());
169  default: break;
170  }
171  }
172  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
173  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
174  return QVariant::fromValue(m);
175  }
176 
177  void ITimestampBased::setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
178  {
179  if (!index.isEmpty())
180  {
181  const ColumnIndex i = index.frontCasted<ColumnIndex>();
182  switch (i)
183  {
184  case IndexUtcTimestamp: this->setUtcTimestamp(variant.toDateTime()); return;
185  case IndexMSecsSinceEpoch: this->setMSecsSinceEpoch(variant.toLongLong()); return;
186  case IndexUtcTimestampFormattedYmdhms:
187  case IndexUtcTimestampFormattedYmdhmsz:
188  case IndexUtcTimestampFormattedHm:
189  case IndexUtcTimestampFormattedHms:
190  case IndexUtcTimestampFormattedDhms:
191  {
192  const QDateTime dt = fromStringUtc(variant.toString());
193  m_timestampMSecsSinceEpoch = dt.toMSecsSinceEpoch();
194  }
195  return;
196  default: break;
197  }
198  }
199  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
200  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
201  }
202 
204  {
205  Q_UNUSED(index);
206  return Compare::compare(m_timestampMSecsSinceEpoch, compareValue.m_timestampMSecsSinceEpoch);
207  }
208 
210  {
212  }
213 
215  {
216  static const QString ts("%1 (%2)");
217  if (!this->hasValidTimestamp()) { return ts.arg("-", this->getTimeOffsetWithUnit()); }
218  if (formatted) { return ts.arg(this->getFormattedUtcTimestampHms(), this->getTimeOffsetWithUnit()); }
219  return ts.arg(m_timeOffsetMs).arg(this->getTimeOffsetWithUnit());
220  }
221 
222  QString ITimestampWithOffsetBased::getFormattedTimestampAndOffset(bool includeRawTimestamp) const
223  {
224  if (!includeRawTimestamp) { return this->getTimestampAndOffset(true); }
225  static const QString ts("%1/%2 (%3)");
226  if (!this->hasValidTimestamp()) { return ts.arg("-", "-", this->getTimeOffsetWithUnit()); }
227  return ts.arg(this->getFormattedUtcTimestampHmsz())
229  .arg(this->getTimeOffsetWithUnit());
230  }
231 
233  {
234  return this->getAdjustedMSecsSinceEpoch() > otherTimestampObj.getAdjustedMSecsSinceEpoch();
235  }
236 
237  bool ITimestampWithOffsetBased::isNewerThanAdjusted(qint64 mSecsSinceEpoch) const
238  {
239  return this->getAdjustedMSecsSinceEpoch() > mSecsSinceEpoch;
240  }
241 
243  {
244  return this->getAdjustedMSecsSinceEpoch() < otherTimestampObj.getAdjustedMSecsSinceEpoch();
245  }
246 
247  bool ITimestampWithOffsetBased::isOlderThanAdjusted(qint64 mSecsSinceEpoch) const
248  {
249  return this->getAdjustedMSecsSinceEpoch() < mSecsSinceEpoch;
250  }
251 
253  {
254  if (ITimestampBased::canHandleIndex(index)) { return true; }
255  if (index.isEmpty()) { return false; }
256  const int i = index.frontCasted<int>();
257  return (i >= static_cast<int>(IndexOffsetMs)) && (i <= static_cast<int>(IndexOffsetWithUnit));
258  }
259 
261 
263 
265  {
266  return QStringLiteral("%1ms").arg(this->getTimeOffsetMs());
267  }
268 
270  {
272  if (!index.isEmpty())
273  {
274  const ColumnIndex i = index.frontCasted<ColumnIndex>();
275  switch (i)
276  {
277  case IndexOffsetMs:
278  {
279  return QVariant::fromValue(m_timeOffsetMs);
280  }
281  case IndexAdjustedMsWithOffset:
282  {
283  return QVariant::fromValue(this->getAdjustedMSecsSinceEpoch());
284  }
285  case IndexOffsetWithUnit:
286  {
287  return QVariant::fromValue(this->getTimeOffsetWithUnit());
288  }
289  default: break;
290  }
291  }
292  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
293  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
294  return QVariant();
295  }
296 
298  {
300  {
301  ITimestampBased::setPropertyByIndex(index, variant);
302  return;
303  }
304  if (!index.isEmpty())
305  {
306  const ColumnIndex i = index.frontCasted<ColumnIndex>();
307  switch (i)
308  {
309  case IndexOffsetMs:
310  {
311  m_timeOffsetMs = variant.value<qint64>();
312  return;
313  }
314  case IndexAdjustedMsWithOffset: return; // read only
315  case IndexOffsetWithUnit: return; // read only
316  default: break;
317  }
318  }
319  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
320  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
321  }
322 
324  const ITimestampWithOffsetBased &compareValue) const
325  {
327  {
328  return ITimestampBased::comparePropertyByIndex(index, compareValue);
329  }
330  if (!index.isEmpty())
331  {
332  const ColumnIndex i = index.frontCasted<ColumnIndex>();
333  switch (i)
334  {
335  case IndexOffsetWithUnit:
336  case IndexOffsetMs:
337  {
338  return Compare::compare(m_timeOffsetMs, compareValue.m_timeOffsetMs);
339  }
340  case IndexAdjustedMsWithOffset:
341  {
342  return Compare::compare(this->getAdjustedMSecsSinceEpoch(), compareValue.getAdjustedMSecsSinceEpoch());
343  }
344  default: break;
345  }
346  }
347  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
348  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
349  return 0;
350  }
351 } // namespace swift::misc
Non-owning reference to a CPropertyIndex with a subset of its features.
QString toQString(bool i18n=false) const
Cast as QString.
CastType frontCasted() const
First element casted to given type, usually the PropertIndex enum.
Entity with timestamp.
qint64 getMSecsSinceEpoch() const
Timestamp as ms value.
bool isNewerThan(const ITimestampBased &otherTimestampObj) const
Is this newer than other?
bool isOlderThanNowMinusOffset(int offsetMs) const
Older than now-offset.
static bool isAnyTimestampIndex(int index)
Any of the timestamp indexes.
void updateMissingParts(const ITimestampBased &other)
Update missing parts.
void setTimestampToNull()
Set to null.
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
int comparePropertyByIndex(CPropertyIndexRef index, const ITimestampBased &compareValue) const
Compare for index.
QString getFormattedUtcTimestampYmdhms() const
As yyyy MM dd HH mm ss.
void setByYearMonthDayHourMinute(const QString &yyyyMMddhhmmss)
Set by value such as "20141003231045".
static bool canHandleIndex(CPropertyIndexRef index)
Can given index be handled.
QString getFormattedUtcTimestampHmsz() const
As hh:mm:ss.zzz.
qint64 m_timestampMSecsSinceEpoch
timestamp value
void setCurrentUtcTime()
Set the current time as timestamp.
QString getFormattedUtcTimestampHm() const
As hh:mm.
QDateTime getUtcTimestamp() const
Get timestamp.
bool isOlderThan(const ITimestampBased &otherTimestampObj) const
Is this older than other?
QString getFormattedUtcTimestampHms() const
As hh:mm:ss.
ColumnIndex
Properties by index.
qint64 msecsToNow() const
Milliseconds to now.
bool isSame(const ITimestampBased &otherTimestampObj) const
Same timestamp.
QString getFormattedUtcTimestampMdhms() const
As MM dd HH mm ss.
QString getFormattedUtcTimestampDhms() const
As dd HH mm ss.
void setUtcTimestamp(const QDateTime &timestamp)
Set timestamp.
bool hasValidTimestamp() const
Valid timestamp?
qint64 msecsTo(const ITimestampBased &otherTimestampObj) const
Time difference.
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
QString getFormattedUtcTimestampYmdhmsz() const
As yyyy MM dd HH mm ss.zzz.
qint64 absMsecsTo(const ITimestampBased &otherTimestampObj) const
Time difference.
QString getFormattedUtcTimestampMdhmsz() const
As MM dd HH mm ss.zzz.
void setMSecsSinceEpoch(qint64 mSecsSinceEpoch)
Timestamp as ms value.
void addMsecs(qint64 ms)
Add the given number of milliseconds to the timestamp.
qint64 getAdjustedMSecsSinceEpoch() const
Timestamp with offset added for interpolation.
static bool canHandleIndex(CPropertyIndexRef index)
Can given index be handled.
QVariant propertyByIndex(swift::misc::CPropertyIndexRef index) const
Property by index.
QString getTimeOffsetWithUnit() const
Offset with unit.
qint64 getTimeOffsetMs() const
Milliseconds to add to timestamp for interpolation.
int comparePropertyByIndex(CPropertyIndexRef index, const ITimestampWithOffsetBased &compareValue) const
Compare for index.
qint64 m_timeOffsetMs
offset time in ms
bool hasNonZeroOffsetTime() const
Having a valid offset time.
void setPropertyByIndex(swift::misc::CPropertyIndexRef index, const QVariant &variant)
Set property by index.
bool isNewerThanAdjusted(const ITimestampWithOffsetBased &otherTimestampObj) const
Is this newer than other?
QString getTimestampAndOffset(bool formatted) const
Timestamp and offset.
bool isOlderThanAdjusted(const ITimestampWithOffsetBased &otherTimestampObj) const
Is this older than other?
void addMsecsToOffsetTime(qint64 msToAdd)
Adds a value to offset time.
QString getFormattedTimestampAndOffset(bool includeRawTimestamp) const
Timestamp and offset.
Free functions in swift::misc.
SWIFT_MISC_EXPORT QString removeDateTimeSeparators(const QString &s)
Remove the typical separators such as "-", " ".
SWIFT_MISC_EXPORT QDateTime fromStringUtc(const QString &dateTimeString, const QString &format)
Same as QDateTime::fromString but QDateTime will be set to UTC.
SWIFT_MISC_EXPORT QDateTime parseDateTimeStringOptimized(const QString &dateTimeString)
Parse yyyyMMddHHmmsszzz strings optimized.
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26