{"id":15902866,"url":"https://github.com/erikh/fancy-duration","last_synced_at":"2026-03-08T16:05:05.453Z","repository":{"id":62444520,"uuid":"496798203","full_name":"erikh/fancy-duration","owner":"erikh","description":"Fancier Duration Text for Rust","archived":false,"fork":false,"pushed_at":"2024-08-01T05:47:23.000Z","size":62,"stargazers_count":6,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-13T12:03:35.969Z","etag":null,"topics":["duration","rust-lang","serde"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/fancy-duration","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/erikh.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-05-26T23:11:56.000Z","updated_at":"2024-10-07T15:25:12.000Z","dependencies_parsed_at":"2022-11-01T22:30:48.350Z","dependency_job_id":"2ff78e64-4321-4564-9d63-9b958227bb26","html_url":"https://github.com/erikh/fancy-duration","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikh%2Ffancy-duration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikh%2Ffancy-duration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikh%2Ffancy-duration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikh%2Ffancy-duration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erikh","download_url":"https://codeload.github.com/erikh/fancy-duration/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221799221,"owners_count":16882380,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["duration","rust-lang","serde"],"created_at":"2024-10-06T12:00:25.019Z","updated_at":"2026-03-08T16:05:05.410Z","avatar_url":"https://github.com/erikh.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fancier Durations now in an easily consumable library\n\nA \"fancy duration\" is a text description of the duration. For example, \"1h 20m 30s\" which might be read as \"one hour, twenty minutes and thirty seconds\". Expression in a duration type is transparent through a variety of means; chrono and the time crate are supported, as well as serialization into and from string types with serde. Time support starts in years and funnels down to nanoseconds.\n\nHere are the [docs](https://docs.rs/fancy_duration).\n\nWhat follows are some usage examples. You can either wrap your duration-like type in a FancyDuration struct, or use types which allow for monkeypatched methods that allow you to work directly on the target type. For example, use AsFancyDuration to inject fancy_duration calls to perform the construction (which can be formatted or converted to string) and ParseFancyDuration to inject parse_fancy_duration constructors to accept strings into your favorite type. std::time::Duration, time::Duration, and chrono::Duration are all supported (some features may need to be required) and you can make more types eligible by implementing the AsTimes trait.\n\n```rust\nuse std::time::Duration;\nuse fancy_duration::FancyDuration;\n\npub fn main() {\n    assert_eq!(FancyDuration(Duration::new(20, 0)).to_string(), \"20s\");\n    assert_eq!(FancyDuration(Duration::new(600, 0)).to_string(), \"10m\");\n    assert_eq!(FancyDuration(Duration::new(120, 0)).to_string(), \"2m\");\n    assert_eq!(FancyDuration(Duration::new(185, 0)).to_string(), \"3m 5s\");\n    assert_eq!(FancyDuration::\u003cDuration\u003e::parse(\"3m 5s\").unwrap().duration(), Duration::new(185, 0));\n    assert_eq!(FancyDuration(Duration::new(185, 0)).to_string(), \"3m 5s\");\n\n    // these traits are also implemented for chrono and time\n    use fancy_duration::{ParseFancyDuration, AsFancyDuration};\n    assert_eq!(Duration::new(20, 0).fancy_duration().to_string(), \"20s\");\n    assert_eq!(Duration::new(600, 0).fancy_duration().to_string(), \"10m\");\n    assert_eq!(Duration::new(120, 0).fancy_duration().to_string(), \"2m\");\n    assert_eq!(Duration::new(185, 0).fancy_duration().to_string(), \"3m 5s\");\n    assert_eq!(Duration::parse_fancy_duration(\"3m 5s\".to_string()).unwrap(), Duration::new(185, 0));\n    assert_eq!(Duration::new(185, 0).fancy_duration().to_string(), \"3m 5s\");\n\n    #[cfg(feature = \"time\")]\n    {\n        // also works with time::Duration from the `time` crate\n        assert_eq!(FancyDuration(time::Duration::new(20, 0)).to_string(), \"20s\");\n        assert_eq!(FancyDuration(time::Duration::new(600, 0)).to_string(), \"10m\");\n        assert_eq!(FancyDuration(time::Duration::new(120, 0)).to_string(), \"2m\");\n        assert_eq!(FancyDuration(time::Duration::new(185, 0)).to_string(), \"3m 5s\");\n        assert_eq!(FancyDuration::\u003ctime::Duration\u003e::parse(\"3m 5s\").unwrap().duration(), time::Duration::new(185, 0));\n        assert_eq!(FancyDuration(time::Duration::new(185, 0)).to_string(), \"3m 5s\");\n    }\n\n    #[cfg(feature = \"chrono\")]\n    {\n        // also works with chrono!\n        assert_eq!(FancyDuration(chrono::Duration::seconds(20)).to_string(), \"20s\");\n        assert_eq!(FancyDuration(chrono::Duration::seconds(600)).to_string(), \"10m\");\n        assert_eq!(FancyDuration(chrono::Duration::seconds(120)).to_string(), \"2m\");\n        assert_eq!(FancyDuration(chrono::Duration::seconds(185)).to_string(), \"3m 5s\");\n        assert_eq!(FancyDuration::\u003cchrono::Duration\u003e::parse(\"3m 5s\").unwrap().duration(), chrono::Duration::seconds(185));\n        assert_eq!(FancyDuration(chrono::Duration::seconds(185)).to_string(), \"3m 5s\");\n    }\n}\n```\n\n## Benchmarks\n\nEach interval test increases the number of things that will be formatted. The first set of parse tests parse one string with several terms, the others parse a static set of 5 terms in a single iteration.\n\nBenchmarking system was a Ryzen 5900X with 64GB RAM running Linux 6.6.8 in a desktop configuration.\n\nAs of 0.9.1:\n\n```\nfancy duration format seconds: std\n                        time:   [644.13 ps 645.34 ps 646.96 ps]\nfancy duration format seconds: time\n                        time:   [6.6756 ns 6.6945 ns 6.7181 ns]\nfancy duration format seconds: chrono\n                        time:   [658.36 ps 658.73 ps 659.15 ps]\nfancy duration format minutes: std\n                        time:   [666.00 ps 666.50 ps 667.03 ps]\nfancy duration format minutes: time\n                        time:   [6.6301 ns 6.6324 ns 6.6349 ns]\nfancy duration format minutes: chrono\n                        time:   [646.99 ps 647.24 ps 647.50 ps]\nfancy duration format hours: std\n                        time:   [658.35 ps 660.83 ps 662.88 ps]\nfancy duration format hours: time\n                        time:   [6.5761 ns 6.5792 ns 6.5826 ns]\nfancy duration format hours: chrono\n                        time:   [648.05 ps 648.38 ps 648.74 ps]\nfancy duration format days: std\n                        time:   [641.06 ps 641.33 ps 641.62 ps]\nfancy duration format days: time\n                        time:   [6.5374 ns 6.5410 ns 6.5452 ns]\nfancy duration format days: chrono\n                        time:   [662.60 ps 665.24 ps 667.41 ps]\nfancy duration format weeks: std\n                        time:   [641.06 ps 641.32 ps 641.61 ps]\nfancy duration format weeks: time\n                        time:   [6.7987 ns 6.8158 ns 6.8288 ns]\nfancy duration format weeks: chrono\n                        time:   [660.01 ps 662.64 ps 665.05 ps]\nfancy duration format months: std\n                        time:   [641.66 ps 642.02 ps 642.41 ps]\nfancy duration format months: time\n                        time:   [6.5435 ns 6.5498 ns 6.5573 ns]\nfancy duration format months: chrono\n                        time:   [672.00 ps 672.39 ps 672.83 ps]\nfancy duration parse one: std\n                        time:   [332.00 ns 332.48 ns 332.98 ns]\nfancy duration parse one: time\n                        time:   [346.25 ns 346.58 ns 346.92 ns]\nfancy duration parse one: chrono\n                        time:   [369.81 ns 371.26 ns 372.65 ns]\nfancy duration parse 5 distinct items: std\n                        time:   [1.9150 µs 1.9183 µs 1.9214 µs]\nfancy duration parse 5 distinct items: time\n                        time:   [1.8446 µs 1.8474 µs 1.8503 µs]\nfancy duration parse 5 distinct items: chrono\n                        time:   [1.8281 µs 1.8311 µs 1.8345 µs]\n```\n\n## Author\n\nErik Hollensbe \u003cgit@hollensbe.org\u003e\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferikh%2Ffancy-duration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferikh%2Ffancy-duration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferikh%2Ffancy-duration/lists"}