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 {
15  ITimestampBased::ITimestampBased(qint64 msSincePoch) : m_timestampMSecsSinceEpoch(msSincePoch) {}
16 
18  : m_timestampMSecsSinceEpoch(timestamp.toMSecsSinceEpoch())
19  {}
20 
22  {
23  if (m_timestampMSecsSinceEpoch < 0) { return {}; }
25  }
26 
28 
30  {
31  // yyyy MM dd hh mm ss zzz
32  // 0123 45 67 89 01 23 456
33  // 1234 56 78 90 12 34 567
34 
35  const QString s(removeDateTimeSeparators(yyyyMMddhhmmsszzz));
37  this->setUtcTimestamp(dt);
38  }
39 
41  {
42  m_timestampMSecsSinceEpoch = timestamp.isValid() ? timestamp.toMSecsSinceEpoch() : -1;
43  }
44 
45  bool ITimestampBased::isNewerThan(const ITimestampBased &otherTimestampObj) const
46  {
47  return m_timestampMSecsSinceEpoch > otherTimestampObj.m_timestampMSecsSinceEpoch;
48  }
49 
50  bool ITimestampBased::isNewerThan(qint64 mSecsSinceEpoch) const
51  {
52  return m_timestampMSecsSinceEpoch > mSecsSinceEpoch;
53  }
54 
55  bool ITimestampBased::isOlderThan(const ITimestampBased &otherTimestampObj) const
56  {
57  return m_timestampMSecsSinceEpoch < otherTimestampObj.m_timestampMSecsSinceEpoch;
58  }
59 
60  bool ITimestampBased::isOlderThan(qint64 mSecsSinceEpoch) const
61  {
62  return m_timestampMSecsSinceEpoch < mSecsSinceEpoch;
63  }
64 
66  {
67  if (offsetMs <= 0) { return false; }
69  }
70 
71  bool ITimestampBased::isSame(const ITimestampBased &otherTimestampObj) const
72  {
73  return m_timestampMSecsSinceEpoch == otherTimestampObj.m_timestampMSecsSinceEpoch;
74  }
75 
76  qint64 ITimestampBased::msecsTo(const ITimestampBased &otherTimestampObj) const
77  {
78  return otherTimestampObj.m_timestampMSecsSinceEpoch - m_timestampMSecsSinceEpoch;
79  }
80 
81  qint64 ITimestampBased::absMsecsTo(const ITimestampBased &otherTimestampObj) const
82  {
83  qint64 dt = this->msecsTo(otherTimestampObj);
84  return dt > 0 ? dt : dt * -1;
85  }
86 
88  {
91  }
92 
94 
96 
98  {
99  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("MM-dd hh:mm:ss") : "";
100  }
101 
103  {
104  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("MM-dd hh:mm:ss.zzz") : "";
105  }
106 
108  {
109  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("dd hh:mm:ss") : "";
110  }
111 
113  {
114  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("hh:mm:ss") : "";
115  }
116 
118  {
119  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("hh:mm:ss.zzz") : "";
120  }
121 
123  {
124  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("hh::mm") : "";
125  }
126 
128  {
129  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("yyyy-MM-dd HH:mm:ss") : "";
130  }
131 
133  {
134  return this->hasValidTimestamp() ? this->getUtcTimestamp().toString("yyyy-MM-dd HH:mm:ss.zzz") : "";
135  }
136 
138 
140  {
141  return (index >= static_cast<int>(IndexUtcTimestamp)) && (index <= static_cast<int>(IndexMSecsSinceEpoch));
142  }
143 
145  {
146  if (index.isEmpty()) { return false; }
147  const int i = index.frontCasted<int>();
148  return isAnyTimestampIndex(i);
149  }
150 
152  {
153  if (!index.isEmpty())
154  {
155  const auto i = index.frontCasted<ColumnIndex>();
156  switch (i)
157  {
158  case IndexUtcTimestamp: return QVariant::fromValue(this->getUtcTimestamp());
159  case IndexMSecsSinceEpoch: return QVariant::fromValue(this->getMSecsSinceEpoch());
160  case IndexUtcTimestampFormattedDhms: return QVariant::fromValue(this->getFormattedUtcTimestampDhms());
161  case IndexUtcTimestampFormattedHm: return QVariant::fromValue(this->getFormattedUtcTimestampHm());
162  case IndexUtcTimestampFormattedHms: return QVariant::fromValue(this->getFormattedUtcTimestampHms());
163  case IndexUtcTimestampFormattedYmdhms: return QVariant::fromValue(this->getFormattedUtcTimestampYmdhms());
164  case IndexUtcTimestampFormattedYmdhmsz: return QVariant::fromValue(this->getFormattedUtcTimestampYmdhmsz());
165  case IndexUtcTimestampFormattedMdhms: return QVariant::fromValue(this->getFormattedUtcTimestampMdhms());
166  case IndexUtcTimestampFormattedMdhmsz: return QVariant::fromValue(this->getFormattedUtcTimestampMdhmsz());
167  default: break;
168  }
169  }
170  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
171  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
172  return QVariant::fromValue(m);
173  }
174 
176  {
177  if (!index.isEmpty())
178  {
179  const auto i = index.frontCasted<ColumnIndex>();
180  switch (i)
181  {
182  case IndexUtcTimestamp: this->setUtcTimestamp(variant.toDateTime()); return;
183  case IndexMSecsSinceEpoch: this->setMSecsSinceEpoch(variant.toLongLong()); return;
184  case IndexUtcTimestampFormattedYmdhms:
185  case IndexUtcTimestampFormattedYmdhmsz:
186  case IndexUtcTimestampFormattedHm:
187  case IndexUtcTimestampFormattedHms:
188  case IndexUtcTimestampFormattedDhms:
189  {
190  const QDateTime dt = fromStringUtc(variant.toString());
192  }
193  return;
194  default: break;
195  }
196  }
197  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
198  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
199  }
200 
202  {
203  Q_UNUSED(index);
204  return Compare::compare(m_timestampMSecsSinceEpoch, compareValue.m_timestampMSecsSinceEpoch);
205  }
206 
208  {
210  }
211 
213  {
214  static const QString ts("%1 (%2)");
215  if (!this->hasValidTimestamp()) { return ts.arg("-", this->getTimeOffsetWithUnit()); }
216  if (formatted) { return ts.arg(this->getFormattedUtcTimestampHms(), this->getTimeOffsetWithUnit()); }
217  return ts.arg(m_timeOffsetMs).arg(this->getTimeOffsetWithUnit());
218  }
219 
221  {
222  if (!includeRawTimestamp) { return this->getTimestampAndOffset(true); }
223  static const QString ts("%1/%2 (%3)");
224  if (!this->hasValidTimestamp()) { return ts.arg("-", "-", this->getTimeOffsetWithUnit()); }
225  return ts.arg(this->getFormattedUtcTimestampHmsz())
227  .arg(this->getTimeOffsetWithUnit());
228  }
229 
231  {
232  return this->getAdjustedMSecsSinceEpoch() > otherTimestampObj.getAdjustedMSecsSinceEpoch();
233  }
234 
235  bool ITimestampWithOffsetBased::isNewerThanAdjusted(qint64 mSecsSinceEpoch) const
236  {
237  return this->getAdjustedMSecsSinceEpoch() > mSecsSinceEpoch;
238  }
239 
241  {
242  return this->getAdjustedMSecsSinceEpoch() < otherTimestampObj.getAdjustedMSecsSinceEpoch();
243  }
244 
245  bool ITimestampWithOffsetBased::isOlderThanAdjusted(qint64 mSecsSinceEpoch) const
246  {
247  return this->getAdjustedMSecsSinceEpoch() < mSecsSinceEpoch;
248  }
249 
251  {
252  if (ITimestampBased::canHandleIndex(index)) { return true; }
253  if (index.isEmpty()) { return false; }
254  const int i = index.frontCasted<int>();
255  return (i >= static_cast<int>(IndexOffsetMs)) && (i <= static_cast<int>(IndexOffsetWithUnit));
256  }
257 
259 
261 
263  {
264  return QStringLiteral("%1ms").arg(this->getTimeOffsetMs());
265  }
266 
268  {
270  if (!index.isEmpty())
271  {
272  const auto i = index.frontCasted<ColumnIndex>();
273  switch (i)
274  {
275  case IndexOffsetMs:
276  {
278  }
279  case IndexAdjustedMsWithOffset:
280  {
282  }
283  case IndexOffsetWithUnit:
284  {
286  }
287  default: break;
288  }
289  }
290  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
291  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
292  return {};
293  }
294 
296  {
298  {
299  ITimestampBased::setPropertyByIndex(index, variant);
300  return;
301  }
302  if (!index.isEmpty())
303  {
304  const auto i = index.frontCasted<ColumnIndex>();
305  switch (i)
306  {
307  case IndexOffsetMs:
308  {
309  m_timeOffsetMs = variant.value<qint64>();
310  return;
311  }
312  case IndexAdjustedMsWithOffset: return; // read only
313  case IndexOffsetWithUnit: return; // read only
314  default: break;
315  }
316  }
317  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
318  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
319  }
320 
322  const ITimestampWithOffsetBased &compareValue) const
323  {
325  {
326  return ITimestampBased::comparePropertyByIndex(index, compareValue);
327  }
328  if (!index.isEmpty())
329  {
330  const auto i = index.frontCasted<ColumnIndex>();
331  switch (i)
332  {
333  case IndexOffsetWithUnit:
334  case IndexOffsetMs:
335  {
336  return Compare::compare(m_timeOffsetMs, compareValue.m_timeOffsetMs);
337  }
338  case IndexAdjustedMsWithOffset:
339  {
340  return Compare::compare(this->getAdjustedMSecsSinceEpoch(), compareValue.getAdjustedMSecsSinceEpoch());
341  }
342  default: break;
343  }
344  }
345  const QString m = QStringLiteral("Cannot handle index %1").arg(index.toQString());
346  SWIFT_VERIFY_X(false, Q_FUNC_INFO, qUtf8Printable(m));
347  return 0;
348  }
349 } // 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.
ITimestampBased()=default
Constructor.
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.
qint64 currentMSecsSinceEpoch()
QDateTime fromMSecsSinceEpoch(qint64 msecs)
bool isValid() const const
qint64 toMSecsSinceEpoch() const const
QString toString(QStringView format) const const
QString arg(Args &&... args) const const
QVariant fromValue(T &&value)
QDateTime toDateTime() const const
qlonglong toLongLong(bool *ok) const const
QString toString() const const
T value() const &const
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26