From 9cf7d07ee358421ac07b6803b5376df0185b0389 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sun, 31 May 2020 21:44:52 +0800 Subject: [PATCH] add format_human --- README.md | 9 ++++++++ src/lib.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8c4e704..3111449 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,12 @@ Formated date: 2020-05-30 13:32:04 +08:00 ``` +```rust +format_human(Duration::from_secs(2 * 24 * 60 * 60 + 1)); +``` + +Output: +``` +2days 0hour 0min 1s +``` + diff --git a/src/lib.rs b/src/lib.rs index 801ef3a..37c8bee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,10 @@ #[macro_use] extern crate quick_error; use chrono::prelude::*; -use std::{ str::Chars, iter::Peekable }; +use std::{ + time::Duration, + str::Chars, + iter::Peekable, +}; quick_error! { #[derive(Debug)] @@ -30,6 +34,46 @@ enum SimpleDateFormatPart { Literal(String), } +pub fn format_human(d: Duration) -> String { + let mut ret = vec![]; + let millis = d.as_millis(); + if millis == 0 { + return "0ms".into(); + } + let return_ret = |v: Vec| { + let mut v = v; + v.reverse(); + v.join(" ") + }; + let left_millis = millis % 1000; + if left_millis > 0 { + ret.push(format!("{}ms", left_millis)) + } + let secs = millis / 1000; + if secs == 0 { return return_ret(ret); } + let left_secs = secs % 60; + if left_secs != 0 || !ret.is_empty() { + ret.push(format!("{}s", left_secs)); + } + let mins = secs / 60; + if mins == 0 { return return_ret(ret); } + let left_mins = mins % 60; + if left_mins != 0 || !ret.is_empty() { + ret.push(format!("{}min", left_mins)); + } + let hours = mins / 60; + if hours == 0 { return return_ret(ret); } + let left_hours = hours % 24; + if left_hours != 0 || !ret.is_empty() { + ret.push(format!("{}hour", left_hours)); + } + let days = hours / 24; + if days != 0 { + ret.push(format!("{}day{}", days, if days == 1 { "" } else { "s" })); + } + return_ret(ret) +} + #[derive(Debug)] pub struct SimpleDateFormat { parts: Vec, @@ -184,7 +228,7 @@ fn get_all_chars(c: char, chars: &mut Peekable) -> usize { } #[test] -fn it_works() { +fn test_simpledateformat_format() { let t = Utc.timestamp_millis(0); assert_eq!("1970/01/01 00:00:00.000 Z", &fmt("yyyy/MM/dd HH:mm:ss.SSS z").unwrap().format(&t)); @@ -203,3 +247,16 @@ fn it_works() { let t = Local.timestamp_millis(1590816448678); assert_eq!("Sat May 30, 2020 01:27:28.678 +08:00 PM", &fmt("EEE MMM dd, yyyy hh:mm:ss.SSS z a").unwrap().format(&t)); } + +#[test] +fn test_format_human() { + assert_eq!("0ms", format_human(Duration::from_millis(0))); + assert_eq!("11ms", format_human(Duration::from_millis(11))); + assert_eq!("11s 111ms", format_human(Duration::from_millis(11111))); + assert_eq!("1s", format_human(Duration::from_secs(1))); + assert_eq!("1min", format_human(Duration::from_secs(60))); + assert_eq!("1hour", format_human(Duration::from_secs(60 * 60))); + assert_eq!("1day", format_human(Duration::from_secs(24 * 60 * 60))); + assert_eq!("2days", format_human(Duration::from_secs(2 * 24 * 60 * 60))); + assert_eq!("2days 0hour 0min 1s", format_human(Duration::from_secs(2 * 24 * 60 * 60 + 1))); +} \ No newline at end of file