aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authortigercosmos <phy.tiger@gmail.com>2017-12-14 21:23:06 +0800
committertigercosmos <phy.tiger@gmail.com>2017-12-17 16:57:01 +0800
commit54c6028033d07d9104f58beb3d92bcc819600d93 (patch)
treeeecab9c0387eb4cc46ba45b4b893401b262a7609 /components
parentb93579a8f0e59c8102a243133455d8012e82e415 (diff)
downloadservo-54c6028033d07d9104f58beb3d92bcc819600d93.tar.gz
servo-54c6028033d07d9104f58beb3d92bcc819600d93.zip
implement valid week string
Diffstat (limited to 'components')
-rw-r--r--components/script/Cargo.toml1
-rw-r--r--components/script/dom/bindings/str.rs67
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs6
-rw-r--r--components/script/lib.rs1
4 files changed, 74 insertions, 1 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index 5561cd7dd95..8c3c77ed27c 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -39,6 +39,7 @@ byteorder = "1.0"
canvas_traits = {path = "../canvas_traits"}
caseless = "0.1.0"
cookie = "0.10"
+chrono = "0.4"
cssparser = "0.23.0"
deny_public_fields = {path = "../deny_public_fields"}
devtools_traits = {path = "../devtools_traits"}
diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs
index 596b2db14b2..83c438a26e7 100644
--- a/components/script/dom/bindings/str.rs
+++ b/components/script/dom/bindings/str.rs
@@ -4,6 +4,8 @@
//! The `ByteString` struct.
+use chrono::{Datelike, TimeZone};
+use chrono::prelude::{Weekday, Utc};
use cssparser::CowRcStr;
use html5ever::{LocalName, Namespace};
use servo_atoms::Atom;
@@ -293,6 +295,13 @@ impl DOMString {
pub fn is_valid_month_string(&self) -> bool {
parse_month_string(&*self.0).is_ok()
}
+
+ /// A valid week string should be like {YYYY}-W{WW}, such as "2017-W52"
+ /// YYYY must be four or more digits, WW both must be two digits
+ /// https://html.spec.whatwg.org/multipage/#valid-week-string
+ pub fn is_valid_week_string(&self) -> bool {
+ parse_week_string(&*self.0).is_ok()
+ }
}
impl Borrow<str> for DOMString {
@@ -445,6 +454,48 @@ fn parse_date_string(value: &str) -> Result<(u32, u32, u32), ()> {
Ok((year_int, month_int, day_int))
}
+/// https://html.spec.whatwg.org/multipage/#parse-a-week-string
+fn parse_week_string(value: &str) -> Result<(u32, u32), ()> {
+ // Step 1, 2, 3
+ let mut iterator = value.split('-');
+ let year = iterator.next().ok_or(())?;
+
+ // Step 4
+ let year_int = year.parse::<u32>().map_err(|_| ())?;
+ if year.len() < 4 || year_int == 0 {
+ return Err(());
+ }
+
+ // Step 5, 6
+ let week = iterator.next().ok_or(())?;
+ let (week_first, week_last) = week.split_at(1);
+ if week_first != "W" {
+ return Err(());
+ }
+
+ // Step 7
+ let week_int = week_last.parse::<u32>().map_err(|_| ())?;
+ if week_last.len() != 2 {
+ return Err(());
+ }
+
+ // Step 8
+ let max_week = max_week_in_year(year_int);
+
+ // Step 9
+ if week_int < 1 || week_int > max_week {
+ return Err(());
+ }
+
+ // Step 10
+ if iterator.next().is_some() {
+ return Err(());
+ }
+
+ // Step 11
+ Ok((year_int, week_int))
+}
+
/// https://html.spec.whatwg.org/multipage/#parse-a-month-component
fn parse_month_component(value: &str) -> Result<(u32, u32), ()> {
// Step 3
@@ -495,7 +546,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
1|3|5|7|8|10|12 => Ok(31),
4|6|9|11 => Ok(30),
2 => {
- if year_num % 400 == 0 || (year_num % 4 == 0 && year_num % 100 != 0) {
+ if is_leap_year(year_num) {
Ok(29)
} else {
Ok(28)
@@ -504,3 +555,17 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
_ => Err(())
}
}
+
+// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day
+fn max_week_in_year(year: u32) -> u32 {
+ match Utc.ymd(year as i32, 1, 1).weekday() {
+ Weekday::Thu => 53,
+ Weekday::Wed if is_leap_year(year) => 53,
+ _ => 52
+ }
+}
+
+#[inline]
+fn is_leap_year(year: u32) -> bool {
+ year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)
+}
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index a951c49f80c..8c5699446ef 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -1005,6 +1005,12 @@ impl HTMLInputElement {
*textinput.single_line_content_mut() = "".into();
}
}
+ InputType::Week => {
+ let mut textinput = self.textinput.borrow_mut();
+ if !textinput.single_line_content().is_valid_week_string() {
+ *textinput.single_line_content_mut() = "".into();
+ }
+ }
InputType::Color => {
let mut textinput = self.textinput.borrow_mut();
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 3bae98a1a06..3143342e4f6 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -31,6 +31,7 @@ extern crate bluetooth_traits;
extern crate byteorder;
extern crate canvas_traits;
extern crate caseless;
+extern crate chrono;
extern crate cookie as cookie_rs;
#[macro_use] extern crate cssparser;
#[macro_use] extern crate deny_public_fields;