From adb5fabfa7e133717985eb28d2be3b09ba8aa83f Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Fri, 15 Sep 2023 09:30:33 +0200 Subject: [PATCH 001/163] Revert "Update codecov/codecov-action action to v4" --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b663b7..27b4c17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -155,7 +155,7 @@ jobs: grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" echo "report=${COVERAGE_REPORT_FILE}" >> $GITHUB_OUTPUT - name: Upload coverage results (to Codecov.io) - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v3 # if: steps.vars.outputs.HAS_CODECOV_TOKEN with: # token: ${{ secrets.CODECOV_TOKEN }} From 93c02dc0b780ac31318bf7bea33d7752523dc704 Mon Sep 17 00:00:00 2001 From: Patrick Klitzke Date: Fri, 15 Sep 2023 18:40:27 +0900 Subject: [PATCH 002/163] Fixes Negative numbers for @ not being recognized (#43) * Fixes Negative numbers for @ not being recognized This commit resolves #40. Adds new file and functions parse_timestamp. Adds tests for handling negative numbers. --- Cargo.lock | 17 ++++++ Cargo.toml | 1 + src/lib.rs | 16 ++++-- src/parse_relative_time.rs | 2 + src/parse_timestamp.rs | 111 +++++++++++++++++++++++++++++++++++++ 5 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 src/parse_timestamp.rs diff --git a/Cargo.lock b/Cargo.lock index 6af6ced..cd3b98a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,6 +118,22 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -138,6 +154,7 @@ name = "parse_datetime" version = "0.5.0" dependencies = [ "chrono", + "nom", "regex", ] diff --git a/Cargo.toml b/Cargo.toml index b28ba6f..5255ddb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ readme = "README.md" [dependencies] regex = "1.9" chrono = { version="0.4", default-features=false, features=["std", "alloc", "clock"] } +nom = "7.1.3" diff --git a/src/lib.rs b/src/lib.rs index 90e191b..bb58926 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,10 +14,12 @@ use std::fmt::{self, Display}; // Expose parse_datetime mod parse_relative_time; +mod parse_timestamp; use chrono::{DateTime, FixedOffset, Local, LocalResult, NaiveDateTime, TimeZone}; use parse_relative_time::parse_relative_time; +use parse_timestamp::parse_timestamp; #[derive(Debug, PartialEq)] pub enum ParseDateTimeError { @@ -169,9 +171,9 @@ pub fn parse_datetime_at_date + Clone>( } // Parse epoch seconds - if s.as_ref().bytes().next() == Some(b'@') { - if let Ok(parsed) = NaiveDateTime::parse_from_str(&s.as_ref()[1..], "%s") { - if let Ok(dt) = naive_dt_to_fixed_offset(date, parsed) { + if let Ok(timestamp) = parse_timestamp(s.as_ref()) { + if let Some(timestamp_date) = NaiveDateTime::from_timestamp_opt(timestamp, 0) { + if let Ok(dt) = naive_dt_to_fixed_offset(date, timestamp_date) { return Ok(dt); } } @@ -359,15 +361,21 @@ mod tests { use chrono::{TimeZone, Utc}; #[test] - fn test_positive_offsets() { + fn test_positive_and_negative_offsets() { let offsets: Vec = vec![ 0, 1, 2, 10, 100, 150, 2000, 1234400000, 1334400000, 1692582913, 2092582910, ]; for offset in offsets { + // positive offset let time = Utc.timestamp_opt(offset, 0).unwrap(); let dt = parse_datetime(format!("@{}", offset)); assert_eq!(dt.unwrap(), time); + + // negative offset + let time = Utc.timestamp_opt(-offset, 0).unwrap(); + let dt = parse_datetime(format!("@-{}", offset)); + assert_eq!(dt.unwrap(), time); } } } diff --git a/src/parse_relative_time.rs b/src/parse_relative_time.rs index afa47b5..7bc0840 100644 --- a/src/parse_relative_time.rs +++ b/src/parse_relative_time.rs @@ -1,3 +1,5 @@ +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. use crate::ParseDateTimeError; use chrono::{Duration, Local, NaiveDate, Utc}; use regex::Regex; diff --git a/src/parse_timestamp.rs b/src/parse_timestamp.rs new file mode 100644 index 0000000..732558d --- /dev/null +++ b/src/parse_timestamp.rs @@ -0,0 +1,111 @@ +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. +use core::fmt; +use std::error::Error; +use std::fmt::Display; +use std::num::ParseIntError; + +use nom::branch::alt; +use nom::character::complete::{char, digit1}; +use nom::combinator::all_consuming; +use nom::multi::fold_many0; +use nom::sequence::preceded; +use nom::sequence::tuple; +use nom::{self, IResult}; + +#[derive(Debug, PartialEq)] +pub enum ParseTimestampError { + InvalidNumber(ParseIntError), + InvalidInput, +} + +impl Display for ParseTimestampError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InvalidInput => { + write!(f, "Invalid input string: cannot be parsed as a timestamp") + } + Self::InvalidNumber(err) => { + write!(f, "Invalid timestamp number: {err}") + } + } + } +} + +impl Error for ParseTimestampError {} + +// TODO is this necessary +impl From for ParseTimestampError { + fn from(err: ParseIntError) -> Self { + Self::InvalidNumber(err) + } +} + +type NomError<'a> = nom::Err>; + +impl<'a> From> for ParseTimestampError { + fn from(_err: NomError<'a>) -> Self { + Self::InvalidInput + } +} + +pub(crate) fn parse_timestamp(s: &str) -> Result { + let s = s.trim().to_lowercase(); + let s = s.as_str(); + + let res: IResult<&str, (char, &str)> = all_consuming(preceded( + char('@'), + tuple(( + // Note: to stay compatible with gnu date this code allows + // multiple + and - and only considers the last one + fold_many0( + // parse either + or - + alt((char('+'), char('-'))), + // start with a + + || '+', + // whatever we get (+ or -), update the accumulator to that value + |_, c| c, + ), + digit1, + )), + ))(s); + + let (_, (sign, number_str)) = res?; + + let mut number = number_str.parse::()?; + + if sign == '-' { + number *= -1; + } + + Ok(number) +} + +#[cfg(test)] +mod tests { + + use crate::parse_timestamp::parse_timestamp; + + #[test] + fn test_valid_timestamp() { + assert_eq!(parse_timestamp("@1234"), Ok(1234)); + assert_eq!(parse_timestamp("@99999"), Ok(99999)); + assert_eq!(parse_timestamp("@-4"), Ok(-4)); + assert_eq!(parse_timestamp("@-99999"), Ok(-99999)); + assert_eq!(parse_timestamp("@+4"), Ok(4)); + assert_eq!(parse_timestamp("@0"), Ok(0)); + + // gnu date accepts numbers signs and uses the last sign + assert_eq!(parse_timestamp("@---+12"), Ok(12)); + assert_eq!(parse_timestamp("@+++-12"), Ok(-12)); + assert_eq!(parse_timestamp("@+----+12"), Ok(12)); + assert_eq!(parse_timestamp("@++++-123"), Ok(-123)); + } + + #[test] + fn test_invalid_timestamp() { + assert!(parse_timestamp("@").is_err()); + assert!(parse_timestamp("@+--+").is_err()); + assert!(parse_timestamp("@+1ab2").is_err()); + } +} From 96db1a281e85b511a573482d9e7a0dfef63fb46b Mon Sep 17 00:00:00 2001 From: Patrick Klitzke Date: Wed, 23 Aug 2023 10:00:43 +0900 Subject: [PATCH 003/163] Support weekdays in parse_datetime This commit resolves issue #23. Adds parse_weekday function that uses chrono weekday parser with a map for edge cases. Adds tests cases to make sure it works correctly. Use nom for parsing. --- Cargo.lock | 17 +++++++ Cargo.toml | 1 + src/lib.rs | 78 +++++++++++++++++++++++++++++- src/parse_relative_time.rs | 2 + src/parse_weekday.rs | 99 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 src/parse_weekday.rs diff --git a/Cargo.lock b/Cargo.lock index 0d099a3..76586d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,6 +118,22 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -138,6 +154,7 @@ name = "parse_datetime" version = "0.4.0" dependencies = [ "chrono", + "nom", "regex", ] diff --git a/Cargo.toml b/Cargo.toml index 9e9fd40..59f01ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ readme = "README.md" [dependencies] regex = "1.9" chrono = { version="0.4", default-features=false, features=["std", "alloc", "clock"] } +nom = "7.1.3" diff --git a/src/lib.rs b/src/lib.rs index 90e191b..7d9437e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,12 @@ use std::fmt::{self, Display}; // Expose parse_datetime mod parse_relative_time; -use chrono::{DateTime, FixedOffset, Local, LocalResult, NaiveDateTime, TimeZone}; +mod parse_weekday; + +use chrono::{ + DateTime, Datelike, Duration, FixedOffset, Local, LocalResult, NaiveDateTime, TimeZone, + Timelike, +}; use parse_relative_time::parse_relative_time; @@ -168,6 +173,27 @@ pub fn parse_datetime_at_date + Clone>( } } + // parse weekday + if let Some(weekday) = parse_weekday::parse_weekday(s.as_ref()) { + let mut beginning_of_day = date + .with_hour(0) + .unwrap() + .with_minute(0) + .unwrap() + .with_second(0) + .unwrap() + .with_nanosecond(0) + .unwrap(); + + while beginning_of_day.weekday() != weekday { + beginning_of_day += Duration::days(1); + } + + let dt = DateTime::::from(beginning_of_day); + + return Ok(dt); + } + // Parse epoch seconds if s.as_ref().bytes().next() == Some(b'@') { if let Ok(parsed) = NaiveDateTime::parse_from_str(&s.as_ref()[1..], "%s") { @@ -353,6 +379,56 @@ mod tests { } } + #[cfg(test)] + mod weekday { + use chrono::{DateTime, Local, TimeZone}; + + use crate::parse_datetime_at_date; + + fn get_formatted_date(date: DateTime, weekday: &str) -> String { + let result = parse_datetime_at_date(date, weekday).unwrap(); + + return result.format("%F %T %f").to_string(); + } + #[test] + fn test_weekday() { + // add some constant hours and minutes and seconds to check its reset + let date = Local.with_ymd_and_hms(2023, 02, 28, 10, 12, 3).unwrap(); + + // 2023-2-28 is tuesday + assert_eq!( + get_formatted_date(date, "tuesday"), + "2023-02-28 00:00:00 000000000" + ); + + // 2023-3-01 is wednesday + assert_eq!( + get_formatted_date(date, "wed"), + "2023-03-01 00:00:00 000000000" + ); + + assert_eq!( + get_formatted_date(date, "thu"), + "2023-03-02 00:00:00 000000000" + ); + + assert_eq!( + get_formatted_date(date, "fri"), + "2023-03-03 00:00:00 000000000" + ); + + assert_eq!( + get_formatted_date(date, "sat"), + "2023-03-04 00:00:00 000000000" + ); + + assert_eq!( + get_formatted_date(date, "sun"), + "2023-03-05 00:00:00 000000000" + ); + } + } + #[cfg(test)] mod timestamp { use crate::parse_datetime; diff --git a/src/parse_relative_time.rs b/src/parse_relative_time.rs index afa47b5..7bc0840 100644 --- a/src/parse_relative_time.rs +++ b/src/parse_relative_time.rs @@ -1,3 +1,5 @@ +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. use crate::ParseDateTimeError; use chrono::{Duration, Local, NaiveDate, Utc}; use regex::Regex; diff --git a/src/parse_weekday.rs b/src/parse_weekday.rs new file mode 100644 index 0000000..d61aca7 --- /dev/null +++ b/src/parse_weekday.rs @@ -0,0 +1,99 @@ +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. +use chrono::Weekday; +use nom::branch::alt; +use nom::bytes::complete::tag; +use nom::combinator::value; +use nom::{self, IResult}; + +// Helper macro to simplify tag matching +macro_rules! tag_match { + ($day:expr, $($pattern:expr),+) => { + value($day, alt(($(tag($pattern)),+))) + }; +} + +pub(crate) fn parse_weekday(s: &str) -> Option { + let s = s.trim().to_lowercase(); + let s = s.as_str(); + + let parse_result: IResult<&str, Weekday> = nom::combinator::all_consuming(alt(( + tag_match!(Weekday::Mon, "monday", "mon"), + tag_match!(Weekday::Tue, "tuesday", "tues", "tue"), + tag_match!(Weekday::Wed, "wednesday", "wednes", "wed"), + tag_match!(Weekday::Thu, "thursday", "thurs", "thur", "thu"), + tag_match!(Weekday::Fri, "friday", "fri"), + tag_match!(Weekday::Sat, "saturday", "sat"), + tag_match!(Weekday::Sun, "sunday", "sun"), + )))(s); + + match parse_result { + Ok((_, weekday)) => Some(weekday), + Err(_) => None, + } +} + +#[cfg(test)] +mod tests { + + use chrono::Weekday::*; + + use crate::parse_weekday::parse_weekday; + + #[test] + fn test_valid_weekdays() { + let days = [ + ("mon", Mon), + ("monday", Mon), + ("tue", Tue), + ("tues", Tue), + ("tuesday", Tue), + ("wed", Wed), + ("wednes", Wed), + ("wednesday", Wed), + ("thu", Thu), + ("thursday", Thu), + ("fri", Fri), + ("friday", Fri), + ("sat", Sat), + ("saturday", Sat), + ("sun", Sun), + ("sunday", Sun), + ]; + + for (name, weekday) in days { + assert_eq!(parse_weekday(name), Some(weekday)); + assert_eq!(parse_weekday(&format!(" {}", name)), Some(weekday)); + assert_eq!(parse_weekday(&format!(" {} ", name)), Some(weekday)); + assert_eq!(parse_weekday(&format!("{} ", name)), Some(weekday)); + + let (left, right) = name.split_at(1); + let (test_str1, test_str2) = ( + format!("{}{}", left.to_uppercase(), right.to_lowercase()), + format!("{}{}", left.to_lowercase(), right.to_uppercase()), + ); + + assert_eq!(parse_weekday(&test_str1), Some(weekday)); + assert_eq!(parse_weekday(&test_str2), Some(weekday)); + } + } + + #[test] + fn test_invalid_weekdays() { + let days = [ + "mond", + "tuesda", + "we", + "th", + "fr", + "sa", + "su", + "garbageday", + "tomorrow", + "yesterday", + ]; + for day in days { + assert!(parse_weekday(day).is_none()); + } + } +} From 70fde9fa18283f11c2e523c5c430e762b1684f52 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 13:41:06 +0000 Subject: [PATCH 004/163] Update Rust crate regex to 1.9.6 --- fuzz/Cargo.lock | 25 +++++++++++++++++++++---- fuzz/Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 5a7c0fd..fc384e7 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -169,6 +169,22 @@ version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -189,6 +205,7 @@ name = "parse_datetime" version = "0.5.0" dependencies = [ "chrono", + "nom", "regex", ] @@ -248,9 +265,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.5" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", @@ -260,9 +277,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index b5a0de8..1f997e2 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -9,7 +9,7 @@ cargo-fuzz = true [dependencies] rand = "0.8.5" libfuzzer-sys = "0.4" -regex = "1.9.5" +regex = "1.9.6" chrono = { version="0.4", default-features=false, features=["std", "alloc", "clock"] } [dependencies.parse_datetime] From bddcc6067f61b0d89448648cb53e6635df2355af Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 21:57:23 +0000 Subject: [PATCH 005/163] Update Rust crate regex to v1.10.0 --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 2 +- fuzz/Cargo.lock | 12 ++++++------ fuzz/Cargo.toml | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd3b98a..eb10320 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,9 +114,9 @@ checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "minimal-lexical" @@ -178,9 +178,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "d119d7c7ca818f8a53c300863d4f87566aac09943aef5b355bb83969dae75d87" dependencies = [ "aho-corasick", "memchr", @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaecc05d5c4b5f7da074b9a0d1a0867e71fd36e7fc0482d8bcfe8e8fc56290" +checksum = "5d58da636bd923eae52b7e9120271cbefb16f399069ee566ca5ebf9c30e32238" dependencies = [ "aho-corasick", "memchr", @@ -201,9 +201,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" +checksum = "c3cbb081b9784b07cceb8824c8583f86db4814d172ab043f3c23f7dc600bf83d" [[package]] name = "syn" diff --git a/Cargo.toml b/Cargo.toml index 5255ddb..a9649b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,6 @@ repository = "https://github.com/uutils/parse_datetime" readme = "README.md" [dependencies] -regex = "1.9" +regex = "1.10" chrono = { version="0.4", default-features=false, features=["std", "alloc", "clock"] } nom = "7.1.3" diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index fc384e7..07d9c91 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -265,9 +265,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.6" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "d119d7c7ca818f8a53c300863d4f87566aac09943aef5b355bb83969dae75d87" dependencies = [ "aho-corasick", "memchr", @@ -277,9 +277,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "5d58da636bd923eae52b7e9120271cbefb16f399069ee566ca5ebf9c30e32238" dependencies = [ "aho-corasick", "memchr", @@ -288,9 +288,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c3cbb081b9784b07cceb8824c8583f86db4814d172ab043f3c23f7dc600bf83d" [[package]] name = "syn" diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 1f997e2..3394ff3 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -9,7 +9,7 @@ cargo-fuzz = true [dependencies] rand = "0.8.5" libfuzzer-sys = "0.4" -regex = "1.9.6" +regex = "1.10.0" chrono = { version="0.4", default-features=false, features=["std", "alloc", "clock"] } [dependencies.parse_datetime] From 57d3527d819fc1214139d092438ba76ec6eed173 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 16:17:34 +0000 Subject: [PATCH 006/163] Update Rust crate regex to 1.10.1 --- fuzz/Cargo.lock | 12 ++++++------ fuzz/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 07d9c91..f3290c3 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -265,9 +265,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d119d7c7ca818f8a53c300863d4f87566aac09943aef5b355bb83969dae75d87" +checksum = "aaac441002f822bc9705a681810a4dd2963094b9ca0ddc41cb963a4c189189ea" dependencies = [ "aho-corasick", "memchr", @@ -277,9 +277,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d58da636bd923eae52b7e9120271cbefb16f399069ee566ca5ebf9c30e32238" +checksum = "5011c7e263a695dc8ca064cddb722af1be54e517a280b12a5356f98366899e5d" dependencies = [ "aho-corasick", "memchr", @@ -288,9 +288,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3cbb081b9784b07cceb8824c8583f86db4814d172ab043f3c23f7dc600bf83d" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "syn" diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 3394ff3..cc53ed1 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -9,7 +9,7 @@ cargo-fuzz = true [dependencies] rand = "0.8.5" libfuzzer-sys = "0.4" -regex = "1.10.0" +regex = "1.10.1" chrono = { version="0.4", default-features=false, features=["std", "alloc", "clock"] } [dependencies.parse_datetime] From 4dfa20c7b02fdebc5cfaf1e6a5158478b139635a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:22:22 +0000 Subject: [PATCH 007/163] Update Rust crate regex to 1.10.2 --- fuzz/Cargo.lock | 8 ++++---- fuzz/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index f3290c3..d0cde42 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -265,9 +265,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaac441002f822bc9705a681810a4dd2963094b9ca0ddc41cb963a4c189189ea" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -277,9 +277,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5011c7e263a695dc8ca064cddb722af1be54e517a280b12a5356f98366899e5d" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index cc53ed1..ab1fee8 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -9,7 +9,7 @@ cargo-fuzz = true [dependencies] rand = "0.8.5" libfuzzer-sys = "0.4" -regex = "1.10.1" +regex = "1.10.2" chrono = { version="0.4", default-features=false, features=["std", "alloc", "clock"] } [dependencies.parse_datetime] From 8ef448acb5d68487483289552d3dde4571b4c164 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 26 Nov 2023 15:58:00 +0100 Subject: [PATCH 008/163] Update of the version in the readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 31a1147..fff2eab 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -parse_datetime = "0.4.0" +parse_datetime = "0.5.0" ``` Then, import the crate and use the `parse_datetime_at_date` function: From 5d11c142b5b9632837d13fc08e73a7b56567a466 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 21 Jan 2024 15:53:29 +0000 Subject: [PATCH 009/163] Update Rust crate regex to 1.10.3 --- fuzz/Cargo.lock | 8 ++++---- fuzz/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index d0cde42..bb78b87 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -265,9 +265,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -277,9 +277,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" dependencies = [ "aho-corasick", "memchr", diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index ab1fee8..7e5c2f2 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -9,7 +9,7 @@ cargo-fuzz = true [dependencies] rand = "0.8.5" libfuzzer-sys = "0.4" -regex = "1.10.2" +regex = "1.10.3" chrono = { version="0.4", default-features=false, features=["std", "alloc", "clock"] } [dependencies.parse_datetime] From 1ded0a062cc02b3722c71a9c0b334e0ac016be19 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Mon, 22 Jan 2024 08:29:59 +0100 Subject: [PATCH 010/163] ci: use dtolnay/rust-toolchain instead of action_rs/toolchain to get rid of some CI warnings --- .github/workflows/ci.yml | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27b4c17..00a5b73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,11 +14,7 @@ jobs: os: [ubuntu-latest, macOS-latest, windows-latest] steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: dtolnay/rust-toolchain@stable - uses: actions-rs/cargo@v1 with: command: check @@ -31,11 +27,7 @@ jobs: os: [ubuntu-latest, macOS-latest, windows-latest] steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: dtolnay/rust-toolchain@stable - uses: actions-rs/cargo@v1 with: command: test @@ -45,11 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: dtolnay/rust-toolchain@stable - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 with: @@ -64,11 +52,7 @@ jobs: os: [ubuntu-latest, macOS-latest, windows-latest] steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: dtolnay/rust-toolchain@stable - run: rustup component add clippy - uses: actions-rs/cargo@v1 with: @@ -108,11 +92,7 @@ jobs: outputs CODECOV_FLAGS - name: rust toolchain ~ install - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ steps.vars.outputs.TOOLCHAIN }} - default: true - profile: minimal # minimal component installation (ie, no documentation) + uses: dtolnay/rust-toolchain@nightly - name: Test uses: actions-rs/cargo@v1 with: From c39e01748c86e803997cc6bd3b9f884423986ac8 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Mon, 22 Jan 2024 09:26:32 +0100 Subject: [PATCH 011/163] ci: remove actions-rs/cargo & use cargo directly --- .github/workflows/ci.yml | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00a5b73..90f47de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,9 +15,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - uses: actions-rs/cargo@v1 - with: - command: check + - run: cargo check test: name: cargo test @@ -28,9 +26,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - uses: actions-rs/cargo@v1 - with: - command: test + - run: cargo test fmt: name: cargo fmt --all -- --check @@ -39,10 +35,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: rustup component add rustfmt - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + - run: cargo fmt --all -- --check clippy: name: cargo clippy -- -D warnings @@ -54,10 +47,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: rustup component add clippy - - uses: actions-rs/cargo@v1 - with: - command: clippy - args: -- -D warnings + - run: cargo clippy -- -D warnings coverage: name: Code Coverage @@ -94,10 +84,7 @@ jobs: - name: rust toolchain ~ install uses: dtolnay/rust-toolchain@nightly - name: Test - uses: actions-rs/cargo@v1 - with: - command: test - args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast + run: cargo test ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast env: CARGO_INCREMENTAL: "0" RUSTC_WRAPPER: "" From 040561c2354f8419a31fd4b42fdcb523ea2bf4b0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 19:43:11 +0000 Subject: [PATCH 012/163] chore(deps): update codecov/codecov-action action to v4 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90f47de..fd37b4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,7 +122,7 @@ jobs: grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" echo "report=${COVERAGE_REPORT_FILE}" >> $GITHUB_OUTPUT - name: Upload coverage results (to Codecov.io) - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 # if: steps.vars.outputs.HAS_CODECOV_TOKEN with: # token: ${{ secrets.CODECOV_TOKEN }} From 9bb047eeab93aac8e40b5a2d4af8ef0c53e71368 Mon Sep 17 00:00:00 2001 From: David Morrison Date: Wed, 31 Jan 2024 15:13:23 -0800 Subject: [PATCH 013/163] fix readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fff2eab..6f3b031 100644 --- a/README.md +++ b/README.md @@ -38,13 +38,13 @@ assert_eq!( ); ``` -For DateTime parsing, import the `parse_datetime` module: +For DateTime parsing, import the `parse_datetime` function: ```rs -use parse_datetime::parse_datetime::from_str; +use parse_datetime::parse_datetime; use chrono::{Local, TimeZone}; -let dt = from_str("2021-02-14 06:37:47"); +let dt = parse_datetime("2021-02-14 06:37:47"); assert_eq!(dt.unwrap(), Local.with_ymd_and_hms(2021, 2, 14, 6, 37, 47).unwrap()); ``` From 261b28db2236afc1dcc25318ec7f3bc1650a5068 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Tue, 6 Feb 2024 09:58:43 +0100 Subject: [PATCH 014/163] ci: use codecov token --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd37b4d..281a34e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,7 +125,7 @@ jobs: uses: codecov/codecov-action@v4 # if: steps.vars.outputs.HAS_CODECOV_TOKEN with: - # token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} file: ${{ steps.coverage.outputs.report }} ## flags: IntegrationTests, UnitTests, ${{ steps.vars.outputs.CODECOV_FLAGS }} flags: ${{ steps.vars.outputs.CODECOV_FLAGS }} From 249c079790469b0e3f7a3abb999bca3748948ff8 Mon Sep 17 00:00:00 2001 From: mhead Date: Sun, 3 Mar 2024 22:54:01 +0530 Subject: [PATCH 015/163] parse time only strings --- src/lib.rs | 6 ++ src/parse_time_only_str.rs | 120 +++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 src/parse_time_only_str.rs diff --git a/src/lib.rs b/src/lib.rs index de65b56..56bd14a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ use std::fmt::{self, Display}; mod parse_relative_time; mod parse_timestamp; +mod parse_time_only_str; mod parse_weekday; use chrono::{ @@ -237,6 +238,11 @@ pub fn parse_datetime_at_date + Clone>( } } + // parse time only dates + if let Some(date_time) = parse_time_only_str::parse_time_only(date, s.as_ref()) { + return Ok(date_time); + } + // Default parse and failure s.as_ref() .parse() diff --git a/src/parse_time_only_str.rs b/src/parse_time_only_str.rs new file mode 100644 index 0000000..69ad488 --- /dev/null +++ b/src/parse_time_only_str.rs @@ -0,0 +1,120 @@ +use chrono::{DateTime, FixedOffset, Local, NaiveTime, TimeZone}; +use regex::Regex; + +mod time_only_formats { + pub const HH_MM: &str = "%R"; + pub const HH_MM_SS: &str = "%T"; + pub const TWELVEHOUR: &str = "%r"; +} + +pub(crate) fn parse_time_only(date: DateTime, s: &str) -> Option> { + let re = + Regex::new(r"^(?