Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
- Minor: Added action to reset `/watching`. (#6759)
- Minor: Removed messaging about running flatpak. This is already apparent in the newer Flatpak runtimes. (#6768)
- Minor: Add `/(un)monitor` and `/(un)restrict` commands for moderators. (#6750, #6785)
- Minor: The follower mode duration in the split header now shows hours or days if possible. (#6812)
- Bugfix: Fixed context menu hotkeys not working on macOS. (#6778)
- Bugfix: Moderation checks now include the lead moderator badge. (#6642)
- Bugfix: Fixed lead moderator badges not being filtered by the `Channel` badge setting. (#6665)
Expand Down
32 changes: 32 additions & 0 deletions src/util/FormatTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "util/FormatTime.hpp"

#include "common/QLogging.hpp"
#include "util/Helpers.hpp"

#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
Expand Down Expand Up @@ -183,6 +184,37 @@ QString formatTime(std::chrono::seconds totalSeconds, int components)
components);
}

QString formatDurationExact(std::chrono::seconds seconds)
{
if (seconds.count() == 0)
{
return u"0s"_s;
}

auto [value, unit] = [&]() -> std::pair<int64_t, char16_t> {
int64_t value = seconds.count();
if ((value % 60) != 0)
{
return {value, 's'};
}
value /= 60;
if ((value % 60) != 0)
{
return {value, 'm'};
}
value /= 60;
if ((value % 24) != 0)
{
return {value, 'h'};
}
return {value / 24, 'd'};
}();

auto str = localizeNumbers(value);
str += unit;
return str;
}

QString formatLongFriendlyDuration(const QDateTime &from, const QDateTime &to)
{
if (!from.isValid() || !to.isValid())
Expand Down
10 changes: 10 additions & 0 deletions src/util/FormatTime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ QString formatTime(int totalSeconds, int components = 4);
QString formatTime(const QString &totalSecondsString, int components = 4);
QString formatTime(std::chrono::seconds totalSeconds, int components = 4);

/// Format a duration with one component while showing the exact value.
///
/// **Examples**:
/// - `2` formats as `2s`
/// - `120` formats as `2m`
/// - `121` formats as `121s`
///
/// Supports seconds, minutes, hours, and days.
QString formatDurationExact(std::chrono::seconds seconds);

/// Formats a duration that's expected to be long (sevreal months or years) like
/// "4 years, 5 days and 8 hours".
///
Expand Down
6 changes: 4 additions & 2 deletions src/widgets/splits/SplitHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "singletons/StreamerMode.hpp"
#include "singletons/Theme.hpp"
#include "singletons/WindowManager.hpp"
#include "util/FormatTime.hpp"
#include "util/Helpers.hpp"
#include "util/LayoutHelper.hpp"
#include "widgets/buttons/DrawnButton.hpp"
Expand Down Expand Up @@ -82,8 +83,9 @@ auto formatRoomModeUnclean(
{
if (modes->followerOnly != 0)
{
text += QString("follow(%1m), ")
.arg(localizeNumbers(modes->followerOnly));
text += QString("follow(%1), ")
.arg(formatDurationExact(
std::chrono::minutes{modes->followerOnly}));
}
else
{
Expand Down
41 changes: 41 additions & 0 deletions tests/src/FormatTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,47 @@ TEST(FormatTime, chrono)
}
}

TEST(FormatTime, formatDurationExact)
{
struct Case {
std::chrono::seconds input;
QStringView output;
};
std::vector<Case> cases{
{.input = 0s, .output = u"0s"},
{.input = 1s, .output = u"1s"},
{.input = 10s, .output = u"10s"},
{.input = 59s, .output = u"59s"},
{.input = 60s, .output = u"1m"},
{.input = 61s, .output = u"61s"},
{.input = 64s, .output = u"64s"},
{.input = 2min, .output = u"2m"},
{.input = 10min, .output = u"10m"},
{.input = 10min + 2s, .output = u"602s"},
{.input = 59min, .output = u"59m"},
{.input = 1h, .output = u"1h"},
{.input = 1h + 1min, .output = u"61m"},
{.input = 1h + 1min + 1s, .output = u"3,661s"},
{.input = 10h, .output = u"10h"},
{.input = 10h + 2s, .output = u"36,002s"},
{.input = 23h, .output = u"23h"},
{.input = 24h, .output = u"1d"},
{.input = 25h, .output = u"25h"},
{.input = 5 * 24h, .output = u"5d"},
{.input = 7 * 24h, .output = u"7d"},
{.input = 14 * 24h, .output = u"14d"},
{.input = 28 * 24h, .output = u"28d"},
{.input = 30 * 24h, .output = u"30d"},
{.input = 31 * 24h, .output = u"31d"},
};

for (const auto &c : cases)
{
ASSERT_EQ(formatDurationExact(c.input), c.output)
<< "Input: " << c.input.count() << 's';
}
}

TEST(FormatTime, formatLongFriendlyDuration)
{
struct Case {
Expand Down
3 changes: 3 additions & 0 deletions tests/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <QApplication>
#include <QJsonArray>
#include <QLocale>
#include <QLoggingCategory>
#include <QtConcurrent>
#include <QTimer>
Expand All @@ -29,6 +30,8 @@ int main(int argc, char **argv)
QApplication app(argc, argv);
// make sure to always debug-log
QLoggingCategory::setFilterRules("chatterino.*=true");
// make sure we use the same language when formatting
QLocale::setDefault(QLocale("en_GB"));

initResources();

Expand Down
Loading