I would like to format some commands execution times in a human readable format, for example:
3 -> 3ms
1100 -> 1s 100ms
62000 -> 1m 2s
etc ..
Taking into account days, hours, minutes, seconds, ...
Is it possible using C#
?
I would like to format some commands execution times in a human readable format, for example:
3 -> 3ms
1100 -> 1s 100ms
62000 -> 1m 2s
etc ..
Taking into account days, hours, minutes, seconds, ...
Is it possible using C#
?
You can use TimeSpan class, something like this:
TimeSpan t = TimeSpan.FromMilliseconds(ms);
string answer = string.Format("{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms",
t.Hours,
t.Minutes,
t.Seconds,
t.Milliseconds);
It's quite similar as this thread I've just found:
What is the best way to convert seconds into (Hour:Minutes:Seconds:Milliseconds) time?
00h:00m:00s:003ms
instead of 3ms
for the input 3
, so I don't think it's exactly what the OP wants ;) –
Endothermic I know this is old, but I wanted to answer with a great nuget package.
Install-Package Humanizer
https://www.nuget.org/packages/Humanizer
https://github.com/MehdiK/Humanizer
Example from their readme.md
TimeSpan.FromMilliseconds(1299630020).Humanize(4) => "2 weeks, 1 day, 1 hour, 30 seconds"
What about this?
var ts = TimeSpan.FromMilliseconds(86300000 /*whatever */);
var parts = string
.Format("{0:D2}d:{1:D2}h:{2:D2}m:{3:D2}s:{4:D3}ms",
ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds)
.Split(':')
.SkipWhile(s => Regex.Match(s, @"00\w").Success) // skip zero-valued components
.ToArray();
var result = string.Join(" ", parts); // combine the result
Console.WriteLine(result); // prints '23h 58m 20s 000ms'
@"^00\w"
as the Regex. –
Inbreed You could utilize the static TimeSpan.FromMilliseconds
method as well as the resulting TimeSpan
's Days
, Hours
, Minutes
, Seconds
and Milliseconds
properties.
But I'm busy right now, so I'll leave the rest to you as an exercise.
.NET 4 accepts format in TimeSpan.Tostring()
.
For other you can implement extension method like
public static string Format(this TimeSpan obj)
{
StringBuilder sb = new StringBuilder();
if (obj.Hours != 0)
{
sb.Append(obj.Hours);
sb.Append(" ");
sb.Append("hours");
sb.Append(" ");
}
if (obj.Minutes != 0 || sb.Length != 0)
{
sb.Append(obj.Minutes);
sb.Append(" ");
sb.Append("minutes");
sb.Append(" ");
}
if (obj.Seconds != 0 || sb.Length != 0)
{
sb.Append(obj.Seconds);
sb.Append(" ");
sb.Append("seconds");
sb.Append(" ");
}
if (obj.Milliseconds != 0 || sb.Length != 0)
{
sb.Append(obj.Milliseconds);
sb.Append(" ");
sb.Append("Milliseconds");
sb.Append(" ");
}
if (sb.Length == 0)
{
sb.Append(0);
sb.Append(" ");
sb.Append("Milliseconds");
}
return sb.ToString();
}
and call as
foreach (TimeSpan span in spans)
{
MessageBox.Show(string.Format("{0}", span.Format()));
}
obj.Hours
) should be obj.TotalHours,ToString("0")
. .TotalHours
so it can show values above 24h, and ,ToString("0")
to convert it to a single digit instead of a comma separated value. –
Selfgovernment public static string ReadableTime(int milliseconds)
{
var parts = new List<string>();
Action<int, string> add = (val, unit) => { if (val > 0) parts.Add(val+unit); };
var t = TimeSpan.FromMilliseconds(milliseconds);
add(t.Days, "d");
add(t.Hours, "h");
add(t.Minutes, "m");
add(t.Seconds, "s");
add(t.Milliseconds, "ms");
return string.Join(" ", parts);
}
t.TotalDays
also works). –
Pricking Old question, new answer:
public static string GetReadableTimeByMs(long ms)
{
TimeSpan t = TimeSpan.FromMilliseconds(ms);
if (t.Hours > 0) return $"{t.Hours}h:{t.Minutes}m:{t.Seconds}s";
else if (t.Minutes > 0) return $"{t.Minutes}m:{t.Seconds}s";
else if (t.Seconds > 0) return $"{t.Seconds}s:{t.Milliseconds}ms";
else return $"{t.Milliseconds}ms";
}
This probably has a slightly different output than requested, but the result is human readable - and it can be adapted to fit many other use cases.
private static List<double> _intervals = new List<double>
{
1.0 / 1000 / 1000,
1.0 / 1000,
1,
1000,
60 * 1000,
60 * 60 * 1000
};
private static List<string> _units = new List<string>
{
"ns",
"µs",
"ms",
"s",
"min",
"h"
};
public string FormatUnits(double milliseconds, string format = "#.#")
{
var interval = _intervals.Last(i=>i<=milliseconds);
var index = _intervals.IndexOf(interval);
return string.Concat((milliseconds / interval).ToString(format) , " " , _units[index]);
}
Example calls...
Console.WriteLine(FormatUnits(1));
Console.WriteLine(FormatUnits(20));
Console.WriteLine(FormatUnits(300));
Console.WriteLine(FormatUnits(4000));
Console.WriteLine(FormatUnits(50000));
Console.WriteLine(FormatUnits(600000));
Console.WriteLine(FormatUnits(7000000));
Console.WriteLine(FormatUnits(80000000));
...and results:
1000 µs
20 ms
300 ms
4 s
50 s
10 min
1.9 h
22.2 h
For example to get 00:01:35.0090000
as 0 hours, 1 minutes, 35 seconds and 9 milliseconds you can use this:
Console.WriteLine("Time elapsed:" +TimeSpan.FromMilliseconds(numberOfMilliseconds).ToString());
Your output:
Time elapsed: 00:01:35.0090000
Maybe something like this?
DateTime.Now.ToString("%d 'd' %h 'h' %m 'm' %s 'seconds' %ms 'ms'")
TimeSpan
s, not DateTime
s. With a DateTime
, you'll always end up with at least one day, which wouldn't really match the input of 3 milliseconds. –
Endothermic You can use TimeSpan.FromMilliseconds
function
var tspan = TimeSpan.FromMilliseconds(YOUR_MILLI_SECONDS);
int h = tspan.Hours;
int m = tspan.Minutes;
int s = tspan.Seconds;
Well i normally hate writing if statements but some times what you really have is a nail and need a hammer.
string time;
if (elapsedTime.TotalMinutes > 2)
time = string.Format("{0:n2} minutes", elapsedTime.TotalMinutes);
else if (elapsedTime.TotalSeconds > 15)
time = string.Format("{0:n2} seconds", elapsedTime.TotalSeconds);
else
time = string.Format("{0:n0}ms", elapsedTime.TotalMilliseconds);
Here my code working for different input value (h, m, s, ms).
public static string FormatTime(this object inputTime, bool displayOriginalValue = true, string inputType = "ms")
{
string originalValue = $"{inputTime}{inputType}";
try
{
//"ms", "s", "min", "h", "d"
double ms = double.Parse(inputTime.ToString());
switch (inputType.ToUpper())
{
case "S":
ms = ms * 1000;
break;
case "MIN":
case "M":
ms = ms * 1000 * 60;
break;
case "H":
ms = ms * 1000 * 60 * 60;
break;
case "D":
ms = ms * 1000 * 60 * 60 * 24;
break;
default:
break;
}
TimeSpan ts = TimeSpan.FromMilliseconds(ms);
var parts = string
.Format("{0:D2}d:{1:D2}h:{2:D2}m:{3:D2}s:{4:D3}ms",
ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds)
.Split(':')
.SkipWhile(s => Regex.Match(s, @"00\w").Success) // skip zero-valued components
.ToArray();
var result = string.Join(" ", parts); // combine the result
if (ms > 0)
result = result.Replace(" 000ms", "");
if (string.IsNullOrWhiteSpace(result))
result = originalValue;
return displayOriginalValue && result.ToUpper() != originalValue.ToUpper() ? $"{result} ({inputTime}{inputType})" : result;
}
catch (Exception ex)
{
return $"Original input: {originalValue}. Error: {ex.Message}";
}
}
© 2022 - 2024 — McMap. All rights reserved.
new TimeSpan(30000).ToString()
? – AlidaTimeSpan.Format
custom string that doesn't result in "0 years 0 months 0 days 0 hours 0 min 1 sec 100 ms"? – Odine