add parse

This commit is contained in:
2020-05-30 01:01:50 +08:00
parent 7eca5520d7
commit 38d8f7c3cf

View File

@@ -1,6 +1,9 @@
#[macro_use] extern crate quick_error;
use chrono::{ Local,prelude::*, };
use std::str::Chars;
use std::iter::Peekable;
quick_error! {
#[derive(Debug)]
pub enum ParseError {
@@ -10,42 +13,108 @@ quick_error! {
}
}
#[derive(Debug)]
enum SimpleDateFormatPart {
Year,
Month,
YearLower(usize),
YearUpper(usize),
MonthLower(usize),
MonthUpper(usize),
Day,
Hour,
Minute,
Second,
LiteralChar(char),
Literal(String),
}
#[derive(Debug)]
pub struct SimpleDateFormat {
parts: Vec<SimpleDateFormatPart>,
}
impl SimpleDateFormat {
fn format_local(&self, date_time: &DateTime<Local>) -> String {
pub fn format_local(&self, date_time: &DateTime<Local>) -> String {
let mut ret = String::with_capacity(512);
ret.push_str(&format!("{}", date_time.year()));
ret.push('-');
ret.push_str(&format!("{}", date_time.month()));
ret.push('-');
ret.push_str(&format!("{}", date_time.day()));
for part in &self.parts {
match part {
SimpleDateFormatPart::LiteralChar(c) => ret.push(*c),
SimpleDateFormatPart::Literal(s) => ret.push_str(s),
SimpleDateFormatPart::YearLower(cnt) => ret.push_str(&format_str(date_time.year(), *cnt)),
SimpleDateFormatPart::MonthLower(cnt) => ret.push_str(&format_str(date_time.month() as i32, *cnt)),
_ => (),
}
}
ret
}
}
pub fn fmt(f: &str) -> Result<SimpleDateFormat, ParseError> {
Ok(SimpleDateFormat{ parts: vec![] })
let mut parts = vec![];
let mut is_in_quotation_mark = false;
let mut literal = String::new();
let mut chars = f.chars().peekable();
while let Some(c) = chars.next() {
if is_in_quotation_mark && c != '\'' {
literal.push(c);
continue;
}
match c {
'\'' => if is_in_quotation_mark {
if let Some('\'') = chars.peek() {
literal.push(c);
chars.next(); // eat '\''
} else {
is_in_quotation_mark = false;
parts.push(SimpleDateFormatPart::Literal(literal));
literal = String::new();
}
} else {
is_in_quotation_mark = true;
},
',' | '.' | ':' | '-' | ' ' => parts.push(SimpleDateFormatPart::LiteralChar(c)),
'y' => parts.push(SimpleDateFormatPart::YearLower(get_all_chars(c, &mut chars))),
'Y' => parts.push(SimpleDateFormatPart::YearUpper(get_all_chars(c, &mut chars))),
'm' => parts.push(SimpleDateFormatPart::MonthLower(get_all_chars(c, &mut chars))),
'M' => parts.push(SimpleDateFormatPart::MonthUpper(get_all_chars(c, &mut chars))),
_ => (),
}
}
Ok(SimpleDateFormat{ parts })
// Err(ParseError::Format(f.into()))
}
fn format_str(n: i32, cnt: usize) -> String {
let ret = format!("{}", n);
if cnt > ret.len() {
"0".repeat(cnt - ret.len()) + &ret
} else {
ret
}
}
fn get_all_chars(c: char, chars: &mut Peekable<Chars>) -> usize {
let mut cnt = 1_usize;
while let Some(next_char) = chars.peek() {
if *next_char == c {
cnt += 1;
chars.next();
} else {
break;
}
}
cnt
}
#[test]
fn it_works() {
println!("test output: {}", fmt("").unwrap().format_local(&Local::now()));
// println!("test output: {}", fmt("").unwrap().format_local(&Local::now()));
println!("{:?}", fmt("y yy-mm 'mm '''"));
println!("{:?}", fmt("y yy-mm'(-'m')' '[mm]'").unwrap().format_local(&Local::now()));
assert_eq!(2 + 2, 4);
}