Crate fundu_gnu

source ·
Expand description

A simple to use, fast and precise gnu relative time parser fully compatible with the gnu relative time format

fundu-gnu can parse rust strings like

&strDuration
"1hour"Duration::positive(60 * 60, 0)
"minute"Duration::positive(60, 0)
"2 hours"Duration::positive(2 * 60 * 60, 0)
"-3minutes"Duration::negative(3 * 60, 0)
"3 mins ago"Duration::negative(3 * 60, 0)
"999sec +1day"Duration::positive(86_400 + 999, 0)
"55secs500week"Duration::positive(55 + 500 * 604_800, 0)
"123456789"Duration::positive(123_456_789, 0)
"42fortnight"Duration::positive(42 * 2 * 604_800, 0)
"yesterday"Duration::negative(24 * 60 * 60, 0)
"now"Duration::positive(0, 0)
"today -10seconds"Duration::negative(10, 0)

fundu parses into its own Duration which is a superset of other Durations like std::time::Duration, chrono::Duration and time::Duration. See the documentation how to easily handle the conversion between these durations.

The Format

Supported time units:

  • seconds, second, secs, sec
  • minutes, minute, mins, min
  • hours, hour
  • days, day
  • weeks, week
  • fortnights, fortnight (2 weeks)
  • months, month (fuzzy)
  • years, year (fuzzy)

Fuzzy time units are not all of equal duration and depend on a given date. If no date is given when parsing, the system time of now in UTC +0 is assumed.

The special keywords yesterday worth -1 day, tomorrow worth +1 day, today and now each worth a zero duration are allowed, too. These keywords count as a full duration and don’t accept a number, time unit or the ago time unit suffix.

Summary of the rest of the format:

  • Only numbers like "123 days" and without exponent (like "3e9 days") are allowed. Only seconds time units allow a fraction (like in "1.123456 secs")
  • Multiple durations like "1sec 2min" or "1week2secs" in the source string accumulate
  • Time units without a number (like in "second") are allowed and a value of 1 is assumed.
  • The parsed duration represents the value exactly (without rounding errors as would occur in floating point calculations) as it is specified in the source string.
  • The maximum supported duration (Duration::MAX) has u64::MAX seconds (18_446_744_073_709_551_615) and 999_999_999 nano seconds
  • parsed durations larger than the maximum duration saturate at the maximum duration
  • Negative durations like "-1min" or "1 week ago" are allowed
  • Any leading, trailing whitespace or whitespace between the number and the time unit (like in "1 \n sec") and multiple durations (like in "1week \n 2minutes") is ignored and follows the posix definition of whitespace which is:
    • Space (' ')
    • Horizontal Tab ('\x09')
    • Line Feed ('\x0A')
    • Vertical Tab ('\x0B')
    • Form Feed ('\x0C')
    • Carriage Return ('\x0D')

Please see also the gnu documentation for a description of their format.

Examples

use fundu_gnu::{Duration, RelativeTimeParser};

let parser = RelativeTimeParser::new();
assert_eq!(parser.parse("1hour"), Ok(Duration::positive(60 * 60, 0)));
assert_eq!(parser.parse("minute"), Ok(Duration::positive(60, 0)));
assert_eq!(
    parser.parse("2 hours"),
    Ok(Duration::positive(2 * 60 * 60, 0))
);
assert_eq!(parser.parse("second"), Ok(Duration::positive(1, 0)));
assert_eq!(parser.parse("-3minutes"), Ok(Duration::negative(3 * 60, 0)));
assert_eq!(
    parser.parse("3 mins ago"),
    Ok(Duration::negative(3 * 60, 0))
);
assert_eq!(
    parser.parse("999sec +1day"),
    Ok(Duration::positive(86_400 + 999, 0))
);
assert_eq!(
    parser.parse("55secs500week"),
    Ok(Duration::positive(55 + 500 * 7 * 24 * 60 * 60, 0))
);
assert_eq!(
    parser.parse("300mins20secs 5hour"),
    Ok(Duration::positive(300 * 60 + 20 + 5 * 60 * 60, 0))
);
assert_eq!(
    parser.parse("123456789"),
    Ok(Duration::positive(123_456_789, 0))
);
assert_eq!(
    parser.parse("42fortnight"),
    Ok(Duration::positive(42 * 2 * 7 * 24 * 60 * 60, 0))
);
assert_eq!(
    parser.parse("yesterday"),
    Ok(Duration::negative(24 * 60 * 60, 0))
);
assert_eq!(parser.parse("now"), Ok(Duration::positive(0, 0)));
assert_eq!(
    parser.parse("today -10seconds"),
    Ok(Duration::negative(10, 0))
);

If parsing fuzzy units then the fuzz can cause different Duration based on the given DateTime:

use fundu_gnu::{DateTime, Duration, RelativeTimeParser};

let parser = RelativeTimeParser::new();
let date_time = DateTime::from_gregorian_date_time(1970, 1, 1, 0, 0, 0, 0);
assert_eq!(
    parser.parse_with_date("+1year", Some(date_time)),
    Ok(Duration::positive(365 * 86400, 0))
);
assert_eq!(
    parser.parse_with_date("+2month", Some(date_time)),
    Ok(Duration::positive((31 + 28) * 86400, 0))
);

// 1972 is a leap year
let date_time = DateTime::from_gregorian_date_time(1972, 1, 1, 0, 0, 0, 0);
assert_eq!(
    parser.parse_with_date("+1year", Some(date_time)),
    Ok(Duration::positive(366 * 86400, 0))
);
assert_eq!(
    parser.parse_with_date("+2month", Some(date_time)),
    Ok(Duration::positive((31 + 29) * 86400, 0))
);

If parsing fuzzy units with RelativeTimeParser::parse, the DateTime of now in UTC +0 is assumed.

The global parse method does the same without the need to create a RelativeTimeParser.

use fundu_gnu::{parse, Duration};

assert_eq!(parse("123 sec"), Ok(Duration::positive(123, 0)));
assert_eq!(parse("1sec3min"), Ok(Duration::positive(1 + 3 * 60, 0)));

Convert fundu’s Duration into a std::time::Duration. Converting to chrono::Duration or time::Duration works the same but needs the chrono or time feature activated.

use fundu_gnu::{parse, SaturatingInto};

let duration = parse("123 sec").unwrap();
assert_eq!(
    TryInto::<std::time::Duration>::try_into(duration),
    Ok(std::time::Duration::new(123, 0))
);

// With saturating_into the duration will saturate at the minimum and maximum of
// std::time::Duration, so for negative values at std::time::Duration::ZERO and for positive values
// at std::time::Duration::MAX
assert_eq!(
    SaturatingInto::<std::time::Duration>::saturating_into(duration),
    std::time::Duration::new(123, 0)
);

Structs

Enums

Traits

  • Conversion which saturates at the maximum or maximum instead of overflowing

Functions