| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/i18n/time_formatting.h" | 5 #include "base/i18n/time_formatting.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/i18n/rtl.h" | 9 #include "base/i18n/rtl.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 11 #include "base/test/icu_test_util.h" | 11 #include "base/test/icu_test_util.h" |
| 12 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 #include "third_party/icu/source/common/unicode/uversion.h" | 14 #include "third_party/icu/source/common/unicode/uversion.h" |
| 15 #include "third_party/icu/source/i18n/unicode/calendar.h" | 15 #include "third_party/icu/source/i18n/unicode/calendar.h" |
| 16 #include "third_party/icu/source/i18n/unicode/timezone.h" | 16 #include "third_party/icu/source/i18n/unicode/timezone.h" |
| 17 #include "third_party/icu/source/i18n/unicode/tzfmt.h" | 17 #include "third_party/icu/source/i18n/unicode/tzfmt.h" |
| 18 | 18 |
| 19 namespace base { | 19 namespace base { |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 const Time::Exploded kTestDateTimeExploded = { | 22 const Time::Exploded kTestDateTimeExploded = { |
| 23 2011, 4, 6, 30, // Sat, Apr 30, 2011 | 23 2011, 4, 6, 30, // Sat, Apr 30, 2011 |
| 24 15, 42, 7, 0 // 15:42:07.000 | 24 15, 42, 7, 0 // 15:42:07.000 |
| 25 }; | 25 }; |
| 26 | 26 |
| 27 // Returns difference between the local time and GMT formatted as string. | 27 // Returns difference between the local time and GMT formatted as string. |
| 28 // This function gets |time| because the difference depends on time, | 28 // This function gets |time| because the difference depends on time, |
| 29 // see https://en.wikipedia.org/wiki/Daylight_saving_time for details. | 29 // see https://en.wikipedia.org/wiki/Daylight_saving_time for details. |
| 30 base::string16 GetShortTimeZone(const Time& time) { | 30 string16 GetShortTimeZone(const Time& time) { |
| 31 UErrorCode status = U_ZERO_ERROR; | 31 UErrorCode status = U_ZERO_ERROR; |
| 32 std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault()); | 32 std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault()); |
| 33 std::unique_ptr<icu::TimeZoneFormat> zone_formatter( | 33 std::unique_ptr<icu::TimeZoneFormat> zone_formatter( |
| 34 icu::TimeZoneFormat::createInstance(icu::Locale::getDefault(), status)); | 34 icu::TimeZoneFormat::createInstance(icu::Locale::getDefault(), status)); |
| 35 EXPECT_TRUE(U_SUCCESS(status)); | 35 EXPECT_TRUE(U_SUCCESS(status)); |
| 36 icu::UnicodeString name; | 36 icu::UnicodeString name; |
| 37 zone_formatter->format(UTZFMT_STYLE_SPECIFIC_SHORT, *zone, | 37 zone_formatter->format(UTZFMT_STYLE_SPECIFIC_SHORT, *zone, |
| 38 static_cast<UDate>(time.ToDoubleT() * 1000), | 38 static_cast<UDate>(time.ToDoubleT() * 1000), |
| 39 name, nullptr); | 39 name, nullptr); |
| 40 return base::string16(name.getBuffer(), name.length()); | 40 return string16(name.getBuffer(), name.length()); |
| 41 } |
| 42 |
| 43 // Calls TimeDurationFormat() with |delta| and |width| and returns the resulting |
| 44 // string. On failure, adds a failed expectation and returns an empty string. |
| 45 string16 TimeDurationFormatString(const TimeDelta& delta, |
| 46 DurationFormatWidth width) { |
| 47 string16 str; |
| 48 EXPECT_TRUE(TimeDurationFormat(delta, width, &str)) |
| 49 << "Failed to format " << delta.ToInternalValue() << " with width " |
| 50 << width; |
| 51 return str; |
| 52 } |
| 53 |
| 54 // Calls TimeDurationFormatWithSeconds() with |delta| and |width| and returns |
| 55 // the resulting string. On failure, adds a failed expectation and returns an |
| 56 // empty string. |
| 57 string16 TimeDurationFormatWithSecondsString(const TimeDelta& delta, |
| 58 DurationFormatWidth width) { |
| 59 string16 str; |
| 60 EXPECT_TRUE(TimeDurationFormatWithSeconds(delta, width, &str)) |
| 61 << "Failed to format " << delta.ToInternalValue() << " with width " |
| 62 << width; |
| 63 return str; |
| 41 } | 64 } |
| 42 | 65 |
| 43 #if defined(OS_ANDROID) | 66 #if defined(OS_ANDROID) |
| 44 #define MAYBE_TimeFormatTimeOfDayDefault12h \ | 67 #define MAYBE_TimeFormatTimeOfDayDefault12h \ |
| 45 DISABLED_TimeFormatTimeOfDayDefault12h | 68 DISABLED_TimeFormatTimeOfDayDefault12h |
| 46 #else | 69 #else |
| 47 #define MAYBE_TimeFormatTimeOfDayDefault12h TimeFormatTimeOfDayDefault12h | 70 #define MAYBE_TimeFormatTimeOfDayDefault12h TimeFormatTimeOfDayDefault12h |
| 48 #endif | 71 #endif |
| 49 TEST(TimeFormattingTest, MAYBE_TimeFormatTimeOfDayDefault12h) { | 72 TEST(TimeFormattingTest, MAYBE_TimeFormatTimeOfDayDefault12h) { |
| 50 // Test for a locale defaulted to 12h clock. | 73 // Test for a locale defaulted to 12h clock. |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 TimeFormatWithPattern(time, "MMMMdjmmss")); | 270 TimeFormatWithPattern(time, "MMMMdjmmss")); |
| 248 } | 271 } |
| 249 | 272 |
| 250 TEST(TimeFormattingTest, TimeDurationFormat) { | 273 TEST(TimeFormattingTest, TimeDurationFormat) { |
| 251 test::ScopedRestoreICUDefaultLocale restore_locale; | 274 test::ScopedRestoreICUDefaultLocale restore_locale; |
| 252 TimeDelta delta = TimeDelta::FromMinutes(15 * 60 + 42); | 275 TimeDelta delta = TimeDelta::FromMinutes(15 * 60 + 42); |
| 253 | 276 |
| 254 // US English. | 277 // US English. |
| 255 i18n::SetICUDefaultLocale("en_US"); | 278 i18n::SetICUDefaultLocale("en_US"); |
| 256 EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes"), | 279 EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes"), |
| 257 TimeDurationFormat(delta, DURATION_WIDTH_WIDE)); | 280 TimeDurationFormatString(delta, DURATION_WIDTH_WIDE)); |
| 258 EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min"), | 281 EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min"), |
| 259 TimeDurationFormat(delta, DURATION_WIDTH_SHORT)); | 282 TimeDurationFormatString(delta, DURATION_WIDTH_SHORT)); |
| 260 EXPECT_EQ(ASCIIToUTF16("15h 42m"), | 283 EXPECT_EQ(ASCIIToUTF16("15h 42m"), |
| 261 TimeDurationFormat(delta, DURATION_WIDTH_NARROW)); | 284 TimeDurationFormatString(delta, DURATION_WIDTH_NARROW)); |
| 262 EXPECT_EQ(ASCIIToUTF16("15:42"), | 285 EXPECT_EQ(ASCIIToUTF16("15:42"), |
| 263 TimeDurationFormat(delta, DURATION_WIDTH_NUMERIC)); | 286 TimeDurationFormatString(delta, DURATION_WIDTH_NUMERIC)); |
| 264 | 287 |
| 265 // Danish, with Latin alphabet but different abbreviations and punctuation. | 288 // Danish, with Latin alphabet but different abbreviations and punctuation. |
| 266 i18n::SetICUDefaultLocale("da"); | 289 i18n::SetICUDefaultLocale("da"); |
| 267 EXPECT_EQ(ASCIIToUTF16("15 timer og 42 minutter"), | 290 EXPECT_EQ(ASCIIToUTF16("15 timer og 42 minutter"), |
| 268 TimeDurationFormat(delta, DURATION_WIDTH_WIDE)); | 291 TimeDurationFormatString(delta, DURATION_WIDTH_WIDE)); |
| 269 EXPECT_EQ(ASCIIToUTF16("15 t og 42 min."), | 292 EXPECT_EQ(ASCIIToUTF16("15 t og 42 min."), |
| 270 TimeDurationFormat(delta, DURATION_WIDTH_SHORT)); | 293 TimeDurationFormatString(delta, DURATION_WIDTH_SHORT)); |
| 271 EXPECT_EQ(ASCIIToUTF16("15 t og 42 min"), | 294 EXPECT_EQ(ASCIIToUTF16("15 t og 42 min"), |
| 272 TimeDurationFormat(delta, DURATION_WIDTH_NARROW)); | 295 TimeDurationFormatString(delta, DURATION_WIDTH_NARROW)); |
| 273 EXPECT_EQ(ASCIIToUTF16("15.42"), | 296 EXPECT_EQ(ASCIIToUTF16("15.42"), |
| 274 TimeDurationFormat(delta, DURATION_WIDTH_NUMERIC)); | 297 TimeDurationFormatString(delta, DURATION_WIDTH_NUMERIC)); |
| 275 | 298 |
| 276 // Persian, with non-Arabic numbers. | 299 // Persian, with non-Arabic numbers. |
| 277 i18n::SetICUDefaultLocale("fa"); | 300 i18n::SetICUDefaultLocale("fa"); |
| 278 string16 fa_wide = WideToUTF16( | 301 string16 fa_wide = WideToUTF16( |
| 279 L"\x6f1\x6f5\x20\x633\x627\x639\x62a\x20\x648\x20\x6f4\x6f2\x20\x62f\x642" | 302 L"\x6f1\x6f5\x20\x633\x627\x639\x62a\x20\x648\x20\x6f4\x6f2\x20\x62f\x642" |
| 280 L"\x6cc\x642\x647"); | 303 L"\x6cc\x642\x647"); |
| 281 string16 fa_short = WideToUTF16( | 304 string16 fa_short = WideToUTF16( |
| 282 L"\x6f1\x6f5\x20\x633\x627\x639\x62a\x60c\x200f\x20\x6f4\x6f2\x20\x62f" | 305 L"\x6f1\x6f5\x20\x633\x627\x639\x62a\x60c\x200f\x20\x6f4\x6f2\x20\x62f" |
| 283 L"\x642\x6cc\x642\x647"); | 306 L"\x642\x6cc\x642\x647"); |
| 284 string16 fa_narrow = WideToUTF16( | 307 string16 fa_narrow = WideToUTF16( |
| 285 L"\x6f1\x6f5\x20\x633\x627\x639\x62a\x20\x6f4\x6f2\x20\x62f\x642\x6cc" | 308 L"\x6f1\x6f5\x20\x633\x627\x639\x62a\x20\x6f4\x6f2\x20\x62f\x642\x6cc" |
| 286 L"\x642\x647"); | 309 L"\x642\x647"); |
| 287 string16 fa_numeric = WideToUTF16(L"\x6f1\x6f5\x3a\x6f4\x6f2"); | 310 string16 fa_numeric = WideToUTF16(L"\x6f1\x6f5\x3a\x6f4\x6f2"); |
| 288 EXPECT_EQ(fa_wide, TimeDurationFormat(delta, DURATION_WIDTH_WIDE)); | 311 EXPECT_EQ(fa_wide, TimeDurationFormatString(delta, DURATION_WIDTH_WIDE)); |
| 289 EXPECT_EQ(fa_short, TimeDurationFormat(delta, DURATION_WIDTH_SHORT)); | 312 EXPECT_EQ(fa_short, TimeDurationFormatString(delta, DURATION_WIDTH_SHORT)); |
| 290 EXPECT_EQ(fa_narrow, TimeDurationFormat(delta, DURATION_WIDTH_NARROW)); | 313 EXPECT_EQ(fa_narrow, TimeDurationFormatString(delta, DURATION_WIDTH_NARROW)); |
| 291 EXPECT_EQ(fa_numeric, TimeDurationFormat(delta, DURATION_WIDTH_NUMERIC)); | 314 EXPECT_EQ(fa_numeric, |
| 315 TimeDurationFormatString(delta, DURATION_WIDTH_NUMERIC)); |
| 292 } | 316 } |
| 293 | 317 |
| 294 TEST(TimeFormattingTest, TimeDurationFormatWithSeconds) { | 318 TEST(TimeFormattingTest, TimeDurationFormatWithSeconds) { |
| 295 test::ScopedRestoreICUDefaultLocale restore_locale; | 319 test::ScopedRestoreICUDefaultLocale restore_locale; |
| 296 | 320 |
| 297 // US English. | 321 // US English. |
| 298 i18n::SetICUDefaultLocale("en_US"); | 322 i18n::SetICUDefaultLocale("en_US"); |
| 299 | 323 |
| 300 // Test different formats. | 324 // Test different formats. |
| 301 TimeDelta delta = TimeDelta::FromSeconds(15 * 3600 + 42 * 60 + 30); | 325 TimeDelta delta = TimeDelta::FromSeconds(15 * 3600 + 42 * 60 + 30); |
| 302 EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes, 30 seconds"), | 326 EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes, 30 seconds"), |
| 303 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_WIDE)); | 327 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_WIDE)); |
| 304 EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min, 30 sec"), | 328 EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min, 30 sec"), |
| 305 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_SHORT)); | 329 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_SHORT)); |
| 306 EXPECT_EQ(ASCIIToUTF16("15h 42m 30s"), | 330 EXPECT_EQ(ASCIIToUTF16("15h 42m 30s"), |
| 307 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_NARROW)); | 331 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NARROW)); |
| 308 EXPECT_EQ(ASCIIToUTF16("15:42:30"), | 332 EXPECT_EQ(ASCIIToUTF16("15:42:30"), |
| 309 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_NUMERIC)); | 333 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NUMERIC)); |
| 310 | 334 |
| 311 // Test edge case when hour >= 100. | 335 // Test edge case when hour >= 100. |
| 312 delta = TimeDelta::FromSeconds(125 * 3600 + 42 * 60 + 30); | 336 delta = TimeDelta::FromSeconds(125 * 3600 + 42 * 60 + 30); |
| 313 EXPECT_EQ(ASCIIToUTF16("125 hours, 42 minutes, 30 seconds"), | 337 EXPECT_EQ(ASCIIToUTF16("125 hours, 42 minutes, 30 seconds"), |
| 314 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_WIDE)); | 338 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_WIDE)); |
| 315 EXPECT_EQ(ASCIIToUTF16("125 hr, 42 min, 30 sec"), | 339 EXPECT_EQ(ASCIIToUTF16("125 hr, 42 min, 30 sec"), |
| 316 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_SHORT)); | 340 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_SHORT)); |
| 317 EXPECT_EQ(ASCIIToUTF16("125h 42m 30s"), | 341 EXPECT_EQ(ASCIIToUTF16("125h 42m 30s"), |
| 318 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_NARROW)); | 342 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NARROW)); |
| 319 | 343 |
| 320 // Test edge case when minute = 0. | 344 // Test edge case when minute = 0. |
| 321 delta = TimeDelta::FromSeconds(15 * 3600 + 0 * 60 + 30); | 345 delta = TimeDelta::FromSeconds(15 * 3600 + 0 * 60 + 30); |
| 322 EXPECT_EQ(ASCIIToUTF16("15 hours, 0 minutes, 30 seconds"), | 346 EXPECT_EQ(ASCIIToUTF16("15 hours, 0 minutes, 30 seconds"), |
| 323 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_WIDE)); | 347 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_WIDE)); |
| 324 EXPECT_EQ(ASCIIToUTF16("15 hr, 0 min, 30 sec"), | 348 EXPECT_EQ(ASCIIToUTF16("15 hr, 0 min, 30 sec"), |
| 325 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_SHORT)); | 349 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_SHORT)); |
| 326 EXPECT_EQ(ASCIIToUTF16("15h 0m 30s"), | 350 EXPECT_EQ(ASCIIToUTF16("15h 0m 30s"), |
| 327 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_NARROW)); | 351 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NARROW)); |
| 328 EXPECT_EQ(ASCIIToUTF16("15:00:30"), | 352 EXPECT_EQ(ASCIIToUTF16("15:00:30"), |
| 329 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_NUMERIC)); | 353 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NUMERIC)); |
| 330 | 354 |
| 331 // Test edge case when second = 0. | 355 // Test edge case when second = 0. |
| 332 delta = TimeDelta::FromSeconds(15 * 3600 + 42 * 60 + 0); | 356 delta = TimeDelta::FromSeconds(15 * 3600 + 42 * 60 + 0); |
| 333 EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes, 0 seconds"), | 357 EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes, 0 seconds"), |
| 334 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_WIDE)); | 358 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_WIDE)); |
| 335 EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min, 0 sec"), | 359 EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min, 0 sec"), |
| 336 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_SHORT)); | 360 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_SHORT)); |
| 337 EXPECT_EQ(ASCIIToUTF16("15h 42m 0s"), | 361 EXPECT_EQ(ASCIIToUTF16("15h 42m 0s"), |
| 338 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_NARROW)); | 362 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NARROW)); |
| 339 EXPECT_EQ(ASCIIToUTF16("15:42:00"), | 363 EXPECT_EQ(ASCIIToUTF16("15:42:00"), |
| 340 TimeDurationFormatWithSeconds(delta, DURATION_WIDTH_NUMERIC)); | 364 TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NUMERIC)); |
| 341 } | 365 } |
| 342 | 366 |
| 343 TEST(TimeFormattingTest, TimeIntervalFormat) { | 367 TEST(TimeFormattingTest, TimeIntervalFormat) { |
| 344 test::ScopedRestoreICUDefaultLocale restore_locale; | 368 test::ScopedRestoreICUDefaultLocale restore_locale; |
| 345 i18n::SetICUDefaultLocale("en_US"); | 369 i18n::SetICUDefaultLocale("en_US"); |
| 346 | 370 |
| 347 const Time::Exploded kTestIntervalEndTimeExploded = { | 371 const Time::Exploded kTestIntervalEndTimeExploded = { |
| 348 2011, 5, 6, 28, // Sat, Apr 30, 2012 | 372 2011, 5, 6, 28, // Sat, Apr 30, 2012 |
| 349 15, 42, 7, 0 // 15:42:07.000 | 373 15, 42, 7, 0 // 15:42:07.000 |
| 350 }; | 374 }; |
| 351 | 375 |
| 352 Time begin_time; | 376 Time begin_time; |
| 353 EXPECT_TRUE(Time::FromLocalExploded(kTestDateTimeExploded, &begin_time)); | 377 EXPECT_TRUE(Time::FromLocalExploded(kTestDateTimeExploded, &begin_time)); |
| 354 Time end_time; | 378 Time end_time; |
| 355 EXPECT_TRUE(Time::FromLocalExploded(kTestIntervalEndTimeExploded, &end_time)); | 379 EXPECT_TRUE(Time::FromLocalExploded(kTestIntervalEndTimeExploded, &end_time)); |
| 356 | 380 |
| 357 EXPECT_EQ( | 381 EXPECT_EQ( |
| 358 WideToUTF16(L"Saturday, April 30 – Saturday, May 28"), | 382 WideToUTF16(L"Saturday, April 30 – Saturday, May 28"), |
| 359 DateIntervalFormat(begin_time, end_time, DATE_FORMAT_MONTH_WEEKDAY_DAY)); | 383 DateIntervalFormat(begin_time, end_time, DATE_FORMAT_MONTH_WEEKDAY_DAY)); |
| 360 } | 384 } |
| 361 | 385 |
| 362 } // namespace | 386 } // namespace |
| 363 } // namespace base | 387 } // namespace base |
| OLD | NEW |