From 85c60b810d83b87749b4aa8014236a195f5a57a9 Mon Sep 17 00:00:00 2001 From: Karthik Nishanth Date: Tue, 2 Oct 2018 21:42:32 +0530 Subject: [PATCH 1/6] Complete TODO : Show more user friendly labels --- src/libs/ui/docsetsdialog.cpp | 10 ++-- src/libs/util/CMakeLists.txt | 1 + src/libs/util/readableinterval.cpp | 80 ++++++++++++++++++++++++++++++ src/libs/util/readableinterval.h | 68 +++++++++++++++++++++++++ 4 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/libs/util/readableinterval.cpp create mode 100644 src/libs/util/readableinterval.h diff --git a/src/libs/ui/docsetsdialog.cpp b/src/libs/ui/docsetsdialog.cpp index 56fcb8050..560ffb6f0 100644 --- a/src/libs/ui/docsetsdialog.cpp +++ b/src/libs/ui/docsetsdialog.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ using namespace Zeal; using namespace Zeal::WidgetUi; +using namespace Zeal::Util; #ifdef Q_OS_WIN32 extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; @@ -311,8 +313,8 @@ void DocsetsDialog::downloadCompleted() if (file->open(QIODevice::WriteOnly)) file->write(data); - ui->lastUpdatedLabel->setText(QFileInfo(file->fileName()) - .lastModified().toString(Qt::SystemLocaleShortDate)); + ReadableInterval lastModifiedInterval(QFileInfo(file->fileName()).lastModified()); + ui->lastUpdatedLabel->setText(lastModifiedInterval.toReadableString()); QJsonParseError jsonError; const QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); @@ -518,8 +520,8 @@ void DocsetsDialog::loadDocsetList() return; } - // TODO: Show more user friendly labels, like "5 hours ago" - ui->lastUpdatedLabel->setText(fi.lastModified().toString(Qt::SystemLocaleShortDate)); + ReadableInterval lastModifiedInterval(fi.lastModified()); + ui->lastUpdatedLabel->setText(lastModifiedInterval.toReadableString()); processDocsetList(jsonDoc.array()); } diff --git a/src/libs/util/CMakeLists.txt b/src/libs/util/CMakeLists.txt index d4ab871b3..a7ef562f6 100644 --- a/src/libs/util/CMakeLists.txt +++ b/src/libs/util/CMakeLists.txt @@ -4,6 +4,7 @@ set(CMAKE_AUTOMOC OFF) add_library(Util plist.cpp sqlitedatabase.cpp + readableinterval.cpp version.cpp ) diff --git a/src/libs/util/readableinterval.cpp b/src/libs/util/readableinterval.cpp new file mode 100644 index 000000000..0072640d3 --- /dev/null +++ b/src/libs/util/readableinterval.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015-2018 Oleg Shparber +** Copyright (C) 2013-2014 Jerzy Kozera +** Contact: https://go.zealdocs.org/l/contact +** +** This file is part of Zeal. +** +** Zeal is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** Zeal is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Zeal. If not, see . +** +****************************************************************************/ + +#include "readableinterval.h" + +#include +#include + +using namespace Zeal::Util; + +ReadableInterval::ReadableInterval(QDateTime timestamp, QDateTime reference) : + m_timestamp(timestamp), + m_reference(reference) +{ + m_delta = m_reference.toSecsSinceEpoch() - m_timestamp.toSecsSinceEpoch(); +} + +ReadableInterval::ReadableInterval(QDateTime timestamp) : + m_timestamp(timestamp) +{ + m_reference = QDateTime::currentDateTime(); + m_delta = m_reference.toSecsSinceEpoch() - m_timestamp.toSecsSinceEpoch(); +} + +QString ReadableInterval::pluralForm(QString word, qint64 quantity) +{ + return word + (quantity > 1 ? "s" : ""); +} + +void ReadableInterval::computeDateTimeComponents() +{ + m_isPast = m_delta > 0; + m_year = m_delta / SECONDSPERYEAR; + m_day = (m_delta % SECONDSPERYEAR) / SECONDSPERDAY; + m_hour = ((m_delta % SECONDSPERYEAR) % SECONDSPERDAY) / SECONDSPERHOUR; + m_min = (((m_delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) / SECONDSPERMINUTE; + m_sec = (((m_delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) % SECONDSPERMINUTE; +} + +QString ReadableInterval::toReadableString() +{ + if (m_delta == 0) + return ZERO_INTERVAL_STRING; + else { + QStringList list; + qint8 fieldCount = 0; + computeDateTimeComponents(); + if (m_year && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(m_year).arg(pluralForm(YEAR, m_year))); + if (m_day && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(m_day).arg(pluralForm(DAY, m_day))); + if (m_hour && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(m_hour).arg(pluralForm(HOUR, m_hour))); + if (m_min && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(m_min).arg(pluralForm(MIN, m_min))); + if (m_sec && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(m_sec).arg(pluralForm(SEC, m_sec))); + return QStringLiteral("%1 %2").arg(list.join(JOIN_SEQ)).arg(m_isPast ? PAST_INTERVAL_STRING : FUTURE_INTERVAL_STRING); + } +} diff --git a/src/libs/util/readableinterval.h b/src/libs/util/readableinterval.h new file mode 100644 index 000000000..131fc8d16 --- /dev/null +++ b/src/libs/util/readableinterval.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015-2018 Oleg Shparber +** Contact: https://go.zealdocs.org/l/contact +** +** This file is part of Zeal. +** +** Zeal is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** Zeal is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Zeal. If not, see . +** +****************************************************************************/ + +#ifndef ZEAL_UTIL_READABLEINTERVAL_H +#define ZEAL_UTIL_READABLEINTERVAL_H + +#include + +namespace Zeal { +namespace Util { + +class ReadableInterval +{ +public: + ReadableInterval(QDateTime timestamp, QDateTime reference); + ReadableInterval(QDateTime timestamp); + + QString toReadableString(); + +private: + void computeDateTimeComponents(); + QString pluralForm(QString word, qint64 quantity); + + QDateTime m_timestamp, m_reference; + qint64 m_delta, m_year, m_day, m_hour, m_min, m_sec; + bool m_isPast; + + const qint16 SECONDSPERMINUTE = 60; + const qint16 SECONDSPERHOUR = SECONDSPERMINUTE * 60; + const qint32 SECONDSPERDAY = SECONDSPERHOUR * 24; + const qint32 SECONDSPERYEAR = SECONDSPERDAY * 365; + + const qint8 MAX_FIELDS_DISPLAYED = 3; + + QString ZERO_INTERVAL_STRING = "now"; + QString PAST_INTERVAL_STRING = "ago"; + QString FUTURE_INTERVAL_STRING = "from now"; + QString YEAR = "Year"; + QString DAY = "Day"; + QString HOUR = "Hour"; + QString MIN = "Minute"; + QString SEC = "Second"; + QString JOIN_SEQ= ", "; +}; + +} // namespace Util +} // namespace Zeal + +#endif // ZEAL_UTIL_READABLEINTERVAL_H From 7d4e43c198cf01b30bde9e02c8c99fea4b82d11b Mon Sep 17 00:00:00 2001 From: Karthik Nishanth Date: Mon, 15 Oct 2018 18:46:52 +0530 Subject: [PATCH 2/6] Refactor ReadableInterval, fix clang-tidy warnings --- src/libs/ui/docsetsdialog.cpp | 6 +-- src/libs/util/readableinterval.cpp | 81 ++++++++++++++++-------------- src/libs/util/readableinterval.h | 29 +---------- 3 files changed, 48 insertions(+), 68 deletions(-) diff --git a/src/libs/ui/docsetsdialog.cpp b/src/libs/ui/docsetsdialog.cpp index 560ffb6f0..d868dd67e 100644 --- a/src/libs/ui/docsetsdialog.cpp +++ b/src/libs/ui/docsetsdialog.cpp @@ -313,8 +313,7 @@ void DocsetsDialog::downloadCompleted() if (file->open(QIODevice::WriteOnly)) file->write(data); - ReadableInterval lastModifiedInterval(QFileInfo(file->fileName()).lastModified()); - ui->lastUpdatedLabel->setText(lastModifiedInterval.toReadableString()); + ui->lastUpdatedLabel->setText(ReadableInterval::toReadableString(QFileInfo(file->fileName()).lastModified())); QJsonParseError jsonError; const QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); @@ -520,8 +519,7 @@ void DocsetsDialog::loadDocsetList() return; } - ReadableInterval lastModifiedInterval(fi.lastModified()); - ui->lastUpdatedLabel->setText(lastModifiedInterval.toReadableString()); + ui->lastUpdatedLabel->setText(ReadableInterval::toReadableString(fi.lastModified())); processDocsetList(jsonDoc.array()); } diff --git a/src/libs/util/readableinterval.cpp b/src/libs/util/readableinterval.cpp index 0072640d3..8e4f67597 100644 --- a/src/libs/util/readableinterval.cpp +++ b/src/libs/util/readableinterval.cpp @@ -28,53 +28,60 @@ using namespace Zeal::Util; -ReadableInterval::ReadableInterval(QDateTime timestamp, QDateTime reference) : - m_timestamp(timestamp), - m_reference(reference) -{ - m_delta = m_reference.toSecsSinceEpoch() - m_timestamp.toSecsSinceEpoch(); -} +namespace { +const qint16 SECONDSPERMINUTE = 60; +const qint16 SECONDSPERHOUR = SECONDSPERMINUTE * 60; +const qint32 SECONDSPERDAY = SECONDSPERHOUR * 24; +const qint32 SECONDSPERYEAR = SECONDSPERDAY * 365; -ReadableInterval::ReadableInterval(QDateTime timestamp) : - m_timestamp(timestamp) -{ - m_reference = QDateTime::currentDateTime(); - m_delta = m_reference.toSecsSinceEpoch() - m_timestamp.toSecsSinceEpoch(); +const qint8 MAX_FIELDS_DISPLAYED = 3; + +const QString ZERO_INTERVAL_STRING = "now"; +const QString PAST_INTERVAL_STRING = "ago"; +const QString FUTURE_INTERVAL_STRING = "from now"; +const QString YEAR = "Year"; +const QString DAY = "Day"; +const QString HOUR = "Hour"; +const QString MIN = "Minute"; +const QString SEC = "Second"; +const QString JOIN_SEQ= ", "; } -QString ReadableInterval::pluralForm(QString word, qint64 quantity) +QString ReadableInterval::pluralForm(const QString &word, qint64 quantity) { return word + (quantity > 1 ? "s" : ""); } -void ReadableInterval::computeDateTimeComponents() +QString ReadableInterval::toReadableString(const QDateTime& timestamp, const QDateTime& reference) { - m_isPast = m_delta > 0; - m_year = m_delta / SECONDSPERYEAR; - m_day = (m_delta % SECONDSPERYEAR) / SECONDSPERDAY; - m_hour = ((m_delta % SECONDSPERYEAR) % SECONDSPERDAY) / SECONDSPERHOUR; - m_min = (((m_delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) / SECONDSPERMINUTE; - m_sec = (((m_delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) % SECONDSPERMINUTE; -} + qint64 delta, year, day, hour, min, sec; + bool isPast; -QString ReadableInterval::toReadableString() -{ - if (m_delta == 0) - return ZERO_INTERVAL_STRING; - else { + delta = reference.toSecsSinceEpoch() - timestamp.toSecsSinceEpoch(); + + if (delta) { QStringList list; qint8 fieldCount = 0; - computeDateTimeComponents(); - if (m_year && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(m_year).arg(pluralForm(YEAR, m_year))); - if (m_day && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(m_day).arg(pluralForm(DAY, m_day))); - if (m_hour && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(m_hour).arg(pluralForm(HOUR, m_hour))); - if (m_min && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(m_min).arg(pluralForm(MIN, m_min))); - if (m_sec && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(m_sec).arg(pluralForm(SEC, m_sec))); - return QStringLiteral("%1 %2").arg(list.join(JOIN_SEQ)).arg(m_isPast ? PAST_INTERVAL_STRING : FUTURE_INTERVAL_STRING); + + isPast = delta > 0; + year = delta / SECONDSPERYEAR; + day = (delta % SECONDSPERYEAR) / SECONDSPERDAY; + hour = ((delta % SECONDSPERYEAR) % SECONDSPERDAY) / SECONDSPERHOUR; + min = (((delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) / SECONDSPERMINUTE; + sec = (((delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) % SECONDSPERMINUTE; + + if (year && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(year).arg(ReadableInterval::pluralForm(YEAR, year))); + if (day && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(day).arg(ReadableInterval::pluralForm(DAY, day))); + if (hour && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(hour).arg(ReadableInterval::pluralForm(HOUR, hour))); + if (min && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(min).arg(ReadableInterval::pluralForm(MIN, min))); + if (sec && ++fieldCount <= MAX_FIELDS_DISPLAYED) + list.append(QStringLiteral("%1 %2").arg(sec).arg(ReadableInterval::pluralForm(SEC, sec))); + return QStringLiteral("%1 %2").arg(list.join(JOIN_SEQ), isPast ? PAST_INTERVAL_STRING : FUTURE_INTERVAL_STRING); + } else { + return ZERO_INTERVAL_STRING; } } diff --git a/src/libs/util/readableinterval.h b/src/libs/util/readableinterval.h index 131fc8d16..73b882cdb 100644 --- a/src/libs/util/readableinterval.h +++ b/src/libs/util/readableinterval.h @@ -31,35 +31,10 @@ namespace Util { class ReadableInterval { public: - ReadableInterval(QDateTime timestamp, QDateTime reference); - ReadableInterval(QDateTime timestamp); - - QString toReadableString(); + static QString toReadableString(const QDateTime& timestamp, const QDateTime& reference = QDateTime::currentDateTime()); private: - void computeDateTimeComponents(); - QString pluralForm(QString word, qint64 quantity); - - QDateTime m_timestamp, m_reference; - qint64 m_delta, m_year, m_day, m_hour, m_min, m_sec; - bool m_isPast; - - const qint16 SECONDSPERMINUTE = 60; - const qint16 SECONDSPERHOUR = SECONDSPERMINUTE * 60; - const qint32 SECONDSPERDAY = SECONDSPERHOUR * 24; - const qint32 SECONDSPERYEAR = SECONDSPERDAY * 365; - - const qint8 MAX_FIELDS_DISPLAYED = 3; - - QString ZERO_INTERVAL_STRING = "now"; - QString PAST_INTERVAL_STRING = "ago"; - QString FUTURE_INTERVAL_STRING = "from now"; - QString YEAR = "Year"; - QString DAY = "Day"; - QString HOUR = "Hour"; - QString MIN = "Minute"; - QString SEC = "Second"; - QString JOIN_SEQ= ", "; + static QString pluralForm(const QString& word, qint64 quantity); }; } // namespace Util From fbe812649d6c66ec2b18d3d208f1425a8f1ca765 Mon Sep 17 00:00:00 2001 From: Karthik Nishanth Date: Tue, 16 Oct 2018 20:39:17 +0530 Subject: [PATCH 3/6] Refactor ReadableInterval : Add tr, fix more bugs --- src/libs/util/readableinterval.cpp | 76 +++++++++++++----------------- src/libs/util/readableinterval.h | 27 ++++++++++- 2 files changed, 58 insertions(+), 45 deletions(-) diff --git a/src/libs/util/readableinterval.cpp b/src/libs/util/readableinterval.cpp index 8e4f67597..86373acaf 100644 --- a/src/libs/util/readableinterval.cpp +++ b/src/libs/util/readableinterval.cpp @@ -23,65 +23,55 @@ #include "readableinterval.h" -#include +#include #include using namespace Zeal::Util; -namespace { -const qint16 SECONDSPERMINUTE = 60; -const qint16 SECONDSPERHOUR = SECONDSPERMINUTE * 60; -const qint32 SECONDSPERDAY = SECONDSPERHOUR * 24; -const qint32 SECONDSPERYEAR = SECONDSPERDAY * 365; - -const qint8 MAX_FIELDS_DISPLAYED = 3; - -const QString ZERO_INTERVAL_STRING = "now"; -const QString PAST_INTERVAL_STRING = "ago"; -const QString FUTURE_INTERVAL_STRING = "from now"; -const QString YEAR = "Year"; -const QString DAY = "Day"; -const QString HOUR = "Hour"; -const QString MIN = "Minute"; -const QString SEC = "Second"; -const QString JOIN_SEQ= ", "; +const char* ReadableInterval::describeTimeUnit(TIME_UNITS unit) +{ + switch (unit) { + case YEAR: return QT_TR_NOOP("%n year(s)"); + case DAY: return QT_TR_NOOP("%n day(s)"); + case HOUR: return QT_TR_NOOP("%n hour(s)"); + case MIN: return QT_TR_NOOP("%n min(s)"); + case SEC: return QT_TR_NOOP("%n sec(s)"); + } + return QT_TR_NOOP("%n unit(s)"); } -QString ReadableInterval::pluralForm(const QString &word, qint64 quantity) +QString ReadableInterval::pluralForm(TIME_UNITS unit, qint64 quantity) { - return word + (quantity > 1 ? "s" : ""); + return tr(describeTimeUnit(unit), "", static_cast(quantity)); } QString ReadableInterval::toReadableString(const QDateTime& timestamp, const QDateTime& reference) { qint64 delta, year, day, hour, min, sec; - bool isPast; delta = reference.toSecsSinceEpoch() - timestamp.toSecsSinceEpoch(); - if (delta) { - QStringList list; - qint8 fieldCount = 0; + if (!delta) { + return tr("now"); + } + + bool isPast = delta > 0; + year = delta / SECONDSPERYEAR; + day = (delta % SECONDSPERYEAR) / SECONDSPERDAY; + hour = ((delta % SECONDSPERYEAR) % SECONDSPERDAY) / SECONDSPERHOUR; + min = (((delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) / SECONDSPERMINUTE; + sec = (((delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) % SECONDSPERMINUTE; - isPast = delta > 0; - year = delta / SECONDSPERYEAR; - day = (delta % SECONDSPERYEAR) / SECONDSPERDAY; - hour = ((delta % SECONDSPERYEAR) % SECONDSPERDAY) / SECONDSPERHOUR; - min = (((delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) / SECONDSPERMINUTE; - sec = (((delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) % SECONDSPERMINUTE; + QStringList list; + QList fields({year, day, hour, min, sec}); + QList units({YEAR, DAY, HOUR, MIN, SEC}); - if (year && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(year).arg(ReadableInterval::pluralForm(YEAR, year))); - if (day && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(day).arg(ReadableInterval::pluralForm(DAY, day))); - if (hour && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(hour).arg(ReadableInterval::pluralForm(HOUR, hour))); - if (min && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(min).arg(ReadableInterval::pluralForm(MIN, min))); - if (sec && ++fieldCount <= MAX_FIELDS_DISPLAYED) - list.append(QStringLiteral("%1 %2").arg(sec).arg(ReadableInterval::pluralForm(SEC, sec))); - return QStringLiteral("%1 %2").arg(list.join(JOIN_SEQ), isPast ? PAST_INTERVAL_STRING : FUTURE_INTERVAL_STRING); - } else { - return ZERO_INTERVAL_STRING; + for (qint8 i = 0, j = 0; i < fields.length() && j <= MAX_FIELDS_DISPLAYED; ++i) { + if (fields[i] && ++j) { + list.append(pluralForm(static_cast(units[i]), fields[i])); + } } + + return QStringLiteral("%1 %2").arg(list.join(tr(", ")), + isPast ? tr("ago") : tr("from now")); } diff --git a/src/libs/util/readableinterval.h b/src/libs/util/readableinterval.h index 73b882cdb..f97110ee6 100644 --- a/src/libs/util/readableinterval.h +++ b/src/libs/util/readableinterval.h @@ -24,17 +24,40 @@ #define ZEAL_UTIL_READABLEINTERVAL_H #include +#include + +namespace { + +enum TIME_CONSTANTS { + SECONDSPERMINUTE = 60, + SECONDSPERHOUR = SECONDSPERMINUTE * 60, + SECONDSPERDAY = SECONDSPERHOUR * 24, + SECONDSPERYEAR = SECONDSPERDAY * 365, +}; + +enum TIME_UNITS { + YEAR, + DAY, + HOUR, + MIN, + SEC +}; + +const qint8 MAX_FIELDS_DISPLAYED = 3; + +} // namespace namespace Zeal { namespace Util { class ReadableInterval { + Q_DECLARE_TR_FUNCTIONS(ReadableInterval) public: static QString toReadableString(const QDateTime& timestamp, const QDateTime& reference = QDateTime::currentDateTime()); - private: - static QString pluralForm(const QString& word, qint64 quantity); + static const char* describeTimeUnit(TIME_UNITS unit); + static QString pluralForm(TIME_UNITS unit, qint64 quantity); }; } // namespace Util From cd0a78999af540f250d6b118e422bc68e5c605f8 Mon Sep 17 00:00:00 2001 From: Karthik Nishanth Date: Tue, 16 Oct 2018 21:16:27 +0530 Subject: [PATCH 4/6] make QDateTime epoch compatible with qt < 5.7 --- src/libs/util/readableinterval.cpp | 2 +- src/libs/util/readableinterval.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/util/readableinterval.cpp b/src/libs/util/readableinterval.cpp index 86373acaf..ae0ec17be 100644 --- a/src/libs/util/readableinterval.cpp +++ b/src/libs/util/readableinterval.cpp @@ -49,7 +49,7 @@ QString ReadableInterval::toReadableString(const QDateTime& timestamp, const QDa { qint64 delta, year, day, hour, min, sec; - delta = reference.toSecsSinceEpoch() - timestamp.toSecsSinceEpoch(); + delta = (reference.toMSecsSinceEpoch() - timestamp.toMSecsSinceEpoch()) / MILLISECONDSPERSECOND; if (!delta) { return tr("now"); diff --git a/src/libs/util/readableinterval.h b/src/libs/util/readableinterval.h index f97110ee6..e9974a3b5 100644 --- a/src/libs/util/readableinterval.h +++ b/src/libs/util/readableinterval.h @@ -29,10 +29,11 @@ namespace { enum TIME_CONSTANTS { + MILLISECONDSPERSECOND = 1000, SECONDSPERMINUTE = 60, SECONDSPERHOUR = SECONDSPERMINUTE * 60, SECONDSPERDAY = SECONDSPERHOUR * 24, - SECONDSPERYEAR = SECONDSPERDAY * 365, + SECONDSPERYEAR = SECONDSPERDAY * 365 }; enum TIME_UNITS { From cb9b4999ad65f39d8055424c8732fd616274bbd5 Mon Sep 17 00:00:00 2001 From: Karthik Nishanth Date: Tue, 16 Oct 2018 21:18:09 +0530 Subject: [PATCH 5/6] fix lgtm warning, promote qint8 to int --- src/libs/util/readableinterval.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/util/readableinterval.cpp b/src/libs/util/readableinterval.cpp index ae0ec17be..113ae5205 100644 --- a/src/libs/util/readableinterval.cpp +++ b/src/libs/util/readableinterval.cpp @@ -66,7 +66,7 @@ QString ReadableInterval::toReadableString(const QDateTime& timestamp, const QDa QList fields({year, day, hour, min, sec}); QList units({YEAR, DAY, HOUR, MIN, SEC}); - for (qint8 i = 0, j = 0; i < fields.length() && j <= MAX_FIELDS_DISPLAYED; ++i) { + for (int i = 0, j = 0; i < fields.length() && j <= MAX_FIELDS_DISPLAYED; ++i) { if (fields[i] && ++j) { list.append(pluralForm(static_cast(units[i]), fields[i])); } From 23a76a1e1652dd45d6d3ede5f0797bcb99872726 Mon Sep 17 00:00:00 2001 From: Karthik Nishanth Date: Tue, 30 Oct 2018 20:38:17 +0530 Subject: [PATCH 6/6] Update time calculation using std::chrono --- src/libs/util/readableinterval.cpp | 35 ++++++++++++++++++++---------- src/libs/util/readableinterval.h | 13 +++++------ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/libs/util/readableinterval.cpp b/src/libs/util/readableinterval.cpp index 113ae5205..378f56204 100644 --- a/src/libs/util/readableinterval.cpp +++ b/src/libs/util/readableinterval.cpp @@ -26,7 +26,10 @@ #include #include +#include + using namespace Zeal::Util; +using namespace std::chrono; const char* ReadableInterval::describeTimeUnit(TIME_UNITS unit) { @@ -47,26 +50,34 @@ QString ReadableInterval::pluralForm(TIME_UNITS unit, qint64 quantity) QString ReadableInterval::toReadableString(const QDateTime& timestamp, const QDateTime& reference) { - qint64 delta, year, day, hour, min, sec; - - delta = (reference.toMSecsSinceEpoch() - timestamp.toMSecsSinceEpoch()) / MILLISECONDSPERSECOND; + qint64 delta = reference.toMSecsSinceEpoch() - timestamp.toMSecsSinceEpoch(); + bool isPast = delta > 0; + milliseconds ms(abs(delta)); - if (!delta) { + if (ms < seconds(1)) { return tr("now"); } - bool isPast = delta > 0; - year = delta / SECONDSPERYEAR; - day = (delta % SECONDSPERYEAR) / SECONDSPERDAY; - hour = ((delta % SECONDSPERYEAR) % SECONDSPERDAY) / SECONDSPERHOUR; - min = (((delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) / SECONDSPERMINUTE; - sec = (((delta % SECONDSPERYEAR) % SECONDSPERDAY) % SECONDSPERHOUR) % SECONDSPERMINUTE; + auto year = duration_cast(ms); + ms -= year; + + auto day = duration_cast(ms); + ms -= day; + + auto hour = duration_cast(ms); + ms -= hour; + + auto min = duration_cast(ms); + ms -= min; + + auto sec = duration_cast(ms); + ms -= sec; QStringList list; - QList fields({year, day, hour, min, sec}); + QList fields({year.count(), day.count(), hour.count(), min.count(), sec.count()}); QList units({YEAR, DAY, HOUR, MIN, SEC}); - for (int i = 0, j = 0; i < fields.length() && j <= MAX_FIELDS_DISPLAYED; ++i) { + for (int i = 0, j = 0; i < fields.length() && j < MAX_FIELDS_DISPLAYED; ++i) { if (fields[i] && ++j) { list.append(pluralForm(static_cast(units[i]), fields[i])); } diff --git a/src/libs/util/readableinterval.h b/src/libs/util/readableinterval.h index e9974a3b5..5b5d2354a 100644 --- a/src/libs/util/readableinterval.h +++ b/src/libs/util/readableinterval.h @@ -26,15 +26,12 @@ #include #include -namespace { +#include -enum TIME_CONSTANTS { - MILLISECONDSPERSECOND = 1000, - SECONDSPERMINUTE = 60, - SECONDSPERHOUR = SECONDSPERMINUTE * 60, - SECONDSPERDAY = SECONDSPERHOUR * 24, - SECONDSPERYEAR = SECONDSPERDAY * 365 -}; +namespace { +// TODO : remove with c++20 +using days = std::chrono::duration>; +using years = std::chrono::duration>; enum TIME_UNITS { YEAR,