Merge pull request #449 from matthiasbeyer/libimagtimeui/init
Libimagtimeui/init
This commit is contained in:
commit
e416c1be96
7 changed files with 336 additions and 0 deletions
14
libimagtimeui/Cargo.toml
Normal file
14
libimagtimeui/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "libimagtimeui"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
lazy_static = "0.1"
|
||||||
|
log = "0.3"
|
||||||
|
chrono = "0.2"
|
||||||
|
regex = "0.1"
|
||||||
|
|
||||||
|
[dependencies.libimagerror]
|
||||||
|
path = "../libimagerror"
|
||||||
|
|
110
libimagtimeui/src/date.rs
Normal file
110
libimagtimeui/src/date.rs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
use chrono::naive::date::NaiveDate as ChronoNaiveDate;
|
||||||
|
|
||||||
|
use parse::Parse;
|
||||||
|
|
||||||
|
pub struct Date {
|
||||||
|
year: i32,
|
||||||
|
month: u32,
|
||||||
|
day: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Date {
|
||||||
|
|
||||||
|
pub fn new(year: i32, month: u32, day: u32) -> Date {
|
||||||
|
Date {
|
||||||
|
year: year,
|
||||||
|
month: month,
|
||||||
|
day: day,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn year(&self) -> i32 {
|
||||||
|
self.year
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn month(&self) -> u32 {
|
||||||
|
self.month
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn day(&self) -> u32 {
|
||||||
|
self.day
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<ChronoNaiveDate> for Date {
|
||||||
|
|
||||||
|
fn into(self) -> ChronoNaiveDate {
|
||||||
|
ChronoNaiveDate::from_ymd(self.year, self.month, self.day)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for Date {
|
||||||
|
|
||||||
|
/// Parse the date part of the full string into a Date object
|
||||||
|
fn parse(s: &str) -> Option<Date> {
|
||||||
|
use std::str::FromStr;
|
||||||
|
use regex::Regex;
|
||||||
|
use parse::time_parse_regex;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref R: Regex = Regex::new(time_parse_regex()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
R.captures(s)
|
||||||
|
.and_then(|capts| {
|
||||||
|
let year = capts.name("Y").and_then(|o| FromStr::from_str(o).ok());
|
||||||
|
let month = capts.name("M").and_then(|o| FromStr::from_str(o).ok());
|
||||||
|
let day = capts.name("D").and_then(|o| FromStr::from_str(o).ok());
|
||||||
|
|
||||||
|
if year.is_none() {
|
||||||
|
debug!("No year");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if month.is_none() {
|
||||||
|
debug!("No month");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if day.is_none() {
|
||||||
|
debug!("No day");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Date::new(year.unwrap(), month.unwrap(), day.unwrap()))
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::Date;
|
||||||
|
use parse::Parse;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_valid() {
|
||||||
|
let s = "2016-02-01";
|
||||||
|
let d = Date::parse(s);
|
||||||
|
|
||||||
|
assert!(d.is_some());
|
||||||
|
let d = d.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(2016, d.year());
|
||||||
|
assert_eq!(2, d.month());
|
||||||
|
assert_eq!(1, d.day());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid() {
|
||||||
|
assert!(Date::parse("2016-021-01").is_none());
|
||||||
|
assert!(Date::parse("2016-02-012").is_none());
|
||||||
|
assert!(Date::parse("2016-02-0").is_none());
|
||||||
|
assert!(Date::parse("2016-0-02").is_none());
|
||||||
|
assert!(Date::parse("2016-02").is_none());
|
||||||
|
assert!(Date::parse("2016-2").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
48
libimagtimeui/src/datetime.rs
Normal file
48
libimagtimeui/src/datetime.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
use chrono::naive::datetime::NaiveDateTime as ChronoNaiveDateTime;
|
||||||
|
|
||||||
|
use parse::Parse;
|
||||||
|
use date::Date;
|
||||||
|
use time::Time;
|
||||||
|
|
||||||
|
pub struct DateTime {
|
||||||
|
date: Date,
|
||||||
|
time: Time,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DateTime {
|
||||||
|
|
||||||
|
pub fn new(date: Date, time: Time) -> DateTime {
|
||||||
|
DateTime {
|
||||||
|
date: date,
|
||||||
|
time: time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn date(&self) -> &Date {
|
||||||
|
&self.date
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn time(&self) -> &Time {
|
||||||
|
&self.time
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<ChronoNaiveDateTime> for DateTime {
|
||||||
|
|
||||||
|
fn into(self) -> ChronoNaiveDateTime {
|
||||||
|
ChronoNaiveDateTime::new(self.date.into(), self.time.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for DateTime {
|
||||||
|
|
||||||
|
fn parse(s: &str) -> Option<DateTime> {
|
||||||
|
Date::parse(s)
|
||||||
|
.and_then(|d| Time::parse(s).map(|t| (d, t)))
|
||||||
|
.map(|(d, t)| DateTime::new(d, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
12
libimagtimeui/src/lib.rs
Normal file
12
libimagtimeui/src/lib.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
extern crate chrono;
|
||||||
|
extern crate regex;
|
||||||
|
#[macro_use] extern crate lazy_static;
|
||||||
|
#[macro_use] extern crate log;
|
||||||
|
|
||||||
|
#[macro_use] extern crate libimagerror;
|
||||||
|
|
||||||
|
pub mod date;
|
||||||
|
pub mod datetime;
|
||||||
|
pub mod parse;
|
||||||
|
pub mod time;
|
||||||
|
|
10
libimagtimeui/src/parse.rs
Normal file
10
libimagtimeui/src/parse.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
pub trait Parse : Sized {
|
||||||
|
|
||||||
|
fn parse(s: &str) -> Option<Self>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn time_parse_regex() -> &'static str {
|
||||||
|
r#"(?P<Y>\d{4})-(?P<M>\d{2})-(?P<D>\d{2})(T(?P<h>\d{2})(:(?P<m>\d{2})(:(?P<s>\d{2}))?)?)?$"#
|
||||||
|
}
|
||||||
|
|
130
libimagtimeui/src/time.rs
Normal file
130
libimagtimeui/src/time.rs
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
use chrono::naive::time::NaiveTime as ChronoNaiveTime;
|
||||||
|
|
||||||
|
use parse::Parse;
|
||||||
|
|
||||||
|
pub struct Time {
|
||||||
|
hour: u32,
|
||||||
|
minute: u32,
|
||||||
|
second: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Time {
|
||||||
|
|
||||||
|
pub fn new(hour: u32, minute: u32, second: u32) -> Time {
|
||||||
|
Time {
|
||||||
|
hour: hour,
|
||||||
|
minute: minute,
|
||||||
|
second: second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hour(&self) -> u32 {
|
||||||
|
self.hour
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn minute(&self) -> u32 {
|
||||||
|
self.minute
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn second(&self) -> u32 {
|
||||||
|
self.second
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<ChronoNaiveTime> for Time {
|
||||||
|
|
||||||
|
fn into(self) -> ChronoNaiveTime {
|
||||||
|
ChronoNaiveTime::from_hms(self.hour, self.minute, self.second)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for Time {
|
||||||
|
|
||||||
|
fn parse(s: &str) -> Option<Time> {
|
||||||
|
use std::str::FromStr;
|
||||||
|
use regex::Regex;
|
||||||
|
use parse::time_parse_regex;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref R: Regex = Regex::new(time_parse_regex()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
R.captures(s)
|
||||||
|
.and_then(|capts| {
|
||||||
|
let hour = capts.name("h").and_then(|o| FromStr::from_str(o).ok());
|
||||||
|
let minute = capts.name("m").and_then(|o| FromStr::from_str(o).ok()).unwrap_or(0);
|
||||||
|
let second = capts.name("s").and_then(|o| FromStr::from_str(o).ok()).unwrap_or(0);
|
||||||
|
|
||||||
|
if hour.is_none() {
|
||||||
|
debug!("No hour");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Time::new(hour.unwrap(), minute, second))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::Time;
|
||||||
|
use parse::Parse;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_valid() {
|
||||||
|
let s = "2016-12-12T20:01:02";
|
||||||
|
let t = Time::parse(s);
|
||||||
|
|
||||||
|
assert!(t.is_some());
|
||||||
|
let t = t.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(20, t.hour());
|
||||||
|
assert_eq!(1, t.minute());
|
||||||
|
assert_eq!(2, t.second());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_valid_without_sec() {
|
||||||
|
let s = "2016-12-12T20:01";
|
||||||
|
let t = Time::parse(s);
|
||||||
|
|
||||||
|
assert!(t.is_some());
|
||||||
|
let t = t.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(20, t.hour());
|
||||||
|
assert_eq!(1, t.minute());
|
||||||
|
assert_eq!(0, t.second());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_valid_without_min() {
|
||||||
|
let s = "2016-12-12T20";
|
||||||
|
let t = Time::parse(s);
|
||||||
|
|
||||||
|
assert!(t.is_some());
|
||||||
|
let t = t.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(20, t.hour());
|
||||||
|
assert_eq!(0, t.minute());
|
||||||
|
assert_eq!(0, t.second());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid() {
|
||||||
|
assert!(Time::parse("2015-12-12T").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T200").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T20-20").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T20:200").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T20:20:200").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T20:20:").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T20:").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T2:20:21").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T2:2:20").is_none());
|
||||||
|
assert!(Time::parse("2015-12-12T2:2:2").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
12
libimagtimeui/src/ui.rs
Normal file
12
libimagtimeui/src/ui.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
pub fn time_ui_fmtstr() -> &'static str {
|
||||||
|
"YYYY-MM-DD[THH[:mm[:ss]]]"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn time_ui_fmtstr_expl() -> &'static str {
|
||||||
|
#r"In the UI, the format for Time is always YEAR-MONTH-DAY.
|
||||||
|
Optionally, Time can be specified by seperating it from the date with 'T'.
|
||||||
|
Minutes and Seconds are optional.
|
||||||
|
"#
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue