aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel <kingdread@gmx.de>2020-06-12 15:55:19 +0200
committerDaniel <kingdread@gmx.de>2020-06-12 15:55:19 +0200
commit4a3e7137334601828f56a3ee614f01d84bada4ce (patch)
tree3cf7fc84dfebeff11bd5d12230eb39368f45423f
parent6e52b5f2ac6154eca35355b320b7fb8bbc8f23ee (diff)
downloadraidgrep-4a3e7137334601828f56a3ee614f01d84bada4ce.tar.gz
raidgrep-4a3e7137334601828f56a3ee614f01d84bada4ce.tar.bz2
raidgrep-4a3e7137334601828f56a3ee614f01d84bada4ce.zip
implement -after/-before in terms of -time
It makes sense to unify this implementation to avoid code duplication and bugs that might be hidden. -after and -before can stay for now, as shortcuts for -time < and -time >, the same way we have other shortcuts as well.
-rw-r--r--src/fexpr/grammar.lalrpop8
-rw-r--r--src/filters/log.rs65
-rw-r--r--src/filters/values.rs22
3 files changed, 32 insertions, 63 deletions
diff --git a/src/fexpr/grammar.lalrpop b/src/fexpr/grammar.lalrpop
index 700481c..092407e 100644
--- a/src/fexpr/grammar.lalrpop
+++ b/src/fexpr/grammar.lalrpop
@@ -52,8 +52,12 @@ LogPredicate: Box<dyn filters::log::LogFilter> = {
"-outcome" <Comma<FightOutcome>> => filters::log::outcome(<>),
"-weekday" <Comma<Weekday>> => filters::log::weekday(<>),
- "-before" <Date> => filters::log::before(<>),
- "-after" <Date> => filters::log::after(<>),
+ "-before" <Date> => filters::values::comparison(
+ filters::values::time(), filters::values::CompOp::Less, filters::values::constant(<>)
+ ),
+ "-after" <Date> => filters::values::comparison(
+ filters::values::time(), filters::values::CompOp::Greater, filters::values::constant(<>)
+ ),
"-log-before" <Date> => filters::log::log_before(<>),
"-log-after" <Date> => filters::log::log_after(<>),
diff --git a/src/filters/log.rs b/src/filters/log.rs
index 9ca7d3c..bde02e5 100644
--- a/src/filters/log.rs
+++ b/src/filters/log.rs
@@ -7,17 +7,12 @@ use super::{
Filter, Inclusion,
};
-use std::{collections::HashSet, ffi::OsStr};
+use std::collections::HashSet;
use evtclib::Boss;
-use chrono::{DateTime, Datelike, Local, TimeZone, Utc, Weekday};
+use chrono::{DateTime, Datelike, Utc, Weekday};
use num_traits::FromPrimitive as _;
-use once_cell::sync::Lazy;
-use regex::Regex;
-
-/// The regular expression used to extract datetimes from filenames.
-static DATE_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\d{8}-\d{6}").unwrap());
/// Filter trait used for filters that operate on complete logs.
pub trait LogFilter = Filter<EarlyLogResult, LogResult>;
@@ -91,23 +86,9 @@ pub fn weekday(weekdays: HashSet<Weekday>) -> Box<dyn LogFilter> {
}
#[derive(Debug, Clone)]
-struct TimeFilter(Option<DateTime<Utc>>, Option<DateTime<Utc>>, bool);
+struct TimeFilter(Option<DateTime<Utc>>, Option<DateTime<Utc>>);
impl Filter<EarlyLogResult, LogResult> for TimeFilter {
- fn filter_early(&self, early_log: &EarlyLogResult) -> Inclusion {
- // Ignore the filename heuristic if the user wishes so.
- if !self.2 {
- return Inclusion::Unknown;
- }
- early_log
- .log_file
- .file_name()
- .and_then(datetime_from_filename)
- .map(|d| time_is_between(d, self.0, self.1))
- .map(Into::into)
- .unwrap_or(Inclusion::Unknown)
- }
-
fn filter(&self, log: &LogResult) -> bool {
time_is_between(log.time, self.0, self.1)
}
@@ -133,46 +114,12 @@ fn time_is_between(
after_ok && before_ok
}
-/// Try to extract the log time from the filename.
-///
-/// This expects the filename to have the datetime in the pattern `YYYYmmdd-HHMMSS` somewhere in
-/// it.
-pub(crate) fn datetime_from_filename(name: &OsStr) -> Option<DateTime<Utc>> {
- let date_match = DATE_REGEX.find(name.to_str()?)?;
- let local_time = Local
- .datetime_from_str(date_match.as_str(), "%Y%m%d-%H%M%S")
- .ok()?;
- Some(local_time.with_timezone(&Utc))
-}
-
-/// A `LogFilter` that only accepts logs in the given time frame.
-///
-/// If a bound is not given, -Infinity is assumed for the lower bound, and Infinity for the upper
-/// bound.
-pub fn time(lower: Option<DateTime<Utc>>, upper: Option<DateTime<Utc>>) -> Box<dyn LogFilter> {
- Box::new(TimeFilter(lower, upper, true))
-}
-
-/// A `LogFilter` that only accepts logs after the given date.
-///
-/// Also see [`time`][time] and [`before`][before].
-pub fn after(when: DateTime<Utc>) -> Box<dyn LogFilter> {
- time(Some(when), None)
-}
-
-/// A `LogFilter` that only accepts logs before the given date.
-///
-/// Also see [`time`][time] and [`after`][after].
-pub fn before(when: DateTime<Utc>) -> Box<dyn LogFilter> {
- time(None, Some(when))
-}
-
/// A `LogFilter` that only accepts logs in the given time frame.
///
-/// Compared to [`time`][time], this filter ignores the file name. This can result in more accurate
-/// results if you renamed logs, but if also leads to a worse runtime.
+/// Compared to [`-time`][super::values::time], this filter ignores the file name. This can result
+/// in more accurate results if you renamed logs, but if also leads to a worse runtime.
pub fn log_time(lower: Option<DateTime<Utc>>, upper: Option<DateTime<Utc>>) -> Box<dyn LogFilter> {
- Box::new(TimeFilter(lower, upper, false))
+ Box::new(TimeFilter(lower, upper))
}
/// Like [`after`][after], but ignores the file name for date calculations.
diff --git a/src/filters/values.rs b/src/filters/values.rs
index df5b805..a523dad 100644
--- a/src/filters/values.rs
+++ b/src/filters/values.rs
@@ -14,15 +14,21 @@
use std::{
cmp::Ordering,
convert::TryFrom,
+ ffi::OsStr,
fmt::{self, Debug},
};
-use chrono::{DateTime, Duration, Utc};
+use chrono::{DateTime, Duration, Local, TimeZone, Utc};
use evtclib::Agent;
+use once_cell::sync::Lazy;
+use regex::Regex;
use super::{log::LogFilter, player::PlayerFilter, Filter, Inclusion};
use crate::{EarlyLogResult, LogResult};
+/// The regular expression used to extract datetimes from filenames.
+static DATE_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\d{8}-\d{6}").unwrap());
+
/// A producer for a given value.
///
/// A producer is something that produces a value of a certain type from a log, which can then be
@@ -167,7 +173,7 @@ impl Producer for TimeProducer {
early_log
.log_file
.file_name()
- .and_then(super::log::datetime_from_filename)
+ .and_then(datetime_from_filename)
}
fn produce(&self, log: &LogResult) -> Self::Output {
@@ -175,6 +181,18 @@ impl Producer for TimeProducer {
}
}
+/// Try to extract the log time from the filename.
+///
+/// This expects the filename to have the datetime in the pattern `YYYYmmdd-HHMMSS` somewhere in
+/// it.
+fn datetime_from_filename(name: &OsStr) -> Option<DateTime<Utc>> {
+ let date_match = DATE_REGEX.find(name.to_str()?)?;
+ let local_time = Local
+ .datetime_from_str(date_match.as_str(), "%Y%m%d-%H%M%S")
+ .ok()?;
+ Some(local_time.with_timezone(&Utc))
+}
+
/// A producer that produces the time at which a log was created.
pub fn time() -> Box<dyn Producer<Output = DateTime<Utc>>> {
Box::new(TimeProducer)