summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authormunjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-16 20:52:08 +0000
committermunjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-16 20:52:08 +0000
commit32a63d995d4cf1988fe8eb9ed84555d62ef9a40d (patch)
treeb17a8ba975363905b812dd8082354042c55de39b /chrome/common
parent4b7f783f138f5ec55da9083bf31aa7d813be68e5 (diff)
downloadchromium_src-32a63d995d4cf1988fe8eb9ed84555d62ef9a40d.zip
chromium_src-32a63d995d4cf1988fe8eb9ed84555d62ef9a40d.tar.gz
chromium_src-32a63d995d4cf1988fe8eb9ed84555d62ef9a40d.tar.bz2
Augment time_format.h/.cc to format elapsed time also.
Review URL: http://codereview.chromium.org/67186 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13874 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/time_format.cc242
-rw-r--r--chrome/common/time_format.h15
-rw-r--r--chrome/common/time_format_unittest.cc37
3 files changed, 196 insertions, 98 deletions
diff --git a/chrome/common/time_format.cc b/chrome/common/time_format.cc
index 70f173d..5fd9485 100644
--- a/chrome/common/time_format.cc
+++ b/chrome/common/time_format.cc
@@ -24,82 +24,169 @@
using base::Time;
using base::TimeDelta;
-class TimeRemainingFormat {
+namespace {
+
+static const char kFallbackFormatSuffixShort[] = "}";
+static const char kFallbackFormatSuffixLeft[] = " left}";
+static const char kFallbackFormatSuffixAgo[] = " ago}";
+
+static const int kInvalidMsgId = -1;
+
+// Contains message IDs for various time units and pluralities.
+struct MessageIDs {
+ // There are 4 different time units and 6 different pluralities.
+ int ids[4][6];
+};
+
+// Message IDs for different time formats.
+static const MessageIDs kTimeShortMessageIDs = { {
+ {
+ IDS_TIME_SECS_DEFAULT, IDS_TIME_SEC_SINGULAR, IDS_TIME_SECS_ZERO,
+ IDS_TIME_SECS_TWO, IDS_TIME_SECS_FEW, IDS_TIME_SECS_MANY
+ },
+ {
+ IDS_TIME_MINS_DEFAULT, IDS_TIME_MIN_SINGULAR, kInvalidMsgId,
+ IDS_TIME_MINS_TWO, IDS_TIME_MINS_FEW, IDS_TIME_MINS_MANY
+ },
+ {
+ IDS_TIME_HOURS_DEFAULT, IDS_TIME_HOUR_SINGULAR, kInvalidMsgId,
+ IDS_TIME_HOURS_TWO, IDS_TIME_HOURS_FEW, IDS_TIME_HOURS_MANY
+ },
+ {
+ IDS_TIME_DAYS_DEFAULT, IDS_TIME_DAY_SINGULAR, kInvalidMsgId,
+ IDS_TIME_DAYS_TWO, IDS_TIME_DAYS_FEW, IDS_TIME_DAYS_MANY
+ }
+} };
+
+static const MessageIDs kTimeRemainingMessageIDs = { {
+ {
+ IDS_TIME_REMAINING_SECS_DEFAULT, IDS_TIME_REMAINING_SEC_SINGULAR,
+ IDS_TIME_REMAINING_SECS_ZERO, IDS_TIME_REMAINING_SECS_TWO,
+ IDS_TIME_REMAINING_SECS_FEW, IDS_TIME_REMAINING_SECS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_MINS_DEFAULT, IDS_TIME_REMAINING_MIN_SINGULAR,
+ kInvalidMsgId, IDS_TIME_REMAINING_MINS_TWO,
+ IDS_TIME_REMAINING_MINS_FEW, IDS_TIME_REMAINING_MINS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_HOURS_DEFAULT, IDS_TIME_REMAINING_HOUR_SINGULAR,
+ kInvalidMsgId, IDS_TIME_REMAINING_HOURS_TWO,
+ IDS_TIME_REMAINING_HOURS_FEW, IDS_TIME_REMAINING_HOURS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_DAYS_DEFAULT, IDS_TIME_REMAINING_DAY_SINGULAR,
+ kInvalidMsgId, IDS_TIME_REMAINING_DAYS_TWO,
+ IDS_TIME_REMAINING_DAYS_FEW, IDS_TIME_REMAINING_DAYS_MANY
+ }
+} };
+
+static const MessageIDs kTimeElapsedMessageIDs = { {
+ {
+ IDS_TIME_ELAPSED_SECS_DEFAULT, IDS_TIME_ELAPSED_SEC_SINGULAR,
+ IDS_TIME_ELAPSED_SECS_ZERO, IDS_TIME_ELAPSED_SECS_TWO,
+ IDS_TIME_ELAPSED_SECS_FEW, IDS_TIME_ELAPSED_SECS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_MINS_DEFAULT, IDS_TIME_ELAPSED_MIN_SINGULAR,
+ kInvalidMsgId, IDS_TIME_ELAPSED_MINS_TWO,
+ IDS_TIME_ELAPSED_MINS_FEW, IDS_TIME_ELAPSED_MINS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_HOURS_DEFAULT, IDS_TIME_ELAPSED_HOUR_SINGULAR,
+ kInvalidMsgId, IDS_TIME_ELAPSED_HOURS_TWO,
+ IDS_TIME_ELAPSED_HOURS_FEW, IDS_TIME_ELAPSED_HOURS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_DAYS_DEFAULT, IDS_TIME_ELAPSED_DAY_SINGULAR,
+ kInvalidMsgId, IDS_TIME_ELAPSED_DAYS_TWO,
+ IDS_TIME_ELAPSED_DAYS_FEW, IDS_TIME_ELAPSED_DAYS_MANY
+ }
+} };
+
+// Different format types.
+enum FormatType {
+ FORMAT_SHORT,
+ FORMAT_REMAINING,
+ FORMAT_ELAPSED,
+};
+
+} // namespace
+
+class TimeFormatter {
public:
- const std::vector<PluralFormat*>& formatter(bool short_version) {
- return short_version ? short_formatter_ : long_formatter_;
+ const std::vector<PluralFormat*>& formatter(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return short_formatter_;
+ case FORMAT_REMAINING:
+ return time_left_formatter_;
+ case FORMAT_ELAPSED:
+ return time_elapsed_formatter_;
+ default:
+ NOTREACHED();
+ return short_formatter_;
+ }
}
private:
- TimeRemainingFormat() {
- BuildFormats(true, &short_formatter_);
- BuildFormats(false, &long_formatter_);
+ static const MessageIDs& GetMessageIDs(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return kTimeShortMessageIDs;
+ case FORMAT_REMAINING:
+ return kTimeRemainingMessageIDs;
+ case FORMAT_ELAPSED:
+ return kTimeElapsedMessageIDs;
+ default:
+ NOTREACHED();
+ return kTimeShortMessageIDs;
+ }
}
- ~TimeRemainingFormat() {
+
+ static const char* GetFallbackFormatSuffix(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return kFallbackFormatSuffixShort;
+ case FORMAT_REMAINING:
+ return kFallbackFormatSuffixLeft;
+ case FORMAT_ELAPSED:
+ return kFallbackFormatSuffixAgo;
+ default:
+ NOTREACHED();
+ return kFallbackFormatSuffixShort;
+ }
+ }
+
+ TimeFormatter() {
+ BuildFormats(FORMAT_SHORT, &short_formatter_);
+ BuildFormats(FORMAT_REMAINING, &time_left_formatter_);
+ BuildFormats(FORMAT_ELAPSED, &time_elapsed_formatter_);
+ }
+ ~TimeFormatter() {
STLDeleteContainerPointers(short_formatter_.begin(),
short_formatter_.end());
- STLDeleteContainerPointers(long_formatter_.begin(),
- long_formatter_.end());
+ STLDeleteContainerPointers(time_left_formatter_.begin(),
+ time_left_formatter_.end());
+ STLDeleteContainerPointers(time_elapsed_formatter_.begin(),
+ time_elapsed_formatter_.end());
}
- friend class Singleton<TimeRemainingFormat>;
- friend struct DefaultSingletonTraits<TimeRemainingFormat>;
+ friend class Singleton<TimeFormatter>;
+ friend struct DefaultSingletonTraits<TimeFormatter>;
- std::vector<PluralFormat*> long_formatter_;
std::vector<PluralFormat*> short_formatter_;
- static void BuildFormats(bool short_version,
+ std::vector<PluralFormat*> time_left_formatter_;
+ std::vector<PluralFormat*> time_elapsed_formatter_;
+ static void BuildFormats(FormatType format_type,
std::vector<PluralFormat*>* time_formats);
static PluralFormat* createFallbackFormat(const PluralRules& rules,
int index,
- bool short_version);
+ FormatType format_type);
- DISALLOW_EVIL_CONSTRUCTORS(TimeRemainingFormat);
+ DISALLOW_EVIL_CONSTRUCTORS(TimeFormatter);
};
-void TimeRemainingFormat::BuildFormats(
- bool short_version,
- std::vector<PluralFormat*>* time_formats) {
- const static int kInvalidMsgId = -1;
- const static int kTimeMsgIds[][6] = {
- {
- IDS_TIME_SECS_DEFAULT, IDS_TIME_SEC_SINGULAR, IDS_TIME_SECS_ZERO,
- IDS_TIME_SECS_TWO, IDS_TIME_SECS_FEW, IDS_TIME_SECS_MANY
- },
- {
- IDS_TIME_MINS_DEFAULT, IDS_TIME_MIN_SINGULAR, kInvalidMsgId,
- IDS_TIME_MINS_TWO, IDS_TIME_MINS_FEW, IDS_TIME_MINS_MANY
- },
- {
- IDS_TIME_HOURS_DEFAULT, IDS_TIME_HOUR_SINGULAR, kInvalidMsgId,
- IDS_TIME_HOURS_TWO, IDS_TIME_HOURS_FEW, IDS_TIME_HOURS_MANY
- },
- {
- IDS_TIME_DAYS_DEFAULT, IDS_TIME_DAY_SINGULAR, kInvalidMsgId,
- IDS_TIME_DAYS_TWO, IDS_TIME_DAYS_FEW, IDS_TIME_DAYS_MANY
- }
- };
-
- const static int kTimeLeftMsgIds[][6] = {
- {
- IDS_TIME_REMAINING_SECS_DEFAULT, IDS_TIME_REMAINING_SEC_SINGULAR,
- IDS_TIME_REMAINING_SECS_ZERO, IDS_TIME_REMAINING_SECS_TWO,
- IDS_TIME_REMAINING_SECS_FEW, IDS_TIME_REMAINING_SECS_MANY
- },
- {
- IDS_TIME_REMAINING_MINS_DEFAULT, IDS_TIME_REMAINING_MIN_SINGULAR,
- kInvalidMsgId, IDS_TIME_REMAINING_MINS_TWO,
- IDS_TIME_REMAINING_MINS_FEW, IDS_TIME_REMAINING_MINS_MANY
- },
- {
- IDS_TIME_REMAINING_HOURS_DEFAULT, IDS_TIME_REMAINING_HOUR_SINGULAR,
- kInvalidMsgId, IDS_TIME_REMAINING_HOURS_TWO,
- IDS_TIME_REMAINING_HOURS_FEW, IDS_TIME_REMAINING_HOURS_MANY
- },
- {
- IDS_TIME_REMAINING_DAYS_DEFAULT, IDS_TIME_REMAINING_DAY_SINGULAR,
- kInvalidMsgId, IDS_TIME_REMAINING_DAYS_TWO,
- IDS_TIME_REMAINING_DAYS_FEW, IDS_TIME_REMAINING_DAYS_MANY
- }
- };
-
+void TimeFormatter::BuildFormats(FormatType format_type,
+ std::vector<PluralFormat*>* time_formats) {
const static UnicodeString kKeywords[] = {
UNICODE_STRING_SIMPLE("other"), UNICODE_STRING_SIMPLE("one"),
UNICODE_STRING_SIMPLE("zero"), UNICODE_STRING_SIMPLE("two"),
@@ -114,10 +201,13 @@ void TimeRemainingFormat::BuildFormats(
rules.reset(PluralRules::createRules(fallback_rules, err));
DCHECK(U_SUCCESS(err));
}
+
+ const MessageIDs& message_ids = GetMessageIDs(format_type);
+
for (int i = 0; i < 4; ++i) {
UnicodeString pattern;
for (size_t j = 0; j < arraysize(kKeywords); ++j) {
- int msg_id = short_version ? kTimeMsgIds[i][j] : kTimeLeftMsgIds[i][j];
+ int msg_id = message_ids.ids[i][j];
if (msg_id == kInvalidMsgId) continue;
std::string sub_pattern = WideToUTF8(l10n_util::GetString(msg_id));
// NA means this keyword is not used in the current locale.
@@ -138,7 +228,7 @@ void TimeRemainingFormat::BuildFormats(
time_formats->push_back(format);
} else {
delete format;
- time_formats->push_back(createFallbackFormat(*rules, i, short_version));
+ time_formats->push_back(createFallbackFormat(*rules, i, format_type));
// Reset it so that next ICU call can proceed.
err = U_ZERO_ERROR;
}
@@ -147,17 +237,16 @@ void TimeRemainingFormat::BuildFormats(
// Create a hard-coded fallback plural format. This will never be called
// unless translators make a mistake.
-PluralFormat* TimeRemainingFormat::createFallbackFormat(
- const PluralRules& rules,
- int index,
- bool short_version) {
+PluralFormat* TimeFormatter::createFallbackFormat(const PluralRules& rules,
+ int index,
+ FormatType format_type) {
const static UnicodeString kUnits[4][2] = {
{ UNICODE_STRING_SIMPLE("sec"), UNICODE_STRING_SIMPLE("secs") },
{ UNICODE_STRING_SIMPLE("min"), UNICODE_STRING_SIMPLE("mins") },
{ UNICODE_STRING_SIMPLE("hour"), UNICODE_STRING_SIMPLE("hours") },
{ UNICODE_STRING_SIMPLE("day"), UNICODE_STRING_SIMPLE("days") }
};
- UnicodeString suffix(short_version ? "}" : " left}", -1, US_INV);
+ UnicodeString suffix(GetFallbackFormatSuffix(format_type), -1, US_INV);
UnicodeString pattern;
if (rules.isKeyword(UNICODE_STRING_SIMPLE("one"))) {
pattern += UNICODE_STRING_SIMPLE("one{# ") + kUnits[index][0] + suffix;
@@ -169,10 +258,10 @@ PluralFormat* TimeRemainingFormat::createFallbackFormat(
return format;
}
-Singleton<TimeRemainingFormat> time_remaining_format;
+Singleton<TimeFormatter> time_formatter;
-static std::wstring TimeRemainingImpl(const TimeDelta& delta,
- bool short_version) {
+static std::wstring FormatTimeImpl(const TimeDelta& delta,
+ FormatType format_type) {
if (delta.ToInternalValue() < 0) {
NOTREACHED() << "Negative duration";
return std::wstring();
@@ -181,7 +270,7 @@ static std::wstring TimeRemainingImpl(const TimeDelta& delta,
int number;
const std::vector<PluralFormat*>& formatters =
- time_remaining_format->formatter(short_version);
+ time_formatter->formatter(format_type);
UErrorCode error = U_ZERO_ERROR;
UnicodeString time_string;
@@ -222,13 +311,18 @@ static std::wstring TimeRemainingImpl(const TimeDelta& delta,
}
// static
+std::wstring TimeFormat::TimeElapsed(const TimeDelta& delta) {
+ return FormatTimeImpl(delta, FORMAT_ELAPSED);
+}
+
+// static
std::wstring TimeFormat::TimeRemaining(const TimeDelta& delta) {
- return TimeRemainingImpl(delta, false);
+ return FormatTimeImpl(delta, FORMAT_REMAINING);
}
// static
std::wstring TimeFormat::TimeRemainingShort(const TimeDelta& delta) {
- return TimeRemainingImpl(delta, true);
+ return FormatTimeImpl(delta, FORMAT_SHORT);
}
// static
diff --git a/chrome/common/time_format.h b/chrome/common/time_format.h
index 252599b..c04ed62 100644
--- a/chrome/common/time_format.h
+++ b/chrome/common/time_format.h
@@ -18,13 +18,18 @@ class TimeDelta;
class TimeFormat {
public:
- // Returns a localized string of approximate time remaining. The conditions
- // are simpler than PastTime since this is used for in-progress operations
- // and users have different expectations of units.
- // Ex: "3 mins left", "2 days left".
+ // TimeElapsed, TimeRemaining and TimeRemainingShort functions:
+ // These functions return a localized string of approximate time duration. The
+ // conditions are simpler than PastTime since these functions are used for
+ // in-progress operations and users have different expectations of units.
+
+ // Returns times in elapsed-format: "3 mins ago", "2 days ago".
+ static std::wstring TimeElapsed(const base::TimeDelta& delta);
+
+ // Returns times in remaining-format: "3 mins left", "2 days left".
static std::wstring TimeRemaining(const base::TimeDelta& delta);
- // Same as TimeRemaining without the "left".
+ // Returns times in short-format: "3 mins", "2 days".
static std::wstring TimeRemainingShort(const base::TimeDelta& delta);
// For displaying a relative time in the past. This method returns either
diff --git a/chrome/common/time_format_unittest.cc b/chrome/common/time_format_unittest.cc
index 56f38f3..c910209 100644
--- a/chrome/common/time_format_unittest.cc
+++ b/chrome/common/time_format_unittest.cc
@@ -32,16 +32,17 @@ TEST(TimeFormat, RelativeDate) {
}
namespace {
-void TestRemainingTime(const TimeDelta delta,
- const std::wstring& expected_short,
- const std::wstring& expected_long) {
- EXPECT_EQ(expected_short, TimeFormat::TimeRemainingShort(delta));
- EXPECT_EQ(expected_long, TimeFormat::TimeRemaining(delta));
+void TestTimeFormats(const TimeDelta delta, const std::wstring& expected) {
+ std::wstring expected_left = expected + L" left";
+ std::wstring expected_ago = expected + L" ago";
+ EXPECT_EQ(expected, TimeFormat::TimeRemainingShort(delta));
+ EXPECT_EQ(expected_left, TimeFormat::TimeRemaining(delta));
+ EXPECT_EQ(expected_ago, TimeFormat::TimeElapsed(delta));
}
} // namespace
-TEST(TimeFormat, RemainingTime) {
+TEST(TimeFormat, FormatTime) {
const TimeDelta one_day = TimeDelta::FromDays(1);
const TimeDelta three_days = TimeDelta::FromDays(3);
const TimeDelta one_hour = TimeDelta::FromHours(1);
@@ -54,17 +55,15 @@ TEST(TimeFormat, RemainingTime) {
// TODO(jungshik) : These test only pass when the OS locale is 'en'.
// We need to add SetUp() and TearDown() to set the locale to 'en'.
- TestRemainingTime(twohundred_millisecs, L"0 secs", L"0 secs left");
- TestRemainingTime(one_sec - twohundred_millisecs, L"0 secs", L"0 secs left");
- TestRemainingTime(one_sec + twohundred_millisecs, L"1 sec", L"1 sec left");
- TestRemainingTime(five_secs + twohundred_millisecs, L"5 secs",
- L"5 secs left");
- TestRemainingTime(one_min + five_secs, L"1 min", L"1 min left");
- TestRemainingTime(three_mins + twohundred_millisecs,
- L"3 mins", L"3 mins left");
- TestRemainingTime(one_hour + five_secs, L"1 hour", L"1 hour left");
- TestRemainingTime(four_hours + five_secs, L"4 hours", L"4 hours left");
- TestRemainingTime(one_day + five_secs, L"1 day", L"1 day left");
- TestRemainingTime(three_days, L"3 days", L"3 days left");
- TestRemainingTime(three_days + four_hours, L"3 days", L"3 days left");
+ TestTimeFormats(twohundred_millisecs, L"0 secs");
+ TestTimeFormats(one_sec - twohundred_millisecs, L"0 secs");
+ TestTimeFormats(one_sec + twohundred_millisecs, L"1 sec");
+ TestTimeFormats(five_secs + twohundred_millisecs, L"5 secs");
+ TestTimeFormats(one_min + five_secs, L"1 min");
+ TestTimeFormats(three_mins + twohundred_millisecs, L"3 mins");
+ TestTimeFormats(one_hour + five_secs, L"1 hour");
+ TestTimeFormats(four_hours + five_secs, L"4 hours");
+ TestTimeFormats(one_day + five_secs, L"1 day");
+ TestTimeFormats(three_days, L"3 days");
+ TestTimeFormats(three_days + four_hours, L"3 days");
}