From 84ff04f35de5a70e15f81ccc64fbd1bd07e119ea Mon Sep 17 00:00:00 2001 From: David Peter Date: Mon, 5 Oct 2026 10:18:42 +0200 Subject: [PATCH] Support minutes, hours, and time unit aliases --- CHANGELOG.md | 1 + doc/hyperfine.1 | 17 +++++++++++++++-- src/cli.rs | 13 +++++++++---- src/options.rs | 8 +++++--- src/output/format.rs | 3 ++- src/util/units.rs | 10 ++++++++++ 6 files changed, 42 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de2cb35..70027f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Features +- Add minutes and hours to `--time-unit`, along with abbreviated and plural unit names such as `ms`, `min`, and `hours` (@sharkdp) - Add `--reference-name` option to give a meaningful name to the reference command, see #808 (@niklasdewally) - The `--ignore-failure` option now supports a comma-separated list of exit codes to ignore (e.g., `--ignore-failure=1,2`), see #836 (@sharkdp) - Python scripts: Add `--time-unit` option to `advanced_statistics.py` (@sharkdp) diff --git a/doc/hyperfine.1 b/doc/hyperfine.1 index 5e68161..628dd3f 100644 --- a/doc/hyperfine.1 +++ b/doc/hyperfine.1 @@ -255,8 +255,21 @@ order benchmarks by mean runtime .HP \fB\-u\fR, \fB\-\-time\-unit\fR \fIUNIT\fP .IP -Set the time unit to be used. Possible values: microsecond, millisecond, second. If -the option is not given, the time unit is determined automatically. +Set the time unit to be used. If the option is not given, the time unit is +determined automatically. Possible values: +.RS +.IP "microsecond" +Aliases: µs, us, microseconds. +.IP "millisecond" +Aliases: ms, milliseconds. +.IP "second" +Aliases: s, seconds. +.IP "minute" +Aliases: min, minutes. +.IP "hour" +Aliases: h, hours. +.RE +.IP This option affects the standard output as well as all export formats except for CSV and JSON. .HP diff --git a/src/cli.rs b/src/cli.rs index 0852470..e1586e6 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -278,10 +278,15 @@ fn build_command() -> Command { .short('u') .action(ArgAction::Set) .value_name("UNIT") - .value_parser(["microsecond", "millisecond", "second"]) - .help("Set the time unit to be used. Possible values: microsecond, millisecond, second. \ - If the option is not given, the time unit is determined automatically. \ - This option affects the standard output as well as all export formats except for CSV and JSON."), + .value_parser(["µs", "us", "microsecond", "microseconds", "ms", "millisecond", "milliseconds", "s", "second", "seconds", "min", "minute", "minutes", "h", "hour", "hours"]) + .help("Set the time unit to be used. If the option is not given, the time unit is determined automatically. \ + This option affects the standard output as well as all export formats except for CSV and JSON.\n\ + Possible values:\n \ + * 'µs', 'us', 'microsecond', 'microseconds'\n \ + * 'ms', 'millisecond', 'milliseconds'\n \ + * 's', 'second', 'seconds'\n \ + * 'min', 'minute', 'minutes'\n \ + * 'h', 'hour', 'hours'"), ) .arg( Arg::new("export-asciidoc") diff --git a/src/options.rs b/src/options.rs index 92d3823..0c1c12b 100644 --- a/src/options.rs +++ b/src/options.rs @@ -429,9 +429,11 @@ impl Options { } options.time_unit = match matches.get_one::("time-unit").map(|s| s.as_str()) { - Some("microsecond") => Some(Unit::MicroSecond), - Some("millisecond") => Some(Unit::MilliSecond), - Some("second") => Some(Unit::Second), + Some("µs" | "us" | "microsecond" | "microseconds") => Some(Unit::MicroSecond), + Some("ms" | "millisecond" | "milliseconds") => Some(Unit::MilliSecond), + Some("s" | "second" | "seconds") => Some(Unit::Second), + Some("min" | "minute" | "minutes") => Some(Unit::Minute), + Some("h" | "hour" | "hours") => Some(Unit::Hour), _ => None, }; diff --git a/src/output/format.rs b/src/output/format.rs index f1aa0d0..95a480f 100644 --- a/src/output/format.rs +++ b/src/output/format.rs @@ -21,7 +21,8 @@ pub fn format_duration_value(duration: Second, unit: Option) -> (String, U } else if (duration < 1.0 && unit.is_none()) || unit == Some(Unit::MilliSecond) { (Unit::MilliSecond.format(duration), Unit::MilliSecond) } else { - (Unit::Second.format(duration), Unit::Second) + let unit = unit.unwrap_or(Unit::Second); + (unit.format(duration), unit) } } diff --git a/src/util/units.rs b/src/util/units.rs index 4f7c730..65b81dd 100644 --- a/src/util/units.rs +++ b/src/util/units.rs @@ -11,6 +11,8 @@ pub enum Unit { Second, MilliSecond, MicroSecond, + Minute, + Hour, } impl Unit { @@ -20,6 +22,8 @@ impl Unit { Unit::Second => String::from("s"), Unit::MilliSecond => String::from("ms"), Unit::MicroSecond => String::from("µs"), + Unit::Minute => String::from("min"), + Unit::Hour => String::from("h"), } } @@ -29,6 +33,8 @@ impl Unit { Unit::Second => format!("{value:.3}"), Unit::MilliSecond => format!("{:.1}", value * 1e3), Unit::MicroSecond => format!("{:.1}", value * 1e6), + Unit::Minute => format!("{:.1}", value / 60.0), + Unit::Hour => format!("{:.1}", value / 3600.0), } } } @@ -38,6 +44,8 @@ fn test_unit_short_name() { assert_eq!("s", Unit::Second.short_name()); assert_eq!("ms", Unit::MilliSecond.short_name()); assert_eq!("µs", Unit::MicroSecond.short_name()); + assert_eq!("min", Unit::Minute.short_name()); + assert_eq!("h", Unit::Hour.short_name()); } // Note - the values are rounded when formatted. @@ -48,4 +56,6 @@ fn test_unit_format() { assert_eq!("123456.8", Unit::MilliSecond.format(value)); assert_eq!("1234.6", Unit::MicroSecond.format(0.00123456)); + assert_eq!("2.1", Unit::Minute.format(value)); + assert_eq!("0.0", Unit::Hour.format(value)); }