Configurable, precise and fast string parser to a rust std::time::Duration

Released API Docs | Changelog


GitHub branch checks state Crates.io docs.rs MSRV

Table of Contents

Overview

fundu provides a parser to parse strings into a [std::time::Duration]. It tries to improve on the standard method Duration::from_secs_f64(input.parse().unwrap()) ([Duration::from_secs_f64]) by

This library aims for low runtime costs (See Benchmarks) and being a lightweight crate. fundu is purely built on top of the rust stdlib, and there are no additional dependencies required. The accepted string format is almost the same like the scientific floating point format and compatible to the [f64::from_str] format. In other words, if the accepted input string could previously converted to an f64 with f64::from_str, no change is needed to accept the same format with fundu. For further details see the Documentation!

Installation

Add this to Cargo.toml

toml [dependencies] fundu = "0.2.2"

Examples

If only the default configuration is required, the parse_duration method can be used.

```rust use fundu::parse_duration; use std::time::Duration;

let input = "1.0e2s"; asserteq!(parseduration(input).unwrap(), Duration::new(100, 0)); ```

When a customization of the accepted TimeUnits is required, then the builder DurationParser can be used.

```rust use fundu::DurationParser; use std::time::Duration;

let input = "3m"; asserteq!(DurationParser::withalltimeunits().parse(input).unwrap(), Duration::new(180, 0)); ```

When no time units are configured, seconds is assumed.

```rust use fundu::DurationParser; use std::time::Duration;

let input = "1.0e2"; asserteq!(DurationParser::withouttime_units().parse(input).unwrap(), Duration::new(100, 0)); ```

However, this will return an error because y (Years) is not a default time unit.

```rust use fundu::DurationParser;

let input = "3y"; assert!(DurationParser::new().parse(input).is_err()); ```

The parser is reusable and the set of time units is fully customizable

```rust use fundu::{DurationParser, TimeUnit::*}; use std::time::Duration;

let mut parser = DurationParser::withtimeunits(&[NanoSecond, Minute, Hour]); for (input, expected) in &[ ("9e3ns", Duration::new(0, 9000)), ("10m", Duration::new(600, 0)), ("1.1h", Duration::new(3960, 0)), ("7", Duration::new(7, 0)), ] { assert_eq!(parser.parse(input).unwrap(), *expected); } ```

Also, fundu tries to give informative error messages

```rust use fundu::DurationParser; use std::time::Duration;

asserteq!( DurationParser::withouttimeunits() .parse("1y") .unwraperr() .to_string(), "Syntax error: No time units allowed but found: y at column 1" ); ```

Time units

Time units are used to calculate the final Duration. Seconds are the default unit if no time unit was present in the input string. The table below gives an overview of the constructor methods and which time units are available. If a custom set of time units is required, DurationParser::with_time_units can be used.

Name | Time unit | Calculation | DurationParser::new \| parse_duration | DurationParser:: with_all_time_units | DurationParser:: without_time_units --- | --- | --- | --- | --- | --- Nanoseconds | ns | 1e-9s | ☑ | ☑ | ☐ Microseconds | Ms | 1e-6s | ☑ | ☑ | ☐ Milliseconds | ms | 1e-3s |☑ | ☑ | ☐ Seconds | s | SI definition | ☑ | ☑ | ☐ (seconds is still used as base) Minutes | m | 60s | ☑ | ☑ | ☐ Hours | h | 60m | ☑ | ☑ | ☐ Days | d | 24h | ☑ | ☑ | ☐ Weeks | w | 7d | ☑ | ☑ | ☐ Months | M | Year / 12 | ☐ | ☑ | ☐ Years | y | 365.25d | ☐ | ☑ | ☐

Note, that Months and Years are not included in the default configuration. The current implementation uses an approximate calculation of Months and Years in seconds. If they are included in the final configuration, the Julian year based calculation is used. (See table)

Benchmarks

To run the benchmarks on your machine, clone the repository

bash git clone https://github.com/Joining7943/fundu.git cd fundu

and then run the benchmarks with

bash cargo bench

To get a rough idea about the parsing times, here the average parsing speed of two inputs on a comparatively slow machine (Quad core 3000Mhz, 8GB DDR3, Linux)

Input | parser with time units | avg parsing time | ~ samples / s --- | --- | --- | --- 1 | no | 48.716 ns | 20_527_136.874 1 | yes | 52.548 ns | 19_030_219.989 format!("{}.{}e-1022", "1".repeat(1022), "1".repeat(1022)) | no | 3.7219 µs | 268_679.975 format!("{}.{}e-1022", "1".repeat(1022), "1".repeat(1022)) | yes | 3.7132 µs | 269_309.490

Platform support

Since fundu is purely built on top of the rust stdlib without platform specific code, this library should be compatible with all platforms. Please open an issue if you find any unsupported platforms which rust itself supports.

See also the CI

TODO

See also Changelog

License

MIT license (LICENSE or http://opensource.org/licenses/MIT)