Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(558)

Unified Diff: content/renderer/date_time_formatter.cc

Issue 12191005: Move Android Date/Time parsing to the renderer (C++ and ICU) instead of the current parsing that ha… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased view_messages.h and fixed the link issue on the linux bot Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/date_time_formatter.cc
diff --git a/content/renderer/date_time_formatter.cc b/content/renderer/date_time_formatter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..eca5b9773e8bcf2deb35f041d3c4472bd3c00cee
--- /dev/null
+++ b/content/renderer/date_time_formatter.cc
@@ -0,0 +1,193 @@
+// Copyright (c) 2013 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 "content/renderer/date_time_formatter.h"
+
+#include "base/string_util.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDateTimeChooserParams.h"
+#include "third_party/icu/public/i18n/unicode/smpdtfmt.h"
+
+
+namespace content {
+
+void DateTimeFormatter::CreatePatternMap() {
+ // Initialize all the UI elements with empty patterns,
+ // then fill in the ones that are actually date/time inputs and
+ // are implemented.
+ for (int i = 0 ; i <= ui::TEXT_INPUT_TYPE_MAX; ++i) {
+ patterns_[i] = "";
+ }
+ patterns_[ui::TEXT_INPUT_TYPE_DATE] = "yyyy-MM-dd";
+ patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME] = "yyyy-MM-dd'T'HH:mm'Z'";
+ patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL] = "yyyy-MM-dd'T'HH:mm";
+ patterns_[ui::TEXT_INPUT_TYPE_MONTH] = "yyyy-MM";
+ patterns_[ui::TEXT_INPUT_TYPE_TIME] = "HH:mm";
+}
+
+DateTimeFormatter::DateTimeFormatter(
+ const WebKit::WebDateTimeChooserParams& source)
+ : formatted_string_(source.currentValue.utf8()) {
+ CreatePatternMap();
+ ExtractType(source);
+ if (!ParseValues()) {
+ type_ = ui::TEXT_INPUT_TYPE_NONE;
+ ClearAll();
+ LOG(WARNING) << "Problems parsing input <" << formatted_string_ << ">";
+ }
+}
+
+DateTimeFormatter::DateTimeFormatter(
+ ui::TextInputType type,
+ int year, int month, int day, int hour, int minute, int second)
+ : type_(type),
+ year_(year),
+ month_(month),
+ day_(day),
+ hour_(hour),
+ minute_(minute),
+ second_(second) {
+ CreatePatternMap();
+ pattern_ = type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX ?
+ &patterns_[type_] : &patterns_[ui::TEXT_INPUT_TYPE_NONE];
+
+ std::string patt;
+ pattern_->toUTF8String(patt);
+ formatted_string_ = FormatString();
+}
+
+DateTimeFormatter::~DateTimeFormatter() {
+}
+
+int DateTimeFormatter::GetYear() const {
+ return year_;
+}
+
+int DateTimeFormatter::GetMonth() const {
+ return month_;
+}
+
+int DateTimeFormatter::GetDay() const {
+ return day_;
+}
+
+int DateTimeFormatter::GetHour() const {
+ return hour_;
+}
+
+int DateTimeFormatter::GetMinute() const {
+ return minute_;
+}
+
+int DateTimeFormatter::GetSecond() const {
+ return second_;
+}
+
+ui::TextInputType DateTimeFormatter::GetType() const {
+ return type_;
+}
+
+const std::string& DateTimeFormatter::GetFormattedValue() const {
+ return formatted_string_;
+}
+
+const std::string DateTimeFormatter::FormatString() const {
+ UErrorCode success = U_ZERO_ERROR;
+ if (year_ == 0 && month_ == 0 && day_ == 0 &&
+ hour_ == 0 && minute_ == 0 && second_ == 0) {
+ return "";
+ }
+
+ std::string result;
+ const icu::GregorianCalendar calendar(
+ year_, month_, day_, hour_, minute_, second_, success);
+ if (success <= U_ZERO_ERROR) {
+ UDate time = calendar.getTime(success);
+ icu::SimpleDateFormat formatter(*pattern_, success);
+ icu::UnicodeString formattedTime;
+ formatter.format(time, formattedTime, success);
+ formattedTime.toUTF8String(result);
+ if (success <= U_ZERO_ERROR)
+ return result;
+ }
+ LOG(WARNING) << "Calendar not created: error " << success;
+ return "";
+}
+
+void DateTimeFormatter::ExtractType(
+ const WebKit::WebDateTimeChooserParams& source) {
+ switch (source.type) {
+ case WebKit::WebDateTimeInputTypeDate:
+ type_ = ui::TEXT_INPUT_TYPE_DATE;
+ break;
+ case WebKit::WebDateTimeInputTypeDateTime:
+ type_ = ui::TEXT_INPUT_TYPE_DATE_TIME;
+ break;
+ case WebKit::WebDateTimeInputTypeDateTimeLocal:
+ type_ = ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL;
+ break;
+ case WebKit::WebDateTimeInputTypeMonth:
+ type_ = ui::TEXT_INPUT_TYPE_MONTH;
+ break;
+ case WebKit::WebDateTimeInputTypeTime:
+ type_ = ui::TEXT_INPUT_TYPE_TIME;
+ break;
+ case WebKit::WebDateTimeInputTypeWeek: // Not implemented
+ case WebKit::WebDateTimeInputTypeNone:
+ default:
+ type_ = ui::TEXT_INPUT_TYPE_NONE;
+ }
+}
+
+// Not all fields are defined in all configurations and ICU might store
+// garbage if success <= U_ZERO_ERROR so the output is sanitized here.
+int DateTimeFormatter::ExtractValue(
+ const icu::Calendar* calendar, UCalendarDateFields value) const {
+ UErrorCode success = U_ZERO_ERROR;
+ int result = calendar->get(value, success);
+ return (success <= U_ZERO_ERROR) ? result : 0;
+}
+
+bool DateTimeFormatter::ParseValues() {
+ if (type_ == ui::TEXT_INPUT_TYPE_NONE) {
+ ClearAll();
+ return false;
+ }
+
+ if (formatted_string_.empty()) {
+ ClearAll();
+ return true;
+ }
+
+ UErrorCode success = U_ZERO_ERROR;
+ icu::UnicodeString icu_value =
+ icu::UnicodeString::fromUTF8(formatted_string_);
+ if (type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX) {
+ const icu::UnicodeString pattern = patterns_[type_];
+ icu::SimpleDateFormat formatter(pattern, success);
+ formatter.parse(icu_value, success);
+ if (success <= U_ZERO_ERROR) {
+ const icu::Calendar* cal = formatter.getCalendar();
+ year_ = ExtractValue(cal, UCAL_YEAR);
+ month_ = ExtractValue(cal, UCAL_MONTH);
+ day_ = ExtractValue(cal, UCAL_DATE);
+ hour_ = ExtractValue(cal, UCAL_HOUR_OF_DAY); // 24h format
+ minute_ = ExtractValue(cal, UCAL_MINUTE);
+ second_ = ExtractValue(cal, UCAL_SECOND);
+ }
+ }
+
+ return (success <= U_ZERO_ERROR);
+}
+
+void DateTimeFormatter::ClearAll() {
+ year_ = 0;
+ month_ = 0;
+ day_ = 0;
+ hour_ = 0;
+ minute_ = 0;
+ second_ = 0;
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698