summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authordfhoughton <dfhoughton@gmail.com>2018-12-26 19:21:56 -0500
committerdfhoughton <dfhoughton@gmail.com>2018-12-26 19:21:56 -0500
commit8f5db5ad6ec2ffc19bc9bab0edd3bf5efae08dec (patch)
treefc8fd55eb5dd42df7b4a7393743edf5fb8302c09 /src/lib.rs
parent8cea7658c88073b203bfbeed0ec640146ca6b4d3 (diff)
downloadtwo-timer-8f5db5ad6ec2ffc19bc9bab0edd3bf5efae08dec.zip
more refactoring in preparation for handling periods
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs252
1 files changed, 176 insertions, 76 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 5105eee..11baebf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -22,12 +22,18 @@ lazy_static! {
two_times -> <moment_or_period> <to> <moment_or_period>
to => [["to", "through", "until", "up to", "thru", "till"]] | r("-+")
moment_or_period => <moment> | <period>
- period => <named_period> | <modified_period>
- named_period => <a_day> | <a_month> <year>?
+ period => <named_period> | <specific_period>
+ specific_period => <modified_period> | <month_and_year>
+ month_and_year -> <a_month> <year>
+ named_period => <a_day> | <a_month>
modified_period => <modifier> <modifiable_period>
modifier => [["this", "last", "next"]]
modifiable_period => [["week", "month", "year", "pay period", "pp"]] | <a_month> | <a_day>
- moment -> <at_time_on>? <some_day> <at_time>? | <time>
+ moment -> <at_time_on>? <some_day> <at_time>? | <specific_time>
+ specific_time => <time> | <absolute_terminus>
+ absolute_terminus => <first_time> | <last_time>
+ first_time => [["the beginning", "the beginning of time", "the first moment", "the start", "the very start", "the first instant"]]
+ last_time => [["the end", "the end of time", "the very end", "the last moment", "eternity", "infinity", "doomsday", "the crack of doom"]]
some_day => <specific_day> | <relative_day>
specific_day => <adverb> | <date_with_year>
relative_day => ("bar")
@@ -126,10 +132,7 @@ pub fn parse(
}
let parse = parse.unwrap();
if parse.has("universal") {
- return Ok((
- chrono::MIN_DATE.and_hms_milli(0, 0, 0, 0),
- chrono::MAX_DATE.and_hms_milli(23, 59, 59, 999),
- ));
+ return Ok((first_moment(), last_moment()));
}
let parse = parse.name("particular").unwrap();
let now = if now.is_some() {
@@ -143,19 +146,13 @@ pub fn parse(
Period::Minute
};
if let Some(moment) = parse.name("one_time") {
- if moment.has("specific_day") {
- return specific_moment(moment, &now, &period);
- }
- if moment.has("relative_day") || moment.has("time") {
- return Ok(relative_moment(moment, &now, &now, true));
- }
- unreachable!();
+ return handle_one_time(moment, &now, &period);
}
if let Some(two_times) = parse.name("two_times") {
let first = &two_times.children().unwrap()[0];
let last = &two_times.children().unwrap()[2];
- if first.has("specific_day") {
- if last.has("specific_day") {
+ if specific(first, true) {
+ if specific(last, true) {
return match specific_moment(first, &now, &period) {
Ok((d1, _)) => match specific_moment(last, &now, &period) {
Ok((_, d2)) => {
@@ -178,7 +175,7 @@ pub fn parse(
Err(s) => Err(s),
};
}
- } else if last.has("specific_day") {
+ } else if specific(last, false) {
return match specific_moment(last, &now, &period) {
Ok((_, d2)) => {
let (d1, _) = relative_moment(first, &now, &d2, true);
@@ -195,66 +192,21 @@ pub fn parse(
unreachable!();
}
-// add time to a date
-fn moment_and_time(
- m: DateTime<Utc>,
- default_period: &Period,
- daytime: Option<&Match>,
-) -> (DateTime<Utc>, DateTime<Utc>) {
- if let Some(daytime) = daytime {
- let (hour, minute, second) = time(daytime);
- let period = if second.is_some() {
- Period::Second
- } else if minute.is_some() {
- Period::Minute
- } else {
- Period::Hour
- };
- let m = m
- .with_hour(hour)
- .unwrap()
- .with_minute(minute.unwrap_or(0))
- .unwrap()
- .with_second(second.unwrap_or(0))
- .unwrap();
- moment_to_period(m, &period)
- } else {
- moment_to_period(m, default_period)
- }
+fn first_moment() -> DateTime<Utc> {
+ chrono::MIN_DATE.and_hms_milli(0, 0, 0, 0)
}
-fn relative_moment(
- m: &Match,
- now: &DateTime<Utc>,
- other_time: &DateTime<Utc>,
- before: bool,
-) -> (DateTime<Utc>, DateTime<Utc>) {
- if !m.has("some_day") {
- // necessarily just time
- if let Some(t) = m.name("time") {
- let (hour, minute, second) = time(t);
- let period = if second.is_some() {
- Period::Second
- } else if minute.is_some() {
- Period::Minute
- } else {
- Period::Hour
- };
- let mut t = other_time.with_hour(hour).unwrap().with_minute(minute.unwrap_or(0)).unwrap().with_second(second.unwrap_or(0)).unwrap();
- if before && t > *other_time {
- t = t - Duration::days(1);
- } else if !before && t < *other_time {
- t = t + Duration::days(1);
- }
- return moment_to_period(t, &period)
- } else {
- unreachable!();
- }
- }
- unimplemented!();
+fn last_moment() -> DateTime<Utc> {
+ chrono::MAX_DATE.and_hms_milli(23, 59, 59, 999)
}
-fn specific_moment(
+fn specific(m: &Match, first: bool) -> bool {
+ m.has("specific_day")
+ || m.has("specific_period")
+ || m.has("specific_time") && (first || m.has("absolute_terminus"))
+}
+
+fn handle_specific_day(
m: &Match,
now: &DateTime<Utc>,
period: &Period,
@@ -274,12 +226,12 @@ fn specific_moment(
'd' | 'D' => Ok(moment_and_time(now, &Period::Day, time)),
// tomorrow
'm' | 'M' => Ok(moment_and_time(now + Duration::days(1), &Period::Day, time)),
- _ => unreachable!()
+ _ => unreachable!(),
},
// yesterday
'y' | 'Y' => Ok(moment_and_time(now - Duration::days(1), &Period::Day, time)),
- _ => unreachable!()
- }
+ _ => unreachable!(),
+ };
}
if let Some(date) = m.name("date_with_year") {
if let Some(date) = date.name("n_date") {
@@ -343,6 +295,154 @@ fn specific_moment(
unimplemented!();
}
+fn handle_specific_period(
+ moment: &Match,
+ now: &DateTime<Utc>,
+ period: &Period,
+) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+ unimplemented!()
+}
+
+fn handle_specific_time(
+ moment: &Match,
+ now: &DateTime<Utc>,
+ other_time: &DateTime<Utc>,
+ before: bool,
+ period: &Period,
+) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+ if let Some(t) = moment.name("absolute_terminus") {
+ return if t.has("first_time") {
+ Ok(moment_to_period(first_moment(), period))
+ } else {
+ Ok((last_moment(), last_moment()))
+ }
+ }
+ if let Some(t) = moment.name("time") {
+ let (hour, minute, second) = time(t);
+ let period = if second.is_some() {
+ Period::Second
+ } else if minute.is_some() {
+ Period::Minute
+ } else {
+ Period::Hour
+ };
+ let mut t = other_time
+ .with_hour(hour)
+ .unwrap()
+ .with_minute(minute.unwrap_or(0))
+ .unwrap()
+ .with_second(second.unwrap_or(0))
+ .unwrap();
+ if before && t > *other_time {
+ t = t - Duration::days(1);
+ } else if !before && t < *other_time {
+ t = t + Duration::days(1);
+ }
+ return Ok(moment_to_period(t, &period));
+ } else {
+ unreachable!();
+ }
+}
+
+fn handle_one_time(
+ moment: &Match,
+ now: &DateTime<Utc>,
+ period: &Period,
+) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+ if moment.has("specific_day") {
+ return handle_specific_day(moment, now, period);
+ }
+ if let Some(moment) = moment.name("specific_period") {
+ return handle_specific_period(moment, now, period);
+ }
+ if let Some(moment) = moment.name("specific_time") {
+ return handle_specific_time(moment, now, now, true, period);
+ }
+ unimplemented!();
+}
+
+// add time to a date
+fn moment_and_time(
+ m: DateTime<Utc>,
+ default_period: &Period,
+ daytime: Option<&Match>,
+) -> (DateTime<Utc>, DateTime<Utc>) {
+ if let Some(daytime) = daytime {
+ let (hour, minute, second) = time(daytime);
+ let period = if second.is_some() {
+ Period::Second
+ } else if minute.is_some() {
+ Period::Minute
+ } else {
+ Period::Hour
+ };
+ let m = m
+ .with_hour(hour)
+ .unwrap()
+ .with_minute(minute.unwrap_or(0))
+ .unwrap()
+ .with_second(second.unwrap_or(0))
+ .unwrap();
+ moment_to_period(m, &period)
+ } else {
+ moment_to_period(m, default_period)
+ }
+}
+
+fn relative_moment(
+ m: &Match,
+ now: &DateTime<Utc>,
+ other_time: &DateTime<Utc>,
+ before: bool,
+) -> (DateTime<Utc>, DateTime<Utc>) {
+ if !m.has("some_day") {
+ // necessarily just time
+ if let Some(t) = m.name("time") {
+ let (hour, minute, second) = time(t);
+ let period = if second.is_some() {
+ Period::Second
+ } else if minute.is_some() {
+ Period::Minute
+ } else {
+ Period::Hour
+ };
+ let mut t = other_time
+ .with_hour(hour)
+ .unwrap()
+ .with_minute(minute.unwrap_or(0))
+ .unwrap()
+ .with_second(second.unwrap_or(0))
+ .unwrap();
+ if before && t > *other_time {
+ t = t - Duration::days(1);
+ } else if !before && t < *other_time {
+ t = t + Duration::days(1);
+ }
+ return moment_to_period(t, &period);
+ } else {
+ unreachable!();
+ }
+ }
+ unimplemented!();
+}
+
+fn specific_moment(
+ m: &Match,
+ now: &DateTime<Utc>,
+ period: &Period,
+) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+ if let Some(m) = m.name("specific_day") {
+ return handle_specific_day(m, now, period)
+ }
+ if let Some(m) = m.name("specific_period") {
+ return handle_specific_period(m, now, period)
+ }
+ if let Some(m) = m.name("specific_time") {
+ return handle_specific_time(m, now, now, true, period)
+ }
+ unreachable!()
+}
+
fn a_month(m: &Match) -> u32 {
match m.name("a_month").unwrap().as_str()[0..3]
.to_lowercase()