Merge pull request #15 from bspeice/internal_refactor

Internal refactor
pull/24/head
bspeice 2018-07-24 23:32:44 -04:00 committed by GitHub
commit c884bc5842
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 201 additions and 216 deletions

44
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,44 @@
# Contributing
The `dtparse` crate is better for the contributions made by members of the open source community,
and seeks to make it easy to contribute back to the community it comes from. The goals are
fairly straight-forward, but here are the ways that would be most beneficial:
## Bug Reports
The testing suite for `dtparse` is built using tests derived from the [`dateutil`](https://github.com/dateutil/dateutil)
package in Python. Some Rust-specific behavior may show up though, for example in how
Rust handles nanoseconds where Python's standard library will only go to microseconds.
If you believe that behavior is improper, you are encouraged to file an issue; there are no dumb
issues or suggestions, and the world is a better place for having your input.
## Testing/Fuzzing
`dtparse`'s history as a port of Python software has led to some behavior being shown in Rust
that would not otherwise be an issue in Python. Testing for these issues to prevent panics
is greatly appreciated, and some great work has already happened surrounding fuzzing.
New test cases built either by fuzzers or humans are welcome.
## Feature Requests
Handling weird date formats and quirks is the name of the game. Any ideas on how to improve that
or utilities useful in handling the mapping of human time to computers is appreciated.
Writing code to implement the feature is never mandatory (though always appreciated); if there's
something you believe `dtparse` should do that it doesn't currently support, let's make that happen.
# Development Setup
The setup requirements for `dtparse` should be fairly straightforward - the project can be built
and deployed using only the `cargo` tool in Rust.
Much of the test coee is generated from Python code, and then the generated versions are stored
in version control. Thi is to ensure that all users can run the tests even without
installing Python or the other necessary packages.
To regenerate the tests, please use Python 3.6 with the `dateutil` package installed, and run:
- `python build_pycompat.py`
- `python build_pycompat_tokenizer.py`

6
CONTRIBUTORS.md Normal file
View File

@ -0,0 +1,6 @@
This project benefits from the Rust and open source communities, but most specifically from these people:
# Contributors:
- [@messense](https://github.com/messense)
- [@mjmeehan](https://github.com/mjmeehan)

View File

@ -222,7 +222,7 @@ fn parse_and_assert(
fuzzy_with_tokens: bool,
default: Option<&NaiveDateTime>,
ignoretz: bool,
tzinfos: HashMap<String, i32>,
tzinfos: &HashMap<String, i32>,
) {
let mut parser = Parser::new(info);
@ -272,7 +272,7 @@ fn parse_fuzzy_and_assert(
fuzzy_with_tokens: bool,
default: Option<&NaiveDateTime>,
ignoretz: bool,
tzinfos: HashMap<String, i32>,
tzinfos: &HashMap<String, i32>,
) {
let mut parser = Parser::new(info);
@ -316,7 +316,7 @@ fn test_parse_default{i}() {{
micros: {d.microsecond}, tzo: None
}};
parse_and_assert(pdt, info, "{s}", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}}\n'''
TEST_PARSE_SIMPLE = '''
@ -340,7 +340,7 @@ fn test_parse_tzinfo{i}() {{
micros: {d.microsecond}, tzo: Some({offset}),
}};
parse_and_assert(pdt, info, "{s}", None, None, false, false,
None, false, rs_tzinfo_map!());
None, false, &rs_tzinfo_map!());
}}\n'''
TEST_PARSE_OFFSET = '''
@ -353,7 +353,7 @@ fn test_parse_offset{i}() {{
micros: {d.microsecond}, tzo: Some({offset}),
}};
parse_and_assert(pdt, info, "{s}", None, None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}}\n'''
TEST_PARSE_DAYFIRST = '''
@ -366,7 +366,7 @@ fn test_parse_dayfirst{i}() {{
micros: {d.microsecond}, tzo: None,
}};
parse_and_assert(pdt, info, "{s}", Some(true), None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}}\n'''
TEST_PARSE_YEARFIRST = '''
@ -379,7 +379,7 @@ fn test_parse_yearfirst{i}() {{
micros: {d.microsecond}, tzo: None,
}};
parse_and_assert(pdt, info, "{s}", None, Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}}\n'''
TEST_PARSE_DFYF = '''
@ -392,7 +392,7 @@ fn test_parse_dfyf{i}() {{
micros: {d.microsecond}, tzo: None,
}};
parse_and_assert(pdt, info, "{s}", Some(true), Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}}\n'''
TEST_UNSPECIFIED_FALLBACK = '''
@ -406,7 +406,7 @@ fn test_unspecified_fallback{i}() {{
micros: {d.microsecond}, tzo: None
}};
parse_and_assert(pdt, info, "{s}", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}}\n'''
TEST_PARSE_IGNORETZ = '''
@ -419,7 +419,7 @@ fn test_parse_ignoretz{i}() {{
micros: {d.microsecond}, tzo: None
}};
parse_and_assert(pdt, info, "{s}", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}}\n'''
TEST_PARSE_DEFAULT_IGNORE = '''
@ -434,7 +434,7 @@ fn test_parse_default_ignore{i}() {{
micros: {d.microsecond}, tzo: None
}};
parse_and_assert(pdt, info, "{s}", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}}\n'''
TEST_FUZZY_TZINFO = '''
@ -447,7 +447,7 @@ fn test_fuzzy_tzinfo{i}() {{
micros: {d.microsecond}, tzo: Some({offset})
}};
parse_fuzzy_and_assert(pdt, None, info, "{s}", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}}\n'''
TEST_FUZZY_TOKENS_TZINFO = '''
@ -461,7 +461,7 @@ fn test_fuzzy_tokens_tzinfo{i}() {{
}};
let tokens = vec![{tokens}];
parse_fuzzy_and_assert(pdt, Some(tokens), info, "{s}", None, None, true, true,
None, false, HashMap::new());
None, false, &HashMap::new());
}}\n'''
TEST_FUZZY_SIMPLE = '''
@ -474,7 +474,7 @@ fn test_fuzzy_simple{i}() {{
micros: {d.microsecond}, tzo: None
}};
parse_fuzzy_and_assert(pdt, None, info, "{s}", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}}\n'''

5
fuzz/.gitignore vendored
View File

@ -1,5 +0,0 @@
target
libfuzzer
corpus
artifacts

View File

@ -1,22 +0,0 @@
[package]
name = "dtparse-fuzz"
version = "0.0.1"
authors = ["Automatically generated"]
publish = false
[package.metadata]
cargo-fuzz = true
[dependencies.dtparse]
path = ".."
[dependencies.libfuzzer-sys]
git = "https://github.com/rust-fuzz/libfuzzer-sys.git"
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[[bin]]
name = "fuzzer_script_1"
path = "fuzzers/fuzzer_script_1.rs"

View File

@ -1,10 +0,0 @@
#![no_main]
extern crate libfuzzer_sys;
extern crate dtparse;
use dtparse::parse;
#[export_name="rust_fuzzer_test_input"]
pub extern fn go(data: &[u8]) {
if let Ok(s) = std::str::from_utf8(data) {
parse(s);
}
}

View File

@ -39,53 +39,34 @@ lazy_static! {
static ref SIXTY: Decimal = Decimal::new(60, 0);
}
#[derive(Debug, PartialEq)]
pub enum ParseInternalError {
// Errors that indicate internal bugs
YMDEarlyResolve,
YMDValueUnset(Vec<YMDLabel>),
ParseIndexError,
InvalidDecimal,
InvalidInteger,
// Python-style errors
ValueError(String),
}
impl From<DecimalError> for ParseInternalError {
fn from(_err: DecimalError) -> Self {
ParseInternalError::InvalidDecimal
impl From<DecimalError> for ParseError {
fn from(err: DecimalError) -> Self {
ParseError::InvalidNumeric(format!("{}", err))
}
}
impl From<ParseIntError> for ParseInternalError {
fn from(_err: ParseIntError) -> Self {
ParseInternalError::InvalidInteger
impl From<ParseIntError> for ParseError {
fn from(err: ParseIntError) -> Self {
ParseError::InvalidNumeric(format!("{}", err))
}
}
#[derive(Debug, PartialEq)]
pub enum ParseError {
AmbiguousYMD,
AmbiguousWeekday,
InternalError(ParseInternalError),
InvalidMonth,
UnrecognizedToken(String),
InvalidParseResult(ParsingResult),
AmPmWithoutHour,
TimezoneUnsupported,
ImpossibleTimestamp(&'static str),
}
impl From<ParseInternalError> for ParseError {
fn from(err: ParseInternalError) -> Self {
ParseError::InternalError(err)
}
InvalidNumeric(String),
UnrecognizedFormat,
UnrecognizedToken(String),
TimezoneUnsupported,
YearMonthDayError(&'static str),
}
type ParseResult<I> = Result<I, ParseError>;
type ParseIResult<I> = Result<I, ParseInternalError>;
pub fn tokenize(parse_string: &str) -> Vec<String> {
pub(crate) fn tokenize(parse_string: &str) -> Vec<String> {
let tokenizer = Tokenizer::new(parse_string);
tokenizer.collect()
}
@ -268,13 +249,13 @@ fn days_in_month(year: i32, month: i32) -> Result<u32, ParseError> {
1 | 3 | 5 | 7 | 8 | 10 | 12 => Ok(31),
4 | 6 | 9 | 11 => Ok(30),
_ => {
Err(ParseError::InvalidMonth)
Err(ParseError::ImpossibleTimestamp("Invalid month"))
}
}
}
#[derive(Debug, Hash, PartialEq, Eq)]
pub enum YMDLabel {
enum YMDLabel {
Year,
Month,
Day,
@ -311,7 +292,7 @@ impl YMD {
}
}
fn append(&mut self, val: i32, token: &str, label: Option<YMDLabel>) -> ParseIResult<()> {
fn append(&mut self, val: i32, token: &str, label: Option<YMDLabel>) -> ParseResult<()> {
let mut label = label;
// Python auto-detects strings using the '__len__' function here.
@ -320,12 +301,11 @@ impl YMD {
self.century_specified = true;
match label {
None | Some(YMDLabel::Year) => label = Some(YMDLabel::Year),
_ => {
return Err(ParseInternalError::ValueError(format!(
"Invalid label {:?} for token {:?}",
label,
token
)))
Some(YMDLabel::Month) => {
return Err(ParseError::ImpossibleTimestamp("Invalid month"))
}
Some(YMDLabel::Day) => {
return Err(ParseError::ImpossibleTimestamp("Invalid day"))
}
}
}
@ -335,12 +315,11 @@ impl YMD {
match label {
None => label = Some(YMDLabel::Year),
Some(YMDLabel::Year) => (),
_ => {
return Err(ParseInternalError::ValueError(format!(
"Invalid label {:?} for token {:?}",
label,
token
)))
Some(YMDLabel::Month) => {
return Err(ParseError::ImpossibleTimestamp("Invalid month"))
}
Some(YMDLabel::Day) => {
return Err(ParseError::ImpossibleTimestamp("Invalid day"))
}
}
}
@ -350,9 +329,7 @@ impl YMD {
match label {
Some(YMDLabel::Month) => {
if self.mstridx.is_some() {
Err(ParseInternalError::ValueError(
"Month already set.".to_owned(),
))
Err(ParseError::YearMonthDayError("Month already set"))
} else {
self.mstridx = Some(self._ymd.len() - 1);
Ok(())
@ -360,9 +337,7 @@ impl YMD {
}
Some(YMDLabel::Day) => {
if self.dstridx.is_some() {
Err(ParseInternalError::ValueError(
"Day already set.".to_owned(),
))
Err(ParseError::YearMonthDayError("Day already set"))
} else {
self.dstridx = Some(self._ymd.len() - 1);
Ok(())
@ -370,9 +345,7 @@ impl YMD {
}
Some(YMDLabel::Year) => {
if self.ystridx.is_some() {
Err(ParseInternalError::ValueError(
"Year already set.".to_owned(),
))
Err(ParseError::YearMonthDayError("Year already set"))
} else {
self.ystridx = Some(self._ymd.len() - 1);
Ok(())
@ -385,7 +358,7 @@ impl YMD {
fn resolve_from_stridxs(
&mut self,
strids: &mut HashMap<YMDLabel, usize>,
) -> ParseIResult<(Option<i32>, Option<i32>, Option<i32>)> {
) -> ParseResult<(Option<i32>, Option<i32>, Option<i32>)> {
if self._ymd.len() == 3 && strids.len() == 2 {
let missing_key = if !strids.contains_key(&YMDLabel::Year) {
YMDLabel::Year
@ -408,7 +381,7 @@ impl YMD {
}
if self._ymd.len() != strids.len() {
return Err(ParseInternalError::YMDEarlyResolve);
return Err(ParseError::YearMonthDayError("Tried to resolve year, month, and day without enough information"));
}
Ok((
@ -428,7 +401,7 @@ impl YMD {
&mut self,
yearfirst: bool,
dayfirst: bool,
) -> ParseIResult<(Option<i32>, Option<i32>, Option<i32>)> {
) -> ParseResult<(Option<i32>, Option<i32>, Option<i32>)> {
let len_ymd = self._ymd.len();
let mut strids: HashMap<YMDLabel, usize> = HashMap::new();
@ -446,10 +419,9 @@ impl YMD {
return self.resolve_from_stridxs(&mut strids);
};
// Received year, month, day, and ???
if len_ymd > 3 {
return Err(ParseInternalError::ValueError(
"More than three YMD values".to_owned(),
));
return Err(ParseError::YearMonthDayError("Received extra tokens in resolving year, month, and day"));
}
match (len_ymd, self.mstridx) {
@ -515,7 +487,7 @@ impl YMD {
}
#[derive(Default, Debug, PartialEq)]
pub struct ParsingResult {
struct ParsingResult {
year: Option<i32>,
month: Option<i32>,
day: Option<i32>,
@ -550,7 +522,7 @@ impl Parser {
fuzzy_with_tokens: bool,
default: Option<&NaiveDateTime>,
ignoretz: bool,
tzinfos: HashMap<String, i32>,
tzinfos: &HashMap<String, i32>,
) -> ParseResult<(NaiveDateTime, Option<FixedOffset>, Option<Vec<String>>)> {
let default_date = default.unwrap_or(&Local::now().naive_local()).date();
@ -725,7 +697,7 @@ impl Parser {
res.day = day;
if !self.info.validate(&mut res) {
Err(ParseError::InvalidParseResult(res))
Err(ParseError::UnrecognizedFormat)
} else if fuzzy_with_tokens {
let skipped_tokens = self.recombine_skipped(skipped_idxs, l);
Ok((res, Some(skipped_tokens)))
@ -823,7 +795,7 @@ impl Parser {
&self,
_dt: &NaiveDateTime,
res: &ParsingResult,
tzinfos: HashMap<String, i32>,
tzinfos: &HashMap<String, i32>,
) -> ParseResult<Option<FixedOffset>> {
// TODO: Actual timezone support
if let Some(offset) = res.tzoffset {
@ -854,7 +826,7 @@ impl Parser {
ymd: &mut YMD,
res: &mut ParsingResult,
fuzzy: bool,
) -> Result<usize, ParseInternalError> {
) -> ParseResult<usize> {
let mut idx = idx;
let value_repr = &tokens[idx];
let mut value = Decimal::from_str(&value_repr).unwrap();
@ -955,7 +927,7 @@ impl Parser {
if let Ok(val) = tokens[idx + 4].parse::<i32>() {
ymd.append(val, &tokens[idx + 4], None)?;
} else {
return Err(ParseInternalError::ValueError("Unknown string format".to_owned()));
return Err(ParseError::UnrecognizedFormat);
}
}
@ -987,7 +959,7 @@ impl Parser {
} else if ymd.could_be_day(value.to_i64().unwrap() as i32) {
ymd.append(value.to_i64().unwrap() as i32, &value_repr, None)?;
} else if !fuzzy {
return Err(ParseInternalError::ValueError("".to_owned()));
return Err(ParseError::UnrecognizedFormat);
}
Ok(idx)
@ -1003,7 +975,7 @@ impl Parser {
}
}
fn parsems(&self, seconds_str: &str) -> Result<(i32, i32), ParseInternalError> {
fn parsems(&self, seconds_str: &str) -> ParseResult<(i32, i32)> {
if seconds_str.contains(".") {
let split: Vec<&str> = seconds_str.split(".").collect();
let (i, f): (&str, &str) = (split[0], split[1]);
@ -1159,7 +1131,7 @@ pub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option<FixedOffset>)>
false,
None,
false,
HashMap::new(),
&HashMap::new(),
)?;
Ok((res.0, res.1))

View File

@ -3,21 +3,21 @@ use std::collections::HashMap;
use parse;
use ParseError;
use ParseInternalError;
use Parser;
#[test]
fn test_fuzz() {
assert_eq!(parse("\x2D\x38\x31\x39\x34\x38\x34"), Err(ParseError::InvalidMonth));
assert_eq!(parse("\x2D\x38\x31\x39\x34\x38\x34"), Err(ParseError::ImpossibleTimestamp("Invalid month")));
// Garbage in the third delimited field
assert_eq!(parse("2..\x00\x000d\x00+\x010d\x01\x00\x00\x00+"),
Err(ParseError::InternalError(ParseInternalError::ValueError("Unknown string format".to_owned()))));
Err(ParseError::UnrecognizedFormat));
// OverflowError: Python int too large to convert to C long
// assert_eq!(parse("8888884444444888444444444881"), Err(ParseError::AmPmWithoutHour));
let default = NaiveDate::from_ymd(2016, 6, 29).and_hms(0, 0, 0);
let mut p = Parser::default();
let res = p.parse("\x0D\x31", None, None, false, false, Some(&default), false, HashMap::new()).unwrap();
let res = p.parse("\x0D\x31", None, None, false, false, Some(&default), false, &HashMap::new()).unwrap();
assert_eq!(res.0, default);
assert_eq!(parse("\x2D\x2D\x32\x31\x38\x6D"), Err(ParseError::ImpossibleTimestamp("Invalid minute")));

View File

@ -32,7 +32,7 @@ fn parse_and_assert(
fuzzy_with_tokens: bool,
default: Option<&NaiveDateTime>,
ignoretz: bool,
tzinfos: HashMap<String, i32>,
tzinfos: &HashMap<String, i32>,
) {
let mut parser = Parser::new(info);
@ -82,7 +82,7 @@ fn parse_fuzzy_and_assert(
fuzzy_with_tokens: bool,
default: Option<&NaiveDateTime>,
ignoretz: bool,
tzinfos: HashMap<String, i32>,
tzinfos: &HashMap<String, i32>,
) {
let mut parser = Parser::new(info);
@ -125,7 +125,7 @@ fn test_parse_default0() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Thu Sep 25 10:36:28", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -138,7 +138,7 @@ fn test_parse_default1() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Sep 10:36:28", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -151,7 +151,7 @@ fn test_parse_default2() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:36:28", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -164,7 +164,7 @@ fn test_parse_default3() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:36", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -177,7 +177,7 @@ fn test_parse_default4() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Sep 2003", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -190,7 +190,7 @@ fn test_parse_default5() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Sep", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -203,7 +203,7 @@ fn test_parse_default6() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "2003", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -216,7 +216,7 @@ fn test_parse_default7() {
micros: 500000, tzo: None
};
parse_and_assert(pdt, info, "10h36m28.5s", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -229,7 +229,7 @@ fn test_parse_default8() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10h36m28s", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -242,7 +242,7 @@ fn test_parse_default9() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10h36m", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -255,7 +255,7 @@ fn test_parse_default10() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10h", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -268,7 +268,7 @@ fn test_parse_default11() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10 h 36", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -281,7 +281,7 @@ fn test_parse_default12() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10 h 36.5", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -294,7 +294,7 @@ fn test_parse_default13() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "36 m 5", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -307,7 +307,7 @@ fn test_parse_default14() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "36 m 5 s", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -320,7 +320,7 @@ fn test_parse_default15() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "36 m 05", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -333,7 +333,7 @@ fn test_parse_default16() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "36 m 05 s", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -346,7 +346,7 @@ fn test_parse_default17() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10h am", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -359,7 +359,7 @@ fn test_parse_default18() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10h pm", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -372,7 +372,7 @@ fn test_parse_default19() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10am", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -385,7 +385,7 @@ fn test_parse_default20() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10pm", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -398,7 +398,7 @@ fn test_parse_default21() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:00 am", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -411,7 +411,7 @@ fn test_parse_default22() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:00 pm", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -424,7 +424,7 @@ fn test_parse_default23() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:00am", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -437,7 +437,7 @@ fn test_parse_default24() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:00pm", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -450,7 +450,7 @@ fn test_parse_default25() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:00a.m", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -463,7 +463,7 @@ fn test_parse_default26() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:00p.m", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -476,7 +476,7 @@ fn test_parse_default27() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:00a.m.", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -489,7 +489,7 @@ fn test_parse_default28() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "10:00p.m.", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -502,7 +502,7 @@ fn test_parse_default29() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "October", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -515,7 +515,7 @@ fn test_parse_default30() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "31-Dec-00", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -528,7 +528,7 @@ fn test_parse_default31() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "0:01:02", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -541,7 +541,7 @@ fn test_parse_default32() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "12h 01m02s am", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -554,7 +554,7 @@ fn test_parse_default33() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "12:08 PM", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -567,7 +567,7 @@ fn test_parse_default34() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "01h02m03", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -580,7 +580,7 @@ fn test_parse_default35() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "01h02", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -593,7 +593,7 @@ fn test_parse_default36() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "01h02s", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -606,7 +606,7 @@ fn test_parse_default37() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "01m02", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -619,7 +619,7 @@ fn test_parse_default38() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "01m02h", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -632,7 +632,7 @@ fn test_parse_default39() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "2004 10 Apr 11h30m", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -645,7 +645,7 @@ fn test_parse_default40() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Sep 03", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -658,7 +658,7 @@ fn test_parse_default41() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Sep of 03", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -671,7 +671,7 @@ fn test_parse_default42() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "02:17NOV2017", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -684,7 +684,7 @@ fn test_parse_default43() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Thu Sep 10:36:28", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -697,7 +697,7 @@ fn test_parse_default44() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Thu 10:36:28", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -710,7 +710,7 @@ fn test_parse_default45() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Wed", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -723,7 +723,7 @@ fn test_parse_default46() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Wednesday", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -1355,7 +1355,7 @@ fn test_parse_tzinfo0() {
micros: 0, tzo: Some(-10800),
};
parse_and_assert(pdt, info, "Thu Sep 25 10:36:28 BRST 2003", None, None, false, false,
None, false, rs_tzinfo_map!());
None, false, &rs_tzinfo_map!());
}
#[test]
@ -1367,7 +1367,7 @@ fn test_parse_tzinfo1() {
micros: 0, tzo: Some(-10800),
};
parse_and_assert(pdt, info, "2003 10:36:28 BRST 25 Sep Thu", None, None, false, false,
None, false, rs_tzinfo_map!());
None, false, &rs_tzinfo_map!());
}
#[test]
@ -1379,7 +1379,7 @@ fn test_parse_offset0() {
micros: 0, tzo: Some(-10800),
};
parse_and_assert(pdt, info, "Thu, 25 Sep 2003 10:49:41 -0300", None, None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1391,7 +1391,7 @@ fn test_parse_offset1() {
micros: 500000, tzo: Some(-10800),
};
parse_and_assert(pdt, info, "2003-09-25T10:49:41.5-03:00", None, None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1403,7 +1403,7 @@ fn test_parse_offset2() {
micros: 0, tzo: Some(-10800),
};
parse_and_assert(pdt, info, "2003-09-25T10:49:41-03:00", None, None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1415,7 +1415,7 @@ fn test_parse_offset3() {
micros: 500000, tzo: Some(-10800),
};
parse_and_assert(pdt, info, "20030925T104941.5-0300", None, None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1427,7 +1427,7 @@ fn test_parse_offset4() {
micros: 0, tzo: Some(-10800),
};
parse_and_assert(pdt, info, "20030925T104941-0300", None, None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1439,7 +1439,7 @@ fn test_parse_dayfirst0() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "10-09-2003", Some(true), None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1451,7 +1451,7 @@ fn test_parse_dayfirst1() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "10.09.2003", Some(true), None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1463,7 +1463,7 @@ fn test_parse_dayfirst2() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "10/09/2003", Some(true), None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1475,7 +1475,7 @@ fn test_parse_dayfirst3() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "10 09 2003", Some(true), None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1487,7 +1487,7 @@ fn test_parse_dayfirst4() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "090107", Some(true), None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1499,7 +1499,7 @@ fn test_parse_dayfirst5() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "2015 09 25", Some(true), None, false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1511,7 +1511,7 @@ fn test_parse_yearfirst0() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "10-09-03", None, Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1523,7 +1523,7 @@ fn test_parse_yearfirst1() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "10.09.03", None, Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1535,7 +1535,7 @@ fn test_parse_yearfirst2() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "10/09/03", None, Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1547,7 +1547,7 @@ fn test_parse_yearfirst3() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "10 09 03", None, Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1559,7 +1559,7 @@ fn test_parse_yearfirst4() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "090107", None, Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1571,7 +1571,7 @@ fn test_parse_yearfirst5() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "2015 09 25", None, Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1583,7 +1583,7 @@ fn test_parse_dfyf0() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "090107", Some(true), Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1595,7 +1595,7 @@ fn test_parse_dfyf1() {
micros: 0, tzo: None,
};
parse_and_assert(pdt, info, "2015 09 25", Some(true), Some(true), false, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1608,7 +1608,7 @@ fn test_unspecified_fallback0() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "April 2009", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -1621,7 +1621,7 @@ fn test_unspecified_fallback1() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Feb 2007", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -1634,7 +1634,7 @@ fn test_unspecified_fallback2() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Feb 2008", None, None, false, false,
Some(default_rsdate), false, HashMap::new());
Some(default_rsdate), false, &HashMap::new());
}
#[test]
@ -1646,7 +1646,7 @@ fn test_parse_ignoretz0() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Thu Sep 25 10:36:28 BRST 2003", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}
#[test]
@ -1658,7 +1658,7 @@ fn test_parse_ignoretz1() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "1996.07.10 AD at 15:08:56 PDT", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}
#[test]
@ -1670,7 +1670,7 @@ fn test_parse_ignoretz2() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Tuesday, April 12, 1952 AD 3:30:42pm PST", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}
#[test]
@ -1682,7 +1682,7 @@ fn test_parse_ignoretz3() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "November 5, 1994, 8:15:30 am EST", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}
#[test]
@ -1694,7 +1694,7 @@ fn test_parse_ignoretz4() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "1994-11-05T08:15:30-05:00", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}
#[test]
@ -1706,7 +1706,7 @@ fn test_parse_ignoretz5() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "1994-11-05T08:15:30Z", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}
#[test]
@ -1718,7 +1718,7 @@ fn test_parse_ignoretz6() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "1976-07-04T00:01:02Z", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}
#[test]
@ -1730,7 +1730,7 @@ fn test_parse_ignoretz7() {
micros: 0, tzo: None
};
parse_and_assert(pdt, info, "Tue Apr 4 00:22:12 PDT 1995", None, None, false, false,
None, true, HashMap::new());
None, true, &HashMap::new());
}
#[test]
@ -1742,7 +1742,7 @@ fn test_fuzzy_tzinfo0() {
micros: 0, tzo: Some(-10800)
};
parse_fuzzy_and_assert(pdt, None, info, "Today is 25 of September of 2003, exactly at 10:49:41 with timezone -03:00.", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1755,7 +1755,7 @@ fn test_fuzzy_tokens_tzinfo0() {
};
let tokens = vec!["Today is ".to_owned(), "of ".to_owned(), ", exactly at ".to_owned(), " with timezone ".to_owned(), ".".to_owned()];
parse_fuzzy_and_assert(pdt, Some(tokens), info, "Today is 25 of September of 2003, exactly at 10:49:41 with timezone -03:00.", None, None, true, true,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1767,7 +1767,7 @@ fn test_fuzzy_simple0() {
micros: 0, tzo: None
};
parse_fuzzy_and_assert(pdt, None, info, "I have a meeting on March 1, 1974", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1779,7 +1779,7 @@ fn test_fuzzy_simple1() {
micros: 0, tzo: None
};
parse_fuzzy_and_assert(pdt, None, info, "On June 8th, 2020, I am going to be the first man on Mars", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1791,7 +1791,7 @@ fn test_fuzzy_simple2() {
micros: 0, tzo: None
};
parse_fuzzy_and_assert(pdt, None, info, "Meet me at the AM/PM on Sunset at 3:00 AM on December 3rd, 2003", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1803,7 +1803,7 @@ fn test_fuzzy_simple3() {
micros: 0, tzo: None
};
parse_fuzzy_and_assert(pdt, None, info, "Meet me at 3:00 AM on December 3rd, 2003 at the AM/PM on Sunset", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1815,7 +1815,7 @@ fn test_fuzzy_simple4() {
micros: 0, tzo: None
};
parse_fuzzy_and_assert(pdt, None, info, "Jan 29, 1945 14:45 AM I going to see you there?", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}
#[test]
@ -1827,5 +1827,5 @@ fn test_fuzzy_simple5() {
micros: 0, tzo: None
};
parse_fuzzy_and_assert(pdt, None, info, "2017-07-17 06:15:", None, None, true, false,
None, false, HashMap::new());
None, false, &HashMap::new());
}

View File

@ -64,7 +64,7 @@ pub fn day_of_week(year: u32, month: u32, day: u32) -> ParseResult<DayOfWeek> {
let c = (year - 1) / 100;
(c, year - 1 - 100 * c)
},
_ => return Err(ParseError::InvalidMonth)
_ => return Err(ParseError::ImpossibleTimestamp("Invalid month"))
};
let e = match month {