84 lines
2.8 KiB
C#
84 lines
2.8 KiB
C#
namespace Salmon.Web;
|
|
|
|
public class TimespanHelper
|
|
{
|
|
//https://stackoverflow.com/questions/16689468/how-to-produce-human-readable-strings-to-represent-a-timespan (@rene)
|
|
public static string GetReadableTimespan(TimeSpan ts)
|
|
{
|
|
// formats and its cutoffs based on totalseconds
|
|
var cutoff = new SortedList<long, string> {
|
|
{59, "{3:S}" },
|
|
{60, "{2:M}" },
|
|
{60*60-1, "{2:M}, {3:S}"},
|
|
{60*60, "{1:H}"},
|
|
{24*60*60-1, "{1:H}, {2:M}"},
|
|
{24*60*60, "{0:D}"},
|
|
{Int64.MaxValue , "{0:D}, {1:H}"}
|
|
};
|
|
|
|
// find nearest best match
|
|
var find = cutoff.Keys.ToList()
|
|
.BinarySearch((long)ts.TotalSeconds);
|
|
// negative values indicate a nearest match
|
|
var near = find < 0 ? Math.Abs(find) - 1 : find;
|
|
// use custom formatter to get the string
|
|
return String.Format(
|
|
new HMSFormatter(),
|
|
cutoff[cutoff.Keys[near]],
|
|
ts.Days,
|
|
ts.Hours,
|
|
ts.Minutes,
|
|
ts.Seconds);
|
|
}
|
|
|
|
// formatter for forms of
|
|
// seconds/hours/day
|
|
public class HMSFormatter : ICustomFormatter, IFormatProvider
|
|
{
|
|
// list of Formats, with a P customformat for pluralization
|
|
static Dictionary<string, string> timeformats = new Dictionary<string, string> {
|
|
{"S", "{0:P:seconds:second}"},
|
|
{"M", "{0:P:minutes:minute}"},
|
|
{"H","{0:P:hours:hour}"},
|
|
{"D", "{0:P:days:day}"}
|
|
};
|
|
|
|
public string Format(string format, object arg, IFormatProvider formatProvider)
|
|
{
|
|
return String.Format(new PluralFormatter(), timeformats[format], arg);
|
|
}
|
|
|
|
public object GetFormat(Type formatType)
|
|
{
|
|
return formatType == typeof(ICustomFormatter) ? this : null;
|
|
}
|
|
}
|
|
|
|
// formats a numeric value based on a format P:Plural:Singular
|
|
public class PluralFormatter : ICustomFormatter, IFormatProvider
|
|
{
|
|
|
|
public string Format(string format, object arg, IFormatProvider formatProvider)
|
|
{
|
|
if (arg != null)
|
|
{
|
|
var parts = format.Split(':'); // ["P", "Plural", "Singular"]
|
|
|
|
if (parts[0] == "P") // correct format?
|
|
{
|
|
// which index postion to use
|
|
int partIndex = (arg.ToString() == "1") ? 2 : 1;
|
|
// pick string (safe guard for array bounds) and format
|
|
return String.Format("{0} {1}", arg, (parts.Length > partIndex ? parts[partIndex] : ""));
|
|
}
|
|
}
|
|
return String.Format(format, arg);
|
|
}
|
|
|
|
public object GetFormat(Type formatType)
|
|
{
|
|
return formatType == typeof(ICustomFormatter) ? this : null;
|
|
}
|
|
}
|
|
}
|