diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fexpr/grammar.lalrpop | 8 | ||||
| -rw-r--r-- | src/filters/log.rs | 65 | ||||
| -rw-r--r-- | src/filters/values.rs | 22 | 
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) | 
