Update function names in BrowserContextKeyedServiceFactory::GetServiceForBrowserConte...
[chromium-blink-merge.git] / content / renderer / date_time_formatter.cc
blobf9d02edff845015720043182637f51bc992eb03c
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/date_time_formatter.h"
7 #include "base/strings/string_util.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "third_party/WebKit/public/platform/WebCString.h"
10 #include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
11 #include "third_party/icu/public/i18n/unicode/smpdtfmt.h"
14 namespace content {
16 void DateTimeFormatter::CreatePatternMap() {
17 // Initialize all the UI elements with empty patterns,
18 // then fill in the ones that are actually date/time inputs and
19 // are implemented.
20 for (int i = 0 ; i <= ui::TEXT_INPUT_TYPE_MAX; ++i) {
21 patterns_[i] = "";
23 patterns_[ui::TEXT_INPUT_TYPE_DATE] = "yyyy-MM-dd";
24 patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME] = "yyyy-MM-dd'T'HH:mm'Z'";
25 patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL] = "yyyy-MM-dd'T'HH:mm";
26 patterns_[ui::TEXT_INPUT_TYPE_MONTH] = "yyyy-MM";
27 patterns_[ui::TEXT_INPUT_TYPE_TIME] = "HH:mm";
28 patterns_[ui::TEXT_INPUT_TYPE_WEEK] = "Y-'W'ww";
31 DateTimeFormatter::DateTimeFormatter(
32 const WebKit::WebDateTimeChooserParams& source)
33 : formatted_string_(source.currentValue.utf8()) {
34 CreatePatternMap();
35 ExtractType(source);
36 if (!ParseValues()) {
37 type_ = ui::TEXT_INPUT_TYPE_NONE;
38 ClearAll();
39 LOG(WARNING) << "Problems parsing input <" << formatted_string_ << ">";
43 DateTimeFormatter::DateTimeFormatter(
44 ui::TextInputType type,
45 int year, int month, int day, int hour, int minute, int second,
46 int week_year, int week)
47 : type_(type),
48 year_(year),
49 month_(month),
50 day_(day),
51 hour_(hour),
52 minute_(minute),
53 second_(second),
54 week_year_(week_year),
55 week_(week) {
56 CreatePatternMap();
57 pattern_ = type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX ?
58 &patterns_[type_] : &patterns_[ui::TEXT_INPUT_TYPE_NONE];
60 formatted_string_ = FormatString();
63 DateTimeFormatter::~DateTimeFormatter() {
66 int DateTimeFormatter::GetYear() const {
67 return year_;
70 int DateTimeFormatter::GetMonth() const {
71 return month_;
74 int DateTimeFormatter::GetDay() const {
75 return day_;
78 int DateTimeFormatter::GetHour() const {
79 return hour_;
82 int DateTimeFormatter::GetMinute() const {
83 return minute_;
86 int DateTimeFormatter::GetSecond() const {
87 return second_;
90 int DateTimeFormatter::GetWeekYear() const {
91 return week_year_;
94 int DateTimeFormatter::GetWeek() const {
95 return week_;
98 ui::TextInputType DateTimeFormatter::GetType() const {
99 return type_;
102 const std::string& DateTimeFormatter::GetFormattedValue() const {
103 return formatted_string_;
106 const std::string DateTimeFormatter::FormatString() const {
107 UErrorCode success = U_ZERO_ERROR;
108 if (year_ == 0 && month_ == 0 && day_ == 0 &&
109 hour_ == 0 && minute_ == 0 && second_ == 0 &&
110 week_year_ == 0 && week_ == 0) {
111 return std::string();
114 std::string result;
115 icu::GregorianCalendar calendar(success);
116 if (success <= U_ZERO_ERROR) {
117 if (type_ == ui::TEXT_INPUT_TYPE_WEEK) {
118 // An ISO week starts with Monday.
119 calendar.setFirstDayOfWeek(UCAL_MONDAY);
120 // ISO 8601 defines that the week with the year's first Thursday is the
121 // first week.
122 calendar.setMinimalDaysInFirstWeek(4);
123 calendar.set(UCAL_YEAR_WOY, week_year_);
124 calendar.set(UCAL_WEEK_OF_YEAR, week_);
125 } else {
126 calendar.set(UCAL_YEAR, year_);
127 calendar.set(UCAL_MONTH, month_);
128 calendar.set(UCAL_DATE, day_);
129 calendar.set(UCAL_HOUR_OF_DAY, hour_);
130 calendar.set(UCAL_MINUTE, minute_);
131 calendar.set(UCAL_SECOND, second_);
133 icu::SimpleDateFormat formatter(*pattern_, success);
134 icu::UnicodeString formatted_time;
135 formatter.format(calendar, formatted_time, NULL, success);
136 UTF16ToUTF8(formatted_time.getBuffer(),
137 static_cast<size_t>(formatted_time.length()),
138 &result);
139 if (success <= U_ZERO_ERROR)
140 return result;
142 LOG(WARNING) << "Calendar not created: error " << success;
143 return std::string();
146 void DateTimeFormatter::ExtractType(
147 const WebKit::WebDateTimeChooserParams& source) {
148 switch (source.type) {
149 case WebKit::WebDateTimeInputTypeDate:
150 type_ = ui::TEXT_INPUT_TYPE_DATE;
151 break;
152 case WebKit::WebDateTimeInputTypeDateTime:
153 type_ = ui::TEXT_INPUT_TYPE_DATE_TIME;
154 break;
155 case WebKit::WebDateTimeInputTypeDateTimeLocal:
156 type_ = ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL;
157 break;
158 case WebKit::WebDateTimeInputTypeMonth:
159 type_ = ui::TEXT_INPUT_TYPE_MONTH;
160 break;
161 case WebKit::WebDateTimeInputTypeTime:
162 type_ = ui::TEXT_INPUT_TYPE_TIME;
163 break;
164 case WebKit::WebDateTimeInputTypeWeek:
165 type_ = ui::TEXT_INPUT_TYPE_WEEK;
166 break;
167 case WebKit::WebDateTimeInputTypeNone:
168 default:
169 type_ = ui::TEXT_INPUT_TYPE_NONE;
173 // Not all fields are defined in all configurations and ICU might store
174 // garbage if success <= U_ZERO_ERROR so the output is sanitized here.
175 int DateTimeFormatter::ExtractValue(
176 const icu::Calendar* calendar, UCalendarDateFields value) const {
177 UErrorCode success = U_ZERO_ERROR;
178 int result = calendar->get(value, success);
179 return (success <= U_ZERO_ERROR) ? result : 0;
182 bool DateTimeFormatter::ParseValues() {
183 if (type_ == ui::TEXT_INPUT_TYPE_NONE) {
184 ClearAll();
185 return false;
188 if (formatted_string_.empty()) {
189 ClearAll();
190 return true;
193 UErrorCode success = U_ZERO_ERROR;
194 icu::UnicodeString icu_value = icu::UnicodeString::fromUTF8(
195 icu::StringPiece(formatted_string_.data(), formatted_string_.size()));
196 if (type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX) {
197 const icu::UnicodeString pattern = patterns_[type_];
198 icu::SimpleDateFormat formatter(pattern, success);
199 formatter.parse(icu_value, success);
200 if (success <= U_ZERO_ERROR) {
201 const icu::Calendar* cal = formatter.getCalendar();
202 year_ = ExtractValue(cal, UCAL_YEAR);
203 month_ = ExtractValue(cal, UCAL_MONTH);
204 day_ = ExtractValue(cal, UCAL_DATE);
205 hour_ = ExtractValue(cal, UCAL_HOUR_OF_DAY); // 24h format
206 minute_ = ExtractValue(cal, UCAL_MINUTE);
207 second_ = ExtractValue(cal, UCAL_SECOND);
208 week_year_ = ExtractValue(cal, UCAL_YEAR_WOY);
209 week_ = ExtractValue(cal, UCAL_WEEK_OF_YEAR);
213 return (success <= U_ZERO_ERROR);
216 void DateTimeFormatter::ClearAll() {
217 year_ = 0;
218 month_ = 0;
219 day_ = 0;
220 hour_ = 0;
221 minute_ = 0;
222 second_ = 0;
223 week_year_ = 0;
224 week_ = 0;
227 } // namespace content