/* ----------------------------------------------------- * * File: TimeSpanFormatter.cs * Author: sven.kopacz@keysight.com * Created: 21.10.2016 * * ----------------------------------------------------- * * Description: See class summary * * ----------------------------------------------------- */ using System; using System.Collections.Generic; using System.Globalization; namespace OpenTap { /// Contains helper functions to format a time span into a human readable string. public static class TimeSpanFormatter { // Each dictionary contains a pair of string per verbosity level // The first string is the unit for the values 1 or -1, the second one is // the unit for values != 1 / -1 (plural) private static readonly Dictionary> C_DAY_UNITS = new Dictionary>() { { FormatVerbosities.SuperBrief, new Tuple(".", ".") }, { FormatVerbosities.Brief, new Tuple("d", "d") }, { FormatVerbosities.Normal, new Tuple("day", "days") }, { FormatVerbosities.Verbose, new Tuple("day", "days") }, }; private static readonly Dictionary> C_HOUR_UNITS = new Dictionary>() { { FormatVerbosities.SuperBrief, new Tuple(":", ":") }, { FormatVerbosities.Brief, new Tuple("h", "h") }, { FormatVerbosities.Normal, new Tuple("hour", "hours") }, { FormatVerbosities.Verbose, new Tuple("hour", "hours") }, }; private static readonly Dictionary> C_MINUTE_UNITS = new Dictionary>() { { FormatVerbosities.SuperBrief, new Tuple(":", ":") }, { FormatVerbosities.Brief, new Tuple("m", "m") }, { FormatVerbosities.Normal, new Tuple("min", "min") }, { FormatVerbosities.Verbose, new Tuple("minute", "minutes") }, }; private static readonly Dictionary> C_SECOND_UNITS = new Dictionary>() { { FormatVerbosities.SuperBrief, new Tuple("", "") }, { FormatVerbosities.Brief, new Tuple("s", "s") }, { FormatVerbosities.Normal, new Tuple("sec", "sec") }, { FormatVerbosities.Verbose, new Tuple("second", "seconds") } }; /// Formats a timespan to a string like "3 min 4 sec". /// /// The timespan. /// The verbosity. /// true to insert a space before each unit. /// true to include those parts of the timespan that are zero, /// starting with hours, e.g. "0h 2m 0s" instead of just "2m". /// true to include, false to exclude the fractions of the second portion. /// The Culture to use for number formatting. Since /// milliseconds are displayed as fractions of seconds, this /// effects the decimal delimiter. By default, the /// DefaultThreadCurrentCulture is used. /// /// The formatted value. public static string Format(TimeSpan timespan, FormatVerbosities verbosity = FormatVerbosities.Normal, bool unitSpacer = true, bool includeZeros = true, bool includeSplitSeconds = true, CultureInfo numberFormatCulture = null) { string result = ""; if (verbosity == FormatVerbosities.SuperBrief) { result = timespan.ToString(); // The system's ToString() will add a fixed number of 0 for the millisecond fraction (e.g. 12:30:05.1200000) // but we want to return only the significant digits if (timespan.Milliseconds != 0) result = result.TrimEnd('0'); } else { string unitInsert = unitSpacer ? " " : ""; result += CreateUnitString(timespan.Days, C_DAY_UNITS[verbosity], unitInsert, createIfZero: false, numberFormatCulture: numberFormatCulture); result += CreateUnitString(timespan.Hours, C_HOUR_UNITS[verbosity], unitInsert, includeZeros, numberFormatCulture: numberFormatCulture); result += CreateUnitString(timespan.Minutes, C_MINUTE_UNITS[verbosity], unitInsert, includeZeros, numberFormatCulture: numberFormatCulture); result += CreateUnitString(timespan.Seconds + (includeSplitSeconds ? timespan.Milliseconds / 1000.0 : 0), C_SECOND_UNITS[verbosity], unitInsert, includeZeros, numberFormatCulture: numberFormatCulture); } return result.Trim(); ; } private static string CreateUnitString(double value, Tuple unit, string unitInsert, bool createIfZero, CultureInfo numberFormatCulture = null) { if (createIfZero || (value != 0)) return value.ToString(numberFormatCulture ?? CultureInfo.DefaultThreadCurrentCulture) + unitInsert + ((Math.Abs(value) == 1) ? unit.Item1 : unit.Item2) + unitInsert; return ""; } } }