You've already forked parse_datetime
mirror of
https://github.com/uutils/parse_datetime.git
synced 2026-06-10 16:13:15 -07:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf6f14bc09 | |||
| 6a52551dea | |||
| 21e7e01fc8 | |||
| 1359dc9349 | |||
| daec32d5c4 | |||
| 7a3d0bafca | |||
| 537df73bdd | |||
| 3e4c6e3b6c | |||
| 29e64c3cda | |||
| db00d0686f | |||
| 1f0eae3536 |
@@ -0,0 +1 @@
|
||||
target/
|
||||
Generated
+1
-1
@@ -13,7 +13,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "humantime_to_duration"
|
||||
version = "0.1.2"
|
||||
version = "0.2.1"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"time",
|
||||
|
||||
+2
-1
@@ -1,10 +1,11 @@
|
||||
[package]
|
||||
name = "humantime_to_duration"
|
||||
description = " parsing human-readable relative time strings and converting them to a Duration"
|
||||
version = "0.1.2"
|
||||
version = "0.2.1"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/uutils/humantime_to_duration"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
regex = "1.7"
|
||||
|
||||
@@ -11,6 +11,7 @@ A Rust crate for parsing human-readable relative time strings and converting the
|
||||
- Parses a variety of human-readable time formats.
|
||||
- Supports positive and negative durations.
|
||||
- Allows for chaining time units (e.g., "1 hour 2 minutes" or "2 days and 2 hours").
|
||||
- Calculate durations relative to a specified date.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -18,21 +19,28 @@ Add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
humantime_to_duration = "0.1.1"
|
||||
humantime_to_duration = "0.2.1"
|
||||
```
|
||||
|
||||
Then, import the crate and use the from_str function:
|
||||
Then, import the crate and use the `from_str` and `from_str_at_date` functions:
|
||||
```
|
||||
use humantime_to_duration::from_str;
|
||||
use humantime_to_duration::{from_str, from_str_at_date};
|
||||
use time::Duration;
|
||||
|
||||
let duration = from_str("+3 days");
|
||||
assert_eq!(duration.unwrap(), Duration::days(3));
|
||||
|
||||
let today = OffsetDateTime::now_utc().date();
|
||||
let yesterday = today - Duration::days(1);
|
||||
assert_eq!(
|
||||
from_str_at_date(yesterday, "2 days").unwrap(),
|
||||
Duration::days(1)
|
||||
);
|
||||
```
|
||||
|
||||
### Supported Formats
|
||||
|
||||
The `from_str` function supports the following formats for relative time:
|
||||
The `from_str` and `from_str_at_date` functions support the following formats for relative time:
|
||||
|
||||
- `num` `unit` (e.g., "-1 hour", "+3 days")
|
||||
- `unit` (e.g., "hour", "day")
|
||||
@@ -47,7 +55,7 @@ The `from_str` function supports the following formats for relative time:
|
||||
|
||||
## Return Values
|
||||
|
||||
The `from_str` function returns:
|
||||
The `from_str` and `from_str_at_date` functions return:
|
||||
|
||||
- `Ok(Duration)` - If the input string can be parsed as a relative time
|
||||
- `Err(ParseDurationError)` - If the input string cannot be parsed as a relative time
|
||||
|
||||
+75
-6
@@ -4,9 +4,9 @@
|
||||
use regex::{Error as RegexError, Regex};
|
||||
use std::error::Error;
|
||||
use std::fmt::{self, Display};
|
||||
use time::Duration;
|
||||
use time::{Date, Duration, OffsetDateTime};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ParseDurationError {
|
||||
InvalidRegex(RegexError),
|
||||
InvalidInput,
|
||||
@@ -62,7 +62,7 @@ impl From<RegexError> for ParseDurationError {
|
||||
/// * "tomorrow"
|
||||
/// * use "ago" for the past
|
||||
///
|
||||
/// [num] can be a positive or negative integer.
|
||||
/// `[num]` can be a positive or negative integer.
|
||||
/// [unit] can be one of the following: "fortnight", "week", "day", "hour",
|
||||
/// "minute", "min", "second", "sec" and their plural forms.
|
||||
///
|
||||
@@ -77,7 +77,47 @@ impl From<RegexError> for ParseDurationError {
|
||||
///
|
||||
/// This function will return `Err(ParseDurationError::InvalidInput)` if the input string
|
||||
/// cannot be parsed as a relative time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use time::Duration;
|
||||
/// use humantime_to_duration::{from_str, ParseDurationError};
|
||||
///
|
||||
/// assert_eq!(from_str("1 hour, 30 minutes").unwrap(), Duration::minutes(90));
|
||||
/// assert_eq!(from_str("tomorrow").unwrap(), Duration::days(1));
|
||||
/// assert!(matches!(from_str("invalid"), Err(ParseDurationError::InvalidInput)));
|
||||
/// ```
|
||||
pub fn from_str(s: &str) -> Result<Duration, ParseDurationError> {
|
||||
from_str_at_date(OffsetDateTime::now_utc().date(), s)
|
||||
}
|
||||
|
||||
/// Parses a duration string and returns a `Duration` instance, with the duration
|
||||
/// calculated from the specified date.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `date` - A `Date` instance representing the base date for the calculation
|
||||
/// * `s` - A string slice representing the relative time.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return `Err(ParseDurationError::InvalidInput)` if the input string
|
||||
/// cannot be parsed as a relative time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use time::{Date, Duration, OffsetDateTime};
|
||||
/// use humantime_to_duration::{from_str_at_date, ParseDurationError};
|
||||
/// let today = OffsetDateTime::now_utc().date();
|
||||
/// let yesterday = today - Duration::days(1);
|
||||
/// assert_eq!(
|
||||
/// from_str_at_date(yesterday, "2 days").unwrap(),
|
||||
/// Duration::days(1) // 1 day from the specified date + 1 day from the input string
|
||||
/// );
|
||||
/// ```
|
||||
pub fn from_str_at_date(date: Date, s: &str) -> Result<Duration, ParseDurationError> {
|
||||
let time_pattern: Regex = Regex::new(
|
||||
r"(?x)
|
||||
(?:(?P<value>[-+]?\d*)\s*)?
|
||||
@@ -149,16 +189,19 @@ pub fn from_str(s: &str) -> Result<Duration, ParseDurationError> {
|
||||
if captures_processed == 0 {
|
||||
Err(ParseDurationError::InvalidInput)
|
||||
} else {
|
||||
Ok(total_duration)
|
||||
let time_now = OffsetDateTime::now_utc().date();
|
||||
let date_duration = date - time_now;
|
||||
|
||||
Ok(total_duration + date_duration)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::from_str;
|
||||
use super::ParseDurationError;
|
||||
use time::Duration;
|
||||
use super::{from_str, from_str_at_date};
|
||||
use time::{Date, Duration, Month, OffsetDateTime};
|
||||
|
||||
#[test]
|
||||
fn test_years() {
|
||||
@@ -300,4 +343,30 @@ mod tests {
|
||||
_ => assert!(false),
|
||||
}*/
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_at_date() {
|
||||
let date = Date::from_calendar_date(2014, Month::September, 5).unwrap();
|
||||
let now = OffsetDateTime::now_utc().date();
|
||||
let days_diff = (date - now).whole_days();
|
||||
|
||||
assert_eq!(
|
||||
from_str_at_date(date, "1 day").unwrap(),
|
||||
Duration::days(days_diff + 1)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
from_str_at_date(date, "2 hours").unwrap(),
|
||||
Duration::days(days_diff) + Duration::hours(2)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_input_at_date() {
|
||||
let date = Date::from_calendar_date(2014, Month::September, 5).unwrap();
|
||||
assert!(matches!(
|
||||
from_str_at_date(date, "invalid"),
|
||||
Err(ParseDurationError::InvalidInput)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
+25
-10
@@ -1,20 +1,14 @@
|
||||
use humantime_to_duration::{from_str, ParseDurationError};
|
||||
use time::Duration;
|
||||
use humantime_to_duration::{from_str, from_str_at_date, ParseDurationError};
|
||||
use time::{Duration, OffsetDateTime};
|
||||
|
||||
#[test]
|
||||
fn test_invalid_input() {
|
||||
let result = from_str("foobar");
|
||||
println!("{result:?}");
|
||||
match result {
|
||||
Err(ParseDurationError::InvalidInput) => assert!(true),
|
||||
_ => assert!(false),
|
||||
}
|
||||
assert_eq!(result, Err(ParseDurationError::InvalidInput));
|
||||
|
||||
let result = from_str("invalid 1");
|
||||
match result {
|
||||
Err(ParseDurationError::InvalidInput) => assert!(true),
|
||||
_ => assert!(false),
|
||||
}
|
||||
assert_eq!(result, Err(ParseDurationError::InvalidInput));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -135,3 +129,24 @@ fn test_display_should_fail() {
|
||||
"Invalid input string: cannot be parsed as a relative time"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_at_date_day() {
|
||||
let today = OffsetDateTime::now_utc().date();
|
||||
let yesterday = today - Duration::days(1);
|
||||
assert_eq!(
|
||||
from_str_at_date(yesterday, "2 days").unwrap(),
|
||||
Duration::days(1)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_input_at_date() {
|
||||
let today = OffsetDateTime::now_utc().date();
|
||||
let result = from_str_at_date(today, "foobar");
|
||||
println!("{result:?}");
|
||||
assert_eq!(result, Err(ParseDurationError::InvalidInput));
|
||||
|
||||
let result = from_str_at_date(today, "invalid 1r");
|
||||
assert_eq!(result, Err(ParseDurationError::InvalidInput));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user