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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/i18n/time_formatting.h"
#include <stddef.h>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "third_party/icu/source/i18n/unicode/datefmt.h"
#include "third_party/icu/source/i18n/unicode/dtptngen.h"
#include "third_party/icu/source/i18n/unicode/smpdtfmt.h"
namespace base {
namespace {
string16 TimeFormat(const icu::DateFormat* formatter,
const Time& time) {
DCHECK(formatter);
icu::UnicodeString date_string;
formatter->format(static_cast<UDate>(time.ToDoubleT() * 1000), date_string);
return string16(date_string.getBuffer(),
static_cast<size_t>(date_string.length()));
}
string16 TimeFormatWithoutAmPm(const icu::DateFormat* formatter,
const Time& time) {
DCHECK(formatter);
icu::UnicodeString time_string;
icu::FieldPosition ampm_field(icu::DateFormat::kAmPmField);
formatter->format(
static_cast<UDate>(time.ToDoubleT() * 1000), time_string, ampm_field);
int ampm_length = ampm_field.getEndIndex() - ampm_field.getBeginIndex();
if (ampm_length) {
int begin = ampm_field.getBeginIndex();
// Doesn't include any spacing before the field.
if (begin)
begin--;
time_string.removeBetween(begin, ampm_field.getEndIndex());
}
return string16(time_string.getBuffer(),
static_cast<size_t>(time_string.length()));
}
icu::SimpleDateFormat CreateSimpleDateFormatter(const char* pattern) {
// Generate a locale-dependent format pattern. The generator will take
// care of locale-dependent formatting issues like which separator to
// use (some locales use '.' instead of ':'), and where to put the am/pm
// marker.
UErrorCode status = U_ZERO_ERROR;
scoped_ptr<icu::DateTimePatternGenerator> generator(
icu::DateTimePatternGenerator::createInstance(status));
DCHECK(U_SUCCESS(status));
icu::UnicodeString generated_pattern =
generator->getBestPattern(icu::UnicodeString(pattern), status);
DCHECK(U_SUCCESS(status));
// Then, format the time using the generated pattern.
icu::SimpleDateFormat formatter(generated_pattern, status);
DCHECK(U_SUCCESS(status));
return formatter;
}
} // namespace
string16 TimeFormatTimeOfDay(const Time& time) {
// We can omit the locale parameter because the default should match
// Chrome's application locale.
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createTimeInstance(icu::DateFormat::kShort));
return TimeFormat(formatter.get(), time);
}
string16 TimeFormatTimeOfDayWithMilliseconds(const Time& time) {
icu::SimpleDateFormat formatter = CreateSimpleDateFormatter("HmsSSS");
return TimeFormatWithoutAmPm(&formatter, time);
}
string16 TimeFormatTimeOfDayWithHourClockType(const Time& time,
HourClockType type,
AmPmClockType ampm) {
// Just redirect to the normal function if the default type matches the
// given type.
HourClockType default_type = GetHourClockType();
if (default_type == type && (type == k24HourClock || ampm == kKeepAmPm)) {
return TimeFormatTimeOfDay(time);
}
const char* base_pattern = (type == k12HourClock ? "ahm" : "Hm");
icu::SimpleDateFormat formatter = CreateSimpleDateFormatter(base_pattern);
if (ampm == kKeepAmPm) {
return TimeFormat(&formatter, time);
} else {
return TimeFormatWithoutAmPm(&formatter, time);
}
}
string16 TimeFormatShortDate(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateInstance(icu::DateFormat::kMedium));
return TimeFormat(formatter.get(), time);
}
string16 TimeFormatShortDateNumeric(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateInstance(icu::DateFormat::kShort));
return TimeFormat(formatter.get(), time);
}
string16 TimeFormatShortDateAndTime(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kShort));
return TimeFormat(formatter.get(), time);
}
string16 TimeFormatShortDateAndTimeWithTimeZone(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(icu::DateFormat::createDateTimeInstance(
icu::DateFormat::kShort, icu::DateFormat::kLong));
return TimeFormat(formatter.get(), time);
}
string16 TimeFormatFriendlyDateAndTime(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull));
return TimeFormat(formatter.get(), time);
}
string16 TimeFormatFriendlyDate(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(icu::DateFormat::createDateInstance(
icu::DateFormat::kFull));
return TimeFormat(formatter.get(), time);
}
HourClockType GetHourClockType() {
// TODO(satorux,jshin): Rework this with ures_getByKeyWithFallback()
// once it becomes public. The short time format can be found at
// "calendar/gregorian/DateTimePatterns/3" in the resources.
scoped_ptr<icu::SimpleDateFormat> formatter(
static_cast<icu::SimpleDateFormat*>(
icu::DateFormat::createTimeInstance(icu::DateFormat::kShort)));
// Retrieve the short time format.
icu::UnicodeString pattern_unicode;
formatter->toPattern(pattern_unicode);
// Determine what hour clock type the current locale uses, by checking
// "a" (am/pm marker) in the short time format. This is reliable as "a"
// is used by all of 12-hour clock formats, but not any of 24-hour clock
// formats, as shown below.
//
// % grep -A4 DateTimePatterns third_party/icu/source/data/locales/*.txt |
// grep -B1 -- -- |grep -v -- '--' |
// perl -nle 'print $1 if /^\S+\s+"(.*)"/' |sort -u
//
// H.mm
// H:mm
// HH.mm
// HH:mm
// a h:mm
// ah:mm
// ahh:mm
// h-mm a
// h:mm a
// hh:mm a
//
// See http://userguide.icu-project.org/formatparse/datetime for details
// about the date/time format syntax.
if (pattern_unicode.indexOf('a') == -1) {
return k24HourClock;
} else {
return k12HourClock;
}
}
} // namespace base
|