mirror of
https://github.com/bspeice/dtparse
synced 2024-12-22 04:18:09 -05:00
commit
dd0ef6eb91
40
.travis.yml
40
.travis.yml
@ -1,40 +0,0 @@
|
|||||||
language: rust
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- rust: stable
|
|
||||||
os: linux
|
|
||||||
- rust: 1.28.0
|
|
||||||
os: linux
|
|
||||||
env: DISABLE_TOOLS=true
|
|
||||||
- rust: stable
|
|
||||||
os: osx
|
|
||||||
- rust: stable-msvc
|
|
||||||
os: windows
|
|
||||||
- rust: stable
|
|
||||||
os: windows
|
|
||||||
|
|
||||||
cache:
|
|
||||||
- cargo
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- rustup show
|
|
||||||
# CMake doesn't like the `sh.exe` provided by Git being in PATH
|
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then rm "C:/Program Files/Git/usr/bin/sh.exe"; fi
|
|
||||||
- if [[ "$DISABLE_TOOLS" == "" ]]; then rustup component add clippy; rustup component add rustfmt; fi
|
|
||||||
|
|
||||||
script:
|
|
||||||
- if [[ "$DISABLE_TOOLS" == "" ]]; then cargo clippy --all && cargo fmt --all -- --check; fi
|
|
||||||
|
|
||||||
# For default build, split up compilation and tests so we can track build times
|
|
||||||
- cargo test --no-run
|
|
||||||
- cargo test
|
|
||||||
- cargo test --release --no-run
|
|
||||||
- cargo test --release
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- staging
|
|
||||||
- trying
|
|
||||||
|
|
12
Cargo.toml
12
Cargo.toml
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dtparse"
|
name = "dtparse"
|
||||||
version = "1.3.0"
|
version = "1.4.0"
|
||||||
authors = ["Bradlee Speice <bradlee@speice.io>"]
|
authors = ["Bradlee Speice <bradlee@speice.io>"]
|
||||||
description = "A dateutil-compatible timestamp parser for Rust"
|
description = "A dateutil-compatible timestamp parser for Rust"
|
||||||
repository = "https://github.com/bspeice/dtparse.git"
|
repository = "https://github.com/bspeice/dtparse.git"
|
||||||
@ -16,10 +16,10 @@ maintenance = { status = "passively-maintained" }
|
|||||||
name = "dtparse"
|
name = "dtparse"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "0.4"
|
chrono = "0.4.24"
|
||||||
lazy_static = "1.1"
|
lazy_static = "1.4.0"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2.15"
|
||||||
rust_decimal = { version = "1.17.0", default-features = false }
|
rust_decimal = { version = "1.29.1", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
base64 = "0.13"
|
base64 = "0.21.0"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# dtparse
|
# dtparse
|
||||||
|
|
||||||
[![travisci](https://travis-ci.org/bspeice/dtparse.svg?branch=master)](https://travis-ci.org/bspeice/dtparse)
|
|
||||||
[![crates.io](https://img.shields.io/crates/v/dtparse.svg)](https://crates.io/crates/dtparse)
|
[![crates.io](https://img.shields.io/crates/v/dtparse.svg)](https://crates.io/crates/dtparse)
|
||||||
[![docs.rs](https://docs.rs/dtparse/badge.svg)](https://docs.rs/dtparse/)
|
[![docs.rs](https://docs.rs/dtparse/badge.svg)](https://docs.rs/dtparse/)
|
||||||
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
status = [
|
|
||||||
"continuous-integration/travis-ci/push",
|
|
||||||
]
|
|
||||||
delete_merged_branches = true
|
|
@ -317,7 +317,7 @@ TEST_PARSE_DEFAULT = '''
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parse_default{i}() {{
|
fn test_parse_default{i}() {{
|
||||||
let info = ParserInfo::default();
|
let info = ParserInfo::default();
|
||||||
let default_rsdate = &NaiveDate::from_ymd(2003, 9, 25).and_hms(0, 0, 0);
|
let default_rsdate = &NaiveDate::from_ymd_opt(2003, 9, 25).unwrap().and_hms_opt(0, 0, 0).unwrap();
|
||||||
let pdt = PyDateTime {{
|
let pdt = PyDateTime {{
|
||||||
year: {d.year}, month: {d.month}, day: {d.day},
|
year: {d.year}, month: {d.month}, day: {d.day},
|
||||||
hour: {d.hour}, minute: {d.minute}, second: {d.second},
|
hour: {d.hour}, minute: {d.minute}, second: {d.second},
|
||||||
@ -407,7 +407,7 @@ TEST_UNSPECIFIED_FALLBACK = '''
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_unspecified_fallback{i}() {{
|
fn test_unspecified_fallback{i}() {{
|
||||||
let info = ParserInfo::default();
|
let info = ParserInfo::default();
|
||||||
let default_rsdate = &NaiveDate::from_ymd(2010, 1, 31).and_hms(0, 0, 0);
|
let default_rsdate = &NaiveDate::from_ymd_opt(2010, 1, 31).unwrap().and_hms_opt(0, 0, 0).unwrap();
|
||||||
let pdt = PyDateTime {{
|
let pdt = PyDateTime {{
|
||||||
year: {d.year}, month: {d.month}, day: {d.day},
|
year: {d.year}, month: {d.month}, day: {d.day},
|
||||||
hour: {d.hour}, minute: {d.minute}, second: {d.second},
|
hour: {d.hour}, minute: {d.minute}, second: {d.second},
|
||||||
@ -435,7 +435,7 @@ TEST_PARSE_DEFAULT_IGNORE = '''
|
|||||||
#[ignore]
|
#[ignore]
|
||||||
fn test_parse_default_ignore{i}() {{
|
fn test_parse_default_ignore{i}() {{
|
||||||
let info = ParserInfo::default();
|
let info = ParserInfo::default();
|
||||||
let default_rsdate = &NaiveDate::from_ymd(2003, 9, 25).and_hms(0, 0, 0);
|
let default_rsdate = &NaiveDate::from_ymd_opt(2003, 9, 25).unwrap().and_hms_opt(0, 0, 0).unwrap();
|
||||||
let pdt = PyDateTime {{
|
let pdt = PyDateTime {{
|
||||||
year: {d.year}, month: {d.month}, day: {d.day},
|
year: {d.year}, month: {d.month}, day: {d.day},
|
||||||
hour: {d.hour}, minute: {d.minute}, second: {d.second},
|
hour: {d.hour}, minute: {d.minute}, second: {d.second},
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
set -ex
|
|
||||||
|
|
||||||
main() {
|
|
||||||
local target=
|
|
||||||
if [ $TRAVIS_OS_NAME = linux ]; then
|
|
||||||
target=x86_64-unknown-linux-musl
|
|
||||||
sort=sort
|
|
||||||
else
|
|
||||||
target=x86_64-apple-darwin
|
|
||||||
sort=gsort # for `sort --sort-version`, from brew's coreutils.
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Builds for iOS are done on OSX, but require the specific target to be
|
|
||||||
# installed.
|
|
||||||
case $TARGET in
|
|
||||||
aarch64-apple-ios)
|
|
||||||
rustup target install aarch64-apple-ios
|
|
||||||
;;
|
|
||||||
armv7-apple-ios)
|
|
||||||
rustup target install armv7-apple-ios
|
|
||||||
;;
|
|
||||||
armv7s-apple-ios)
|
|
||||||
rustup target install armv7s-apple-ios
|
|
||||||
;;
|
|
||||||
i386-apple-ios)
|
|
||||||
rustup target install i386-apple-ios
|
|
||||||
;;
|
|
||||||
x86_64-apple-ios)
|
|
||||||
rustup target install x86_64-apple-ios
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# This fetches latest stable release
|
|
||||||
local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \
|
|
||||||
| cut -d/ -f3 \
|
|
||||||
| grep -E '^v[0.1.0-9.]+$' \
|
|
||||||
| $sort --version-sort \
|
|
||||||
| tail -n1)
|
|
||||||
curl -LSfs https://japaric.github.io/trust/install.sh | \
|
|
||||||
sh -s -- \
|
|
||||||
--force \
|
|
||||||
--git japaric/cross \
|
|
||||||
--tag $tag \
|
|
||||||
--target $target
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
40
ci/script.sh
40
ci/script.sh
@ -1,40 +0,0 @@
|
|||||||
# This script takes care of testing your crate
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cross build --target $TARGET
|
|
||||||
cross build --target $TARGET --release
|
|
||||||
|
|
||||||
if [ ! -z $DISABLE_TESTS ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
cross test --target $TARGET
|
|
||||||
cross test --target $TARGET --release
|
|
||||||
}
|
|
||||||
|
|
||||||
main_web() {
|
|
||||||
CARGO_WEB_RELEASE="$(curl -L -s -H 'Accept: application/json' https://github.com/koute/cargo-web/releases/latest)"
|
|
||||||
CARGO_WEB_VERSION="$(echo $CARGO_WEB_RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/')"
|
|
||||||
CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/$CARGO_WEB_VERSION/cargo-web-x86_64-unknown-linux-gnu.gz"
|
|
||||||
|
|
||||||
echo "Downloading cargo-web from: $CARGO_WEB_URL"
|
|
||||||
curl -L "$CARGO_WEB_URL" | gzip -d > cargo-web
|
|
||||||
chmod +x cargo-web
|
|
||||||
|
|
||||||
mkdir -p ~/.cargo/bin
|
|
||||||
mv cargo-web ~/.cargo/bin
|
|
||||||
|
|
||||||
cargo web build --target $TARGET
|
|
||||||
cargo web test --target $TARGET --release
|
|
||||||
}
|
|
||||||
|
|
||||||
# we don't run the "test phase" when doing deploys
|
|
||||||
if [ -z $TRAVIS_TAG ]; then
|
|
||||||
if [ -z "$USE_CARGO_WEB" ]; then
|
|
||||||
main
|
|
||||||
else
|
|
||||||
main_web
|
|
||||||
fi
|
|
||||||
fi
|
|
@ -43,6 +43,6 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0,
|
.0,
|
||||||
NaiveDate::from_ymd(2015, 9, 10).and_hms(10, 20, 0)
|
NaiveDate::from_ymd_opt(2015, 9, 10).unwrap().and_hms_opt(10, 20, 0).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
35
src/lib.rs
35
src/lib.rs
@ -77,6 +77,9 @@ extern crate chrono;
|
|||||||
extern crate num_traits;
|
extern crate num_traits;
|
||||||
extern crate rust_decimal;
|
extern crate rust_decimal;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate base64;
|
||||||
|
|
||||||
use chrono::Datelike;
|
use chrono::Datelike;
|
||||||
use chrono::Duration;
|
use chrono::Duration;
|
||||||
use chrono::FixedOffset;
|
use chrono::FixedOffset;
|
||||||
@ -617,7 +620,7 @@ struct ParsingResult {
|
|||||||
hour: Option<i32>,
|
hour: Option<i32>,
|
||||||
minute: Option<i32>,
|
minute: Option<i32>,
|
||||||
second: Option<i32>,
|
second: Option<i32>,
|
||||||
microsecond: Option<i32>,
|
nanosecond: Option<i64>,
|
||||||
tzname: Option<String>,
|
tzname: Option<String>,
|
||||||
tzoffset: Option<i32>,
|
tzoffset: Option<i32>,
|
||||||
ampm: Option<bool>,
|
ampm: Option<bool>,
|
||||||
@ -644,7 +647,7 @@ impl ParsingResult {
|
|||||||
+ option_len!(self.hour)
|
+ option_len!(self.hour)
|
||||||
+ option_len!(self.minute)
|
+ option_len!(self.minute)
|
||||||
+ option_len!(self.second)
|
+ option_len!(self.second)
|
||||||
+ option_len!(self.microsecond)
|
+ option_len!(self.nanosecond)
|
||||||
+ option_len!(self.tzname)
|
+ option_len!(self.tzname)
|
||||||
+ option_len!(self.ampm)
|
+ option_len!(self.ampm)
|
||||||
}
|
}
|
||||||
@ -712,7 +715,7 @@ impl Parser {
|
|||||||
) -> ParseResult<(NaiveDateTime, Option<FixedOffset>, Option<Vec<String>>)> {
|
) -> ParseResult<(NaiveDateTime, Option<FixedOffset>, Option<Vec<String>>)> {
|
||||||
let default_date = default.unwrap_or(&Local::now().naive_local()).date();
|
let default_date = default.unwrap_or(&Local::now().naive_local()).date();
|
||||||
|
|
||||||
let default_ts = NaiveDateTime::new(default_date, NaiveTime::from_hms(0, 0, 0));
|
let default_ts = NaiveDateTime::new(default_date, NaiveTime::from_hms_opt(0, 0, 0).unwrap());
|
||||||
|
|
||||||
let (res, tokens) =
|
let (res, tokens) =
|
||||||
self.parse_with_tokens(timestr, dayfirst, yearfirst, fuzzy, fuzzy_with_tokens)?;
|
self.parse_with_tokens(timestr, dayfirst, yearfirst, fuzzy, fuzzy_with_tokens)?;
|
||||||
@ -976,18 +979,18 @@ impl Parser {
|
|||||||
let hour = res.hour.unwrap_or(default.hour() as i32) as u32;
|
let hour = res.hour.unwrap_or(default.hour() as i32) as u32;
|
||||||
let minute = res.minute.unwrap_or(default.minute() as i32) as u32;
|
let minute = res.minute.unwrap_or(default.minute() as i32) as u32;
|
||||||
let second = res.second.unwrap_or(default.second() as i32) as u32;
|
let second = res.second.unwrap_or(default.second() as i32) as u32;
|
||||||
let microsecond = res
|
let nanosecond = res
|
||||||
.microsecond
|
.nanosecond
|
||||||
.unwrap_or(default.timestamp_subsec_micros() as i32) as u32;
|
.unwrap_or(default.timestamp_subsec_nanos() as i64) as u32;
|
||||||
let t =
|
let t =
|
||||||
NaiveTime::from_hms_micro_opt(hour, minute, second, microsecond).ok_or_else(|| {
|
NaiveTime::from_hms_nano_opt(hour, minute, second, nanosecond).ok_or_else(|| {
|
||||||
if hour >= 24 {
|
if hour >= 24 {
|
||||||
ParseError::ImpossibleTimestamp("Invalid hour")
|
ParseError::ImpossibleTimestamp("Invalid hour")
|
||||||
} else if minute >= 60 {
|
} else if minute >= 60 {
|
||||||
ParseError::ImpossibleTimestamp("Invalid minute")
|
ParseError::ImpossibleTimestamp("Invalid minute")
|
||||||
} else if second >= 60 {
|
} else if second >= 60 {
|
||||||
ParseError::ImpossibleTimestamp("Invalid second")
|
ParseError::ImpossibleTimestamp("Invalid second")
|
||||||
} else if microsecond >= 2_000_000 {
|
} else if nanosecond >= 2_000_000_000 {
|
||||||
ParseError::ImpossibleTimestamp("Invalid microsecond")
|
ParseError::ImpossibleTimestamp("Invalid microsecond")
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@ -1004,7 +1007,7 @@ impl Parser {
|
|||||||
tzinfos: &HashMap<String, i32>,
|
tzinfos: &HashMap<String, i32>,
|
||||||
) -> ParseResult<Option<FixedOffset>> {
|
) -> ParseResult<Option<FixedOffset>> {
|
||||||
if let Some(offset) = res.tzoffset {
|
if let Some(offset) = res.tzoffset {
|
||||||
Ok(Some(FixedOffset::east(offset)))
|
Ok(FixedOffset::east_opt(offset))
|
||||||
} else if res.tzoffset == None
|
} else if res.tzoffset == None
|
||||||
&& (res.tzname == Some(" ".to_owned())
|
&& (res.tzname == Some(" ".to_owned())
|
||||||
|| res.tzname == Some(".".to_owned())
|
|| res.tzname == Some(".".to_owned())
|
||||||
@ -1013,9 +1016,9 @@ impl Parser {
|
|||||||
{
|
{
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else if res.tzname.is_some() && tzinfos.contains_key(res.tzname.as_ref().unwrap()) {
|
} else if res.tzname.is_some() && tzinfos.contains_key(res.tzname.as_ref().unwrap()) {
|
||||||
Ok(Some(FixedOffset::east(
|
Ok(FixedOffset::east_opt(
|
||||||
*tzinfos.get(res.tzname.as_ref().unwrap()).unwrap(),
|
*tzinfos.get(res.tzname.as_ref().unwrap()).unwrap(),
|
||||||
)))
|
))
|
||||||
} else if let Some(tzname) = res.tzname.as_ref() {
|
} else if let Some(tzname) = res.tzname.as_ref() {
|
||||||
println!("tzname {} identified but not understood.", tzname);
|
println!("tzname {} identified but not understood.", tzname);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@ -1071,7 +1074,7 @@ impl Parser {
|
|||||||
|
|
||||||
let t = self.parsems(&s[4..])?;
|
let t = self.parsems(&s[4..])?;
|
||||||
res.second = Some(t.0);
|
res.second = Some(t.0);
|
||||||
res.microsecond = Some(t.1);
|
res.nanosecond = Some(t.1);
|
||||||
}
|
}
|
||||||
} else if vec![8, 12, 14].contains(&len_li) {
|
} else if vec![8, 12, 14].contains(&len_li) {
|
||||||
// YYMMDD
|
// YYMMDD
|
||||||
@ -1109,7 +1112,7 @@ impl Parser {
|
|||||||
// TODO: (x, y) = (a, b) syntax?
|
// TODO: (x, y) = (a, b) syntax?
|
||||||
let ms = self.parsems(&tokens[idx + 4]).unwrap();
|
let ms = self.parsems(&tokens[idx + 4]).unwrap();
|
||||||
res.second = Some(ms.0);
|
res.second = Some(ms.0);
|
||||||
res.microsecond = Some(ms.1);
|
res.nanosecond = Some(ms.1);
|
||||||
|
|
||||||
idx += 2;
|
idx += 2;
|
||||||
}
|
}
|
||||||
@ -1183,13 +1186,13 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parsems(&self, seconds_str: &str) -> ParseResult<(i32, i32)> {
|
fn parsems(&self, seconds_str: &str) -> ParseResult<(i32, i64)> {
|
||||||
if seconds_str.contains('.') {
|
if seconds_str.contains('.') {
|
||||||
let split: Vec<&str> = seconds_str.split('.').collect();
|
let split: Vec<&str> = seconds_str.split('.').collect();
|
||||||
let (i, f): (&str, &str) = (split[0], split[1]);
|
let (i, f): (&str, &str) = (split[0], split[1]);
|
||||||
|
|
||||||
let i_parse = i.parse::<i32>()?;
|
let i_parse = i.parse::<i32>()?;
|
||||||
let f_parse = ljust(f, 6, '0').parse::<i32>()?;
|
let f_parse = ljust(f, 9, '0').parse::<i64>()?;
|
||||||
Ok((i_parse, f_parse))
|
Ok((i_parse, f_parse))
|
||||||
} else {
|
} else {
|
||||||
Ok((seconds_str.parse::<i32>()?, 0))
|
Ok((seconds_str.parse::<i32>()?, 0))
|
||||||
@ -1281,7 +1284,7 @@ impl Parser {
|
|||||||
} else if hms == 2 {
|
} else if hms == 2 {
|
||||||
let (sec, micro) = self.parsems(value_repr).unwrap();
|
let (sec, micro) = self.parsems(value_repr).unwrap();
|
||||||
res.second = Some(sec);
|
res.second = Some(sec);
|
||||||
res.microsecond = Some(micro);
|
res.nanosecond = Some(micro);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use base64::Engine;
|
||||||
|
use base64::engine::general_purpose::STANDARD;
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::str;
|
use std::str;
|
||||||
@ -19,7 +21,7 @@ fn test_fuzz() {
|
|||||||
Err(ParseError::UnrecognizedFormat)
|
Err(ParseError::UnrecognizedFormat)
|
||||||
);
|
);
|
||||||
|
|
||||||
let default = NaiveDate::from_ymd(2016, 6, 29).and_hms(0, 0, 0);
|
let default = NaiveDate::from_ymd_opt(2016, 6, 29).unwrap().and_hms_opt(0, 0, 0).unwrap();
|
||||||
let p = Parser::default();
|
let p = Parser::default();
|
||||||
let res = p.parse(
|
let res = p.parse(
|
||||||
"\x0D\x31",
|
"\x0D\x31",
|
||||||
@ -74,7 +76,7 @@ fn github_32() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn github_34() {
|
fn github_34() {
|
||||||
let parse_vec = base64::decode("KTMuLjYpGDYvLjZTNiouNjYuHzZpLjY/NkwuNh42Ry42PzYnKTMuNk02NjY2NjA2NjY2NjY2NjYTNjY2Ni82NjY2NlAuNlAuNlNI").unwrap();
|
let parse_vec = STANDARD.decode("KTMuLjYpGDYvLjZTNiouNjYuHzZpLjY/NkwuNh42Ry42PzYnKTMuNk02NjY2NjA2NjY2NjY2NjYTNjY2Ni82NjY2NlAuNlAuNlNI").unwrap();
|
||||||
let parse_str = str::from_utf8(&parse_vec).unwrap();
|
let parse_str = str::from_utf8(&parse_vec).unwrap();
|
||||||
let parse_result = parse(parse_str);
|
let parse_result = parse(parse_str);
|
||||||
assert!(parse_result.is_err());
|
assert!(parse_result.is_err());
|
||||||
@ -82,7 +84,7 @@ fn github_34() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn github_35() {
|
fn github_35() {
|
||||||
let parse_vec = base64::decode("KTY6LjYqNio6KjYn").unwrap();
|
let parse_vec = STANDARD.decode("KTY6LjYqNio6KjYn").unwrap();
|
||||||
let parse_str = str::from_utf8(&parse_vec).unwrap();
|
let parse_str = str::from_utf8(&parse_vec).unwrap();
|
||||||
let parse_result = parse(parse_str);
|
let parse_result = parse(parse_str);
|
||||||
assert!(parse_result.is_err());
|
assert!(parse_result.is_err());
|
||||||
@ -90,7 +92,7 @@ fn github_35() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn github_36() {
|
fn github_36() {
|
||||||
let parse_vec = base64::decode("KTYuLg==").unwrap();
|
let parse_vec = STANDARD.decode("KTYuLg==").unwrap();
|
||||||
let parse_str = str::from_utf8(&parse_vec).unwrap();
|
let parse_str = str::from_utf8(&parse_vec).unwrap();
|
||||||
let parse_result = parse(parse_str);
|
let parse_result = parse(parse_str);
|
||||||
assert!(parse_result.is_err());
|
assert!(parse_result.is_err());
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
mod fuzzing;
|
mod fuzzing;
|
||||||
mod pycompat_parser;
|
mod pycompat_parser;
|
||||||
mod pycompat_tokenizer;
|
mod pycompat_tokenizer;
|
||||||
|
|
||||||
|
use chrono::NaiveDate;
|
||||||
|
use crate::parse;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nanosecond_precision() {
|
||||||
|
assert_eq!(
|
||||||
|
parse("2008.12.29T08:09:10.123456789").unwrap(),
|
||||||
|
(NaiveDate::from_ymd_opt(2008, 12, 29).unwrap().and_hms_nano_opt(8, 9, 10, 123_456_789).unwrap(), None)
|
||||||
|
)
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user