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?
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"
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.
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'
.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()));
}
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);
}
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
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";
}
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
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;
Maybe something like this?
DateTime.Now.ToString("%d 'd' %h 'h' %m 'm' %s 'seconds' %ms 'ms'")
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);