1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/global_media_controls/public/format_duration.h"
#include <string>
#include "base/i18n/number_formatting.h"
#include "base/i18n/time_formatting.h"
#include "base/i18n/unicodestring.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "third_party/icu/source/i18n/unicode/measfmt.h"
#include "third_party/icu/source/i18n/unicode/measunit.h"
#include "third_party/icu/source/i18n/unicode/measure.h"
namespace global_media_controls {
namespace {
// Returns a singleton `icu::MeasureFormat` object, so that it doesn't have to
// be recreated each time when formatting a time duration.
const icu::MeasureFormat& GetMeasureFormat() {
static const base::NoDestructor<icu::MeasureFormat> measure_format([] {
UErrorCode status = U_ZERO_ERROR;
icu::MeasureFormat measure_format(
icu::Locale::getDefault(), UMeasureFormatWidth::UMEASFMT_WIDTH_NUMERIC,
status);
CHECK(U_SUCCESS(status));
return measure_format;
}());
return *measure_format;
}
} // namespace
std::u16string GetFormattedDuration(const base::TimeDelta& duration) {
UErrorCode status = U_ZERO_ERROR;
std::vector<icu::Measure> measures;
const int64_t total_seconds =
base::ClampRound<int64_t>(duration.InSecondsF());
const int64_t hours = total_seconds / base::Time::kSecondsPerHour;
if (hours != 0) {
measures.emplace_back(hours, icu::MeasureUnit::createHour(status), status);
}
const int64_t minutes =
(total_seconds - hours * base::Time::kSecondsPerHour) /
base::Time::kSecondsPerMinute;
measures.emplace_back(minutes, icu::MeasureUnit::createMinute(status),
status);
const int64_t seconds = total_seconds % base::Time::kSecondsPerMinute;
measures.emplace_back(seconds, icu::MeasureUnit::createSecond(status),
status);
icu::UnicodeString formatted;
icu::FieldPosition ignore(icu::FieldPosition::DONT_CARE);
GetMeasureFormat().formatMeasures(&measures[0], measures.size(), formatted,
ignore, status);
if (U_SUCCESS(status)) {
return base::i18n::UnicodeStringToString16(formatted);
}
// If any step has error, returns the duration in seconds.
return base::NumberToString16(std::ceil(duration.InSecondsF()));
}
} // namespace global_media_controls
|