summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs179
-rw-r--r--tests/tests.rs112
2 files changed, 171 insertions, 120 deletions
diff --git a/src/lib.rs b/src/lib.rs
index f993435..50ed7d3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,11 +6,11 @@ extern crate lazy_static;
extern crate chrono;
use chrono::offset::LocalResult;
use chrono::{Date, DateTime, Datelike, Duration, TimeZone, Timelike, Utc, Weekday};
-use pidgin::{Grammar, Match, Matcher};
+use pidgin::{Match, Matcher};
use regex::Regex;
lazy_static! {
- static ref GRAMMAR: Grammar = grammar!{
+ static ref MATCHER: Matcher = grammar!{
(?ibBw)
TOP -> r(r"\A") <something> r(r"\z")
@@ -19,7 +19,7 @@ lazy_static! {
universal => [["always", "ever", "all time", "forever", "from beginning to end", "from the beginning to the end"]]
particular => <one_time> | <two_times>
one_time => <moment_or_period>
- two_times -> <moment_or_period> <to> <moment_or_period>
+ two_times -> ("from")? <moment_or_period> <to> <moment_or_period>
to => [["to", "through", "until", "up to", "thru", "till"]] | r("-+")
moment_or_period => <moment> | <period>
period => <named_period> | <specific_period>
@@ -50,32 +50,26 @@ lazy_static! {
am_pm => (?-i) [["am", "AM", "pm", "PM", "a.m.", "A.M.", "p.m.", "P.M."]]
h12 => [(1..=12).into_iter().collect::<Vec<_>>()]
h24 => [(1..=24).into_iter().collect::<Vec<_>>()]
- n_date -> <year> ("/") <n_month> ("/") <n_day>
- n_date -> <year> ("-") <n_month> ("-") <n_day>
- n_date -> <year> (".") <n_month> (".") <n_day>
- n_date -> <year> ("/") <n_day> ("/") <n_month>
- n_date -> <year> ("-") <n_day> ("-") <n_month>
- n_date -> <year> (".") <n_day> (".") <n_month>
- n_date -> <n_month> ("/") <n_day> ("/") <year>
- n_date -> <n_month> ("-") <n_day> ("-") <year>
- n_date -> <n_month> (".") <n_day> (".") <year>
- n_date -> <n_day> ("/") <n_month> ("/") <year>
- n_date -> <n_day> ("-") <n_month> ("-") <year>
- n_date -> <n_day> (".") <n_month> (".") <year>
+ n_date -> <year> r("[./-]") <n_month> r("[./-]") <n_day>
+ n_date -> <year> r("[./-]") <n_day> r("[./-]") <n_month>
+ n_date -> <n_month> r("[./-]") <n_day> r("[./-]") <year>
+ n_date -> <n_day> r("[./-]") <n_month> r("[./-]") <year>
a_date -> <a_month> <n_day> (",") <year>
a_date -> <n_day> <a_month> <year>
a_date -> <a_day> (",") <a_month> <n_day> (",") <year>
- year => [
- (100..=3000)
- .into_iter()
- .collect::<Vec<_>>()
- ]
- year => [
+ year => <short_year> | ("-")? <n_year>
+ year -> <suffix_year> <year_suffix>
+ short_year => [
(0..=99)
.into_iter()
.flat_map(|i| vec![format!("'{:02}", i), format!("{:02}", i)])
.collect::<Vec<_>>()
]
+ n_year => r(r"\b(?:[1-9][0-9]{0,4}|0)\b")
+ suffix_year => r(r"\b[1-9][0-9]{0,4}\b")
+ year_suffix => <ce> | <bce>
+ ce => (?-i) [["ce", "c.e.", "ad", "a.d.", "CE", "C.E.", "AD", "A.D."]]
+ bce => (?-i) [["bce", "b.c.e.", "bc", "b.c.", "BCE", "B.C.E.", "BC", "B.C."]]
n_day => [
(1..=31)
.into_iter()
@@ -140,10 +134,7 @@ lazy_static! {
"ever after",
"the last syllable of recorded time",
]]
- };
-}
-lazy_static! {
- static ref MATCHER: Matcher = GRAMMAR.matcher().unwrap();
+ }.matcher().unwrap();
}
#[derive(Debug, Clone)]
@@ -156,7 +147,7 @@ pub struct Config {
}
impl Config {
- pub fn default() -> Config {
+ pub fn new() -> Config {
Config {
now: Utc::now(),
monday_starts_week: true,
@@ -170,7 +161,7 @@ impl Config {
c.now = n;
c
}
- pub fn period(&self, period: Period) -> Config {
+ fn period(&self, period: Period) -> Config {
let mut c = self.clone();
c.period = period;
c
@@ -192,23 +183,36 @@ impl Config {
}
}
+/// A simple categorization of things that could go wrong.
+///
+/// Every error provides a descriptive string that can be displayed.
+#[derive(Debug, Clone)]
+pub enum TimeError {
+ Parse(String),
+ Misordered(String),
+ ImpossibleDate(String),
+ Weekday(String),
+ NoPayPeriod(String),
+}
+
+///
pub fn parse(
phrase: &str,
config: Option<Config>,
-) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+) -> Result<(DateTime<Utc>, DateTime<Utc>), TimeError> {
let parse = MATCHER.parse(phrase);
if parse.is_none() {
- return Err(format!(
+ return Err(TimeError::Parse(format!(
"could not parse \"{}\" as a time expression",
phrase
- ));
+ )));
}
let parse = parse.unwrap();
if parse.has("universal") {
return Ok((first_moment(), last_moment()));
}
let parse = parse.name("particular").unwrap();
- let config = config.unwrap_or(Config::default());
+ let config = config.unwrap_or(Config::new());
if let Some(moment) = parse.name("one_time") {
return handle_one_time(moment, &config);
}
@@ -224,7 +228,11 @@ pub fn parse(
if d1 <= d2 {
Ok((d1, d2))
} else {
- Err(format!("{} is after {}", first.as_str(), last.as_str()))
+ Err(TimeError::Misordered(format!(
+ "{} is after {}",
+ first.as_str(),
+ last.as_str()
+ )))
}
}
Err(s) => Err(s),
@@ -272,11 +280,29 @@ fn pick_terminus(d1: DateTime<Utc>, d2: DateTime<Utc>) -> DateTime<Utc> {
}
}
-fn first_moment() -> DateTime<Utc> {
+/// The moment regarded as the beginning of time.
+///
+/// # Examples
+///
+/// ```rust
+/// # extern crate two_timer;
+/// # use two_timer::first_moment;
+/// println!("{}", first_moment()); // -262144-01-01 00:00:00 UTC
+/// ```
+pub fn first_moment() -> DateTime<Utc> {
chrono::MIN_DATE.and_hms_milli(0, 0, 0, 0)
}
-fn last_moment() -> DateTime<Utc> {
+/// The moment regarded as the end of time.
+///
+/// # Examples
+///
+/// ```rust
+/// # extern crate two_timer;
+/// # use two_timer::last_moment;
+/// println!("{}", last_moment()); // +262143-12-31 23:59:59.999 UTC
+/// ```
+pub fn last_moment() -> DateTime<Utc> {
chrono::MAX_DATE.and_hms_milli(23, 59, 59, 999)
}
@@ -287,11 +313,14 @@ fn specific(m: &Match) -> bool {
fn handle_specific_day(
m: &Match,
config: &Config,
-) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+) -> Result<(DateTime<Utc>, DateTime<Utc>), TimeError> {
let now = config.now.clone();
let mut times = m.all_names("time");
if times.len() > 1 {
- return Err(format!("more than one daytime specified in {}", m.as_str()));
+ return Err(TimeError::Parse(format!(
+ "more than one daytime specified in {}",
+ m.as_str()
+ )));
}
let time = times.pop();
if let Some(adverb) = m.name("adverb") {
@@ -303,7 +332,7 @@ fn handle_specific_day(
'd' | 'D' => Ok(moment_and_time(&config.period(Period::Day), time)),
// tomorrow
'm' | 'M' => Ok(moment_and_time(
- &Config::default()
+ &Config::new()
.now(now + Duration::days(1))
.period(Period::Day),
time,
@@ -312,7 +341,7 @@ fn handle_specific_day(
},
// yesterday
'y' | 'Y' => Ok(moment_and_time(
- &Config::default()
+ &Config::new()
.now(now - Duration::days(1))
.period(Period::Day),
time,
@@ -327,21 +356,18 @@ fn handle_specific_day(
let day = n_day(date);
let d_opt = Utc.ymd_opt(year, month, day);
return match d_opt {
- LocalResult::None => Err(format!(
+ LocalResult::None => Err(TimeError::ImpossibleDate(format!(
"cannot construct UTC date with year {}, month {}, and day {}",
year, month, day
- )),
+ ))),
LocalResult::Single(d1) => {
let d1 = d1.and_hms(0, 0, 0);
Ok(moment_and_time(
- &Config::default().now(d1).period(Period::Day),
+ &Config::new().now(d1).period(Period::Day),
time,
))
}
- LocalResult::Ambiguous(_, _) => Err(format!(
- "cannot construct unambiguous UTC date with year {}, month {}, and day {}",
- year, month, day
- )),
+ LocalResult::Ambiguous(_, _) => unreachable!(),
};
}
if let Some(date) = date.name("a_date") {
@@ -350,40 +376,37 @@ fn handle_specific_day(
let day = n_day(date);
let d_opt = Utc.ymd_opt(year, month, day);
return match d_opt {
- LocalResult::None => Err(format!(
+ LocalResult::None => Err(TimeError::ImpossibleDate(format!(
"cannot construct UTC date with year {}, month {}, and day {}",
year, month, day
- )),
+ ))),
LocalResult::Single(d1) => {
if let Some(wd) = date.name("a_day") {
let wd = weekday(wd.as_str());
if wd == d1.weekday() {
let d1 = d1.and_hms(0, 0, 0);
Ok(moment_and_time(
- &Config::default().now(d1).period(Period::Day),
+ &Config::new().now(d1).period(Period::Day),
time,
))
} else {
- Err(format!(
+ Err(TimeError::Weekday(format!(
"the weekday of year {}, month {}, day {} is not {}",
year,
month,
day,
date.name("a_day").unwrap().as_str()
- ))
+ )))
}
} else {
let d1 = d1.and_hms(0, 0, 0);
Ok(moment_and_time(
- &Config::default().now(d1).period(Period::Day),
+ &Config::new().now(d1).period(Period::Day),
time,
))
}
}
- LocalResult::Ambiguous(_, _) => Err(format!(
- "cannot construct unambiguous UTC date with year {}, month {}, and day {}",
- year, month, day
- )),
+ LocalResult::Ambiguous(_, _) => unreachable!(),
};
}
unreachable!();
@@ -394,7 +417,7 @@ fn handle_specific_day(
fn handle_specific_period(
moment: &Match,
config: &Config,
-) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+) -> Result<(DateTime<Utc>, DateTime<Utc>), TimeError> {
if let Some(moment) = moment.name("month_and_year") {
let y = year(moment, &config.now);
let m = a_month(moment);
@@ -403,7 +426,7 @@ fn handle_specific_period(
LocalResult::Single(d1) => {
let d1 = d1.and_hms(0, 0, 0);
Ok(moment_and_time(
- &Config::default().now(d1).period(Period::Month),
+ &Config::new().now(d1).period(Period::Month),
None,
))
}
@@ -484,7 +507,9 @@ fn handle_specific_period(
};
Ok(moment_to_period(d, &Period::PayPeriod, config))
} else {
- Err(String::from("no pay period start date provided"))
+ Err(TimeError::NoPayPeriod(String::from(
+ "no pay period start date provided",
+ )))
}
}
};
@@ -531,7 +556,7 @@ impl PeriodModifier {
fn handle_specific_time(
moment: &Match,
config: &Config,
-) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+) -> Result<(DateTime<Utc>, DateTime<Utc>), TimeError> {
return if moment.has("first_time") {
Ok(moment_to_period(first_moment(), &config.period, config))
} else {
@@ -542,7 +567,7 @@ fn handle_specific_time(
fn handle_one_time(
moment: &Match,
config: &Config,
-) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+) -> Result<(DateTime<Utc>, DateTime<Utc>), TimeError> {
if moment.has("specific_day") {
return handle_specific_day(moment, config);
}
@@ -652,7 +677,10 @@ fn relative_moment(
unreachable!()
}
-fn specific_moment(m: &Match, config: &Config) -> Result<(DateTime<Utc>, DateTime<Utc>), String> {
+fn specific_moment(
+ m: &Match,
+ config: &Config,
+) -> Result<(DateTime<Utc>, DateTime<Utc>), TimeError> {
if let Some(m) = m.name("specific_day") {
return handle_specific_day(m, config);
}
@@ -725,22 +753,29 @@ fn n_month(m: &Match) -> u32 {
}
fn year(m: &Match, now: &DateTime<Utc>) -> i32 {
- lazy_static! {
- static ref YEAR: Regex = Regex::new(r"\A(?:'0?|0)?(\d{1,2})\z").unwrap();
- }
- let year = m.name("year").unwrap().as_str();
- let cap = YEAR.captures(year);
- if let Some(cap) = cap {
- // year is assumed to be in the current century
- let y = cap[1].parse::<i32>().unwrap();
+ let year = m.name("year").unwrap();
+ if let Some(sy) = year.name("short_year") {
+ let y = s_to_n(sy.as_str()) as i32;
let this_year = now.year() % 100;
if this_year < y {
now.year() - this_year - 100 + y
} else {
now.year() - this_year + y
}
+ } else if let Some(suffix) = year.name("year_suffix") {
+ let y = s_to_n(year.name("suffix_year").unwrap().as_str()) as i32;
+ if suffix.has("bce") {
+ 1 - y // there is no year 0
+ } else {
+ y
+ }
} else {
- year.parse::<i32>().unwrap()
+ let y = s_to_n(year.name("n_year").unwrap().as_str()) as i32;
+ if year.as_str().chars().nth(0).expect("unreachable") == '-' {
+ -y
+ } else {
+ y
+ }
}
}
@@ -811,7 +846,6 @@ fn moment_to_period(
);
(d1, d1 + Duration::seconds(1))
}
- Period::Nanosecond => (now, now + Duration::nanoseconds(1)),
Period::PayPeriod => {
if let Some(pps) = config.pay_period_start {
// find the current pay period start
@@ -831,7 +865,7 @@ fn moment_to_period(
}
#[derive(Debug, Clone)]
-pub enum Period {
+enum Period {
Year,
Month,
Week,
@@ -839,7 +873,6 @@ pub enum Period {
Hour,
Minute,
Second,
- Nanosecond,
PayPeriod,
}
diff --git a/tests/tests.rs b/tests/tests.rs
index 9280c82..4a0aa82 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -27,7 +27,7 @@ fn always() {
#[test]
fn yesterday() {
let now = Utc::now();
- let (start, end) = parse("yesterday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("yesterday", Some(Config::new().now(now))).unwrap();
assert!(start < now);
assert!(end < now);
let then = now - Duration::days(1);
@@ -40,7 +40,7 @@ fn yesterday() {
#[test]
fn tomorrow() {
let now = Utc::now();
- let (start, end) = parse("tomorrow", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("tomorrow", Some(Config::new().now(now))).unwrap();
assert!(start > now);
assert!(end > now);
let then = now + Duration::days(1);
@@ -53,7 +53,7 @@ fn tomorrow() {
#[test]
fn today() {
let now = Utc::now();
- let (start, end) = parse("today", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("today", Some(Config::new().now(now))).unwrap();
assert!(start < now);
assert!(end > now);
let then = now + Duration::days(1);
@@ -154,7 +154,7 @@ fn at_3_pm() {
let now = Utc.ymd(1969, 5, 6).and_hms(16, 0, 0);
let then = Utc.ymd(1969, 5, 6).and_hms(15, 0, 0);
for phrase in ["3 PM", "3 pm", "15"].iter() {
- let (start, end) = parse(phrase, Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse(phrase, Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::hours(1), end);
}
@@ -165,7 +165,7 @@ fn at_3_00_pm() {
let now = Utc.ymd(1969, 5, 6).and_hms(16, 0, 0);
let then = Utc.ymd(1969, 5, 6).and_hms(15, 0, 0);
for phrase in ["3:00 PM", "3:00 pm", "15:00"].iter() {
- let (start, end) = parse(phrase, Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse(phrase, Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::minutes(1), end);
}
@@ -176,7 +176,7 @@ fn at_3_00_00_pm() {
let now = Utc.ymd(1969, 5, 6).and_hms(16, 0, 0);
let then = Utc.ymd(1969, 5, 6).and_hms(15, 0, 0);
for phrase in ["3:00:00 PM", "3:00:00 pm", "15:00:00"].iter() {
- let (start, end) = parse(phrase, Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse(phrase, Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::seconds(1), end);
}
@@ -187,7 +187,7 @@ fn at_3_pm_yesterday() {
let now = Utc.ymd(1969, 5, 6).and_hms(14, 0, 0);
let then = Utc.ymd(1969, 5, 5).and_hms(15, 0, 0);
for phrase in ["3 PM yesterday", "3 pm yesterday", "15 yesterday"].iter() {
- let (start, end) = parse(phrase, Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse(phrase, Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::hours(1), end);
}
@@ -345,7 +345,7 @@ fn this_month() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 6, 1).and_hms(0, 0, 0);
- let (start, end) = parse("this month", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("this month", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -355,7 +355,7 @@ fn next_month() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 6, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 7, 1).and_hms(0, 0, 0);
- let (start, end) = parse("next month", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("next month", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -365,7 +365,7 @@ fn last_month() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 4, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 1).and_hms(0, 0, 0);
- let (start, end) = parse("last month", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("last month", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -375,7 +375,7 @@ fn this_year() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 1, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);
- let (start, end) = parse("this year", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("this year", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -385,7 +385,7 @@ fn next_year() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1971, 1, 1).and_hms(0, 0, 0);
- let (start, end) = parse("next year", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("next year", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -395,7 +395,7 @@ fn last_year() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1968, 1, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 1, 1).and_hms(0, 0, 0);
- let (start, end) = parse("last year", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("last year", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -405,7 +405,7 @@ fn this_week() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 5).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 12).and_hms(0, 0, 0);
- let (start, end) = parse("this week", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("this week", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -415,7 +415,7 @@ fn next_week() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 12).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 19).and_hms(0, 0, 0);
- let (start, end) = parse("next week", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("next week", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -425,7 +425,7 @@ fn last_week() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 4, 28).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 5).and_hms(0, 0, 0);
- let (start, end) = parse("last week", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("last week", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -437,7 +437,7 @@ fn this_week_sunday_starts() {
let d2 = Utc.ymd(1969, 5, 11).and_hms(0, 0, 0);
let (start, end) = parse(
"this week",
- Some(Config::default().now(now).monday_starts_week(false)),
+ Some(Config::new().now(now).monday_starts_week(false)),
)
.unwrap();
assert_eq!(d1, start);
@@ -451,7 +451,7 @@ fn next_week_sunday_starts() {
let d2 = Utc.ymd(1969, 5, 18).and_hms(0, 0, 0);
let (start, end) = parse(
"next week",
- Some(Config::default().now(now).monday_starts_week(false)),
+ Some(Config::new().now(now).monday_starts_week(false)),
)
.unwrap();
assert_eq!(d1, start);
@@ -465,7 +465,7 @@ fn last_week_sunday_starts() {
let d2 = Utc.ymd(1969, 5, 4).and_hms(0, 0, 0);
let (start, end) = parse(
"last week",
- Some(Config::default().now(now).monday_starts_week(false)),
+ Some(Config::new().now(now).monday_starts_week(false)),
)
.unwrap();
assert_eq!(d1, start);
@@ -476,7 +476,7 @@ fn last_week_sunday_starts() {
fn this_pay_period() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
// two-week pay period beginning about a year before "now" on a Sunday
- let config = Config::default()
+ let config = Config::new()
.pay_period_start(Some(Utc.ymd(1968, 5, 5)))
.pay_period_length(14)
.now(now);
@@ -491,7 +491,7 @@ fn this_pay_period() {
fn next_pay_period() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
// two-week pay period beginning about a year before "now" on a Sunday
- let config = Config::default()
+ let config = Config::new()
.pay_period_start(Some(Utc.ymd(1968, 5, 5)))
.pay_period_length(14)
.now(now);
@@ -506,7 +506,7 @@ fn next_pay_period() {
fn last_pay_period() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
// two-week pay period beginning about a year before "now" on a Sunday
- let config = Config::default()
+ let config = Config::new()
.pay_period_start(Some(Utc.ymd(1968, 5, 5)))
.pay_period_length(14)
.now(now);
@@ -521,7 +521,7 @@ fn last_pay_period() {
fn this_pay_period_weird() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
// two-week pay period beginning about a year *after* "now" on a Sunday
- let config = Config::default()
+ let config = Config::new()
.pay_period_start(Some(Utc.ymd(1970, 4, 5)))
.pay_period_length(14)
.now(now);
@@ -536,7 +536,7 @@ fn this_pay_period_weird() {
fn next_pay_period_weird() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
// two-week pay period beginning about a year *after* "now" on a Sunday
- let config = Config::default()
+ let config = Config::new()
.pay_period_start(Some(Utc.ymd(1970, 4, 5)))
.pay_period_length(14)
.now(now);
@@ -551,7 +551,7 @@ fn next_pay_period_weird() {
fn last_pay_period_weird() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
// two-week pay period beginning about a year *after* "now" on a Sunday
- let config = Config::default()
+ let config = Config::new()
.pay_period_start(Some(Utc.ymd(1970, 4, 5)))
.pay_period_length(14)
.now(now);
@@ -567,7 +567,7 @@ fn this_april() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 4, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 1).and_hms(0, 0, 0);
- let (start, end) = parse("this april", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("this april", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -577,7 +577,7 @@ fn next_april() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1970, 4, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1970, 5, 1).and_hms(0, 0, 0);
- let (start, end) = parse("next april", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("next april", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -587,7 +587,7 @@ fn last_april() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1968, 4, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1968, 5, 1).and_hms(0, 0, 0);
- let (start, end) = parse("last april", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("last april", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -597,7 +597,7 @@ fn this_friday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 9).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 10).and_hms(0, 0, 0);
- let (start, end) = parse("this friday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("this friday", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -607,7 +607,7 @@ fn next_friday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 16).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 17).and_hms(0, 0, 0);
- let (start, end) = parse("next friday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("next friday", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -617,7 +617,7 @@ fn last_friday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 2).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 3).and_hms(0, 0, 0);
- let (start, end) = parse("last friday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("last friday", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -627,7 +627,7 @@ fn this_monday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 5).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
- let (start, end) = parse("this monday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("this monday", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -637,7 +637,7 @@ fn next_monday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 12).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 13).and_hms(0, 0, 0);
- let (start, end) = parse("next monday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("next monday", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -647,7 +647,7 @@ fn last_monday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 4, 28).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 4, 29).and_hms(0, 0, 0);
- let (start, end) = parse("last monday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("last monday", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -708,7 +708,7 @@ fn the_crack_of_doom() {
fn friday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let then = Utc.ymd(1969, 5, 2).and_hms(0, 0, 0);
- let (start, end) = parse("Friday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("Friday", Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::days(1), end);
}
@@ -717,7 +717,7 @@ fn friday() {
fn tuesday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let then = Utc.ymd(1969, 4, 29).and_hms(0, 0, 0);
- let (start, end) = parse("Tuesday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("Tuesday", Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::days(1), end);
}
@@ -726,7 +726,7 @@ fn tuesday() {
fn monday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let then = Utc.ymd(1969, 5, 5).and_hms(0, 0, 0);
- let (start, end) = parse("Monday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("Monday", Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::days(1), end);
}
@@ -735,7 +735,7 @@ fn monday() {
fn friday_at_3_pm() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let then = Utc.ymd(1969, 5, 2).and_hms(15, 0, 0);
- let (start, end) = parse("Friday at 3 pm", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("Friday at 3 pm", Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::hours(1), end);
}
@@ -744,7 +744,7 @@ fn friday_at_3_pm() {
fn tuesday_at_3_pm() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let then = Utc.ymd(1969, 4, 29).and_hms(15, 0, 0);
- let (start, end) = parse("Tuesday at 3 pm", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("Tuesday at 3 pm", Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::hours(1), end);
}
@@ -753,7 +753,7 @@ fn tuesday_at_3_pm() {
fn monday_at_3_pm() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let then = Utc.ymd(1969, 5, 5).and_hms(15, 0, 0);
- let (start, end) = parse("Monday at 3 pm", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("Monday at 3 pm", Some(Config::new().now(now))).unwrap();
assert_eq!(then, start);
assert_eq!(then + Duration::hours(1), end);
}
@@ -763,7 +763,7 @@ fn just_may() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 6, 1).and_hms(0, 0, 0);
- let (start, end) = parse("May", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("May", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -773,7 +773,7 @@ fn just_april() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 4, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 1).and_hms(0, 0, 0);
- let (start, end) = parse("April", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("April", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -783,7 +783,7 @@ fn just_june() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1968, 6, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1968, 7, 1).and_hms(0, 0, 0);
- let (start, end) = parse("June", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("June", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -793,7 +793,7 @@ fn monday_through_friday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 5, 5).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 10).and_hms(0, 0, 0);
- let (start, end) = parse("Monday through Friday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("Monday through Friday", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -803,7 +803,7 @@ fn tuesday_through_friday() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 4, 29).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 3).and_hms(0, 0, 0);
- let (start, end) = parse("Tuesday through Friday", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("Tuesday through Friday", Some(Config::new().now(now))).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}
@@ -815,7 +815,7 @@ fn tuesday_through_3_pm_on_friday() {
let d2 = Utc.ymd(1969, 5, 2).and_hms(15, 0, 0);
let (start, end) = parse(
"Tuesday through 3 PM on Friday",
- Some(Config::default().now(now)),
+ Some(Config::new().now(now)),
)
.unwrap();
assert_eq!(d1, start);
@@ -827,7 +827,25 @@ fn this_year_through_today() {
let now = Utc.ymd(1969, 5, 6).and_hms(0, 0, 0);
let d1 = Utc.ymd(1969, 1, 1).and_hms(0, 0, 0);
let d2 = Utc.ymd(1969, 5, 7).and_hms(0, 0, 0);
- let (start, end) = parse("this year through today", Some(Config::default().now(now))).unwrap();
+ let (start, end) = parse("this year through today", Some(Config::new().now(now))).unwrap();
+ assert_eq!(d1, start);
+ assert_eq!(d2, end);
+}
+
+#[test]
+fn april_3_25_bc() {
+ let d1 = Utc.ymd(-24, 4, 3).and_hms(0, 0, 0);
+ let d2 = d1 + Duration::days(1);
+ let (start, end) = parse("April 3, 25 BC", None).unwrap();
+ assert_eq!(d1, start);
+ assert_eq!(d2, end);
+}
+
+#[test]
+fn april_3_25_ad() {
+ let d1 = Utc.ymd(25, 4, 3).and_hms(0, 0, 0);
+ let d2 = d1 + Duration::days(1);
+ let (start, end) = parse("April 3, 25 AD", None).unwrap();
assert_eq!(d1, start);
assert_eq!(d2, end);
}