格式化TimeSpan大于24小时
假设我像这样将时间转换成TimeSpan对象:
Dim sec = 1254234568 Dim t As TimeSpan = TimeSpan.FromSeconds(sec)
如何将TimeSpan对象格式化为如下格式:
>105hr 56mn 47sec
有一个内置函数还是我需要写一个自定义函数?
那么,最简单的做法就是自己设置格式,例如
return string.Format("{0}hr {1}mn {2}sec", (int) span.TotalHours, span.Minutes, span.Seconds);
在VB中:
Public Shared Function FormatTimeSpan(span As TimeSpan) As String Return String.Format("{0}hr {1}mn {2}sec", _ CInt(Math.Truncate(span.TotalHours)), _ span.Minutes, _ span.Seconds) End Function
我不知道.NET 4中的任何TimeSpan
格式是否会使这个更简单。
微软目前没有一个简单的格式string快捷方式。 最简单的选项已经被分享了。
string.Format("{0}hr {1:mm}mn {1:ss}sec", (int)t.TotalHours, t);
但是,一个非常彻底的选项是为TimeSpan
实现您自己的ICustomFormatter
。 我不会推荐它,除非你经常使用它,从长远来看这会节省你的时间。 但是,有时候你会写一个自己编写ICustomFormatter
的类,所以我写了这个例子。
/// <summary> /// Custom string formatter for TimeSpan that allows easy retrieval of Total segments. /// </summary> /// <example> /// TimeSpan myTimeSpan = new TimeSpan(27, 13, 5); /// string.Format("{0:th,###}h {0:mm}m {0:ss}s", myTimeSpan) -> "27h 13m 05s" /// string.Format("{0:TH}", myTimeSpan) -> "27.2180555555556" /// /// NOTE: myTimeSpan.ToString("TH") does not work. See Remarks. /// </example> /// <remarks> /// Due to a quirk of .NET Framework (up through version 4.5.1), /// <code>TimeSpan.ToString(format, new TimeSpanFormatter())</code> will not work; it will always call /// TimeSpanFormat.FormatCustomized() which takes a DateTimeFormatInfo rather than an /// IFormatProvider/ICustomFormatter. DateTimeFormatInfo, unfortunately, is a sealed class. /// </remarks> public class TimeSpanFormatter : IFormatProvider, ICustomFormatter { /// <summary> /// Used to create a wrapper format string with the specified format. /// </summary> private const string DefaultFormat = "{{0:{0}}}"; /// <remarks> /// IFormatProvider.GetFormat implementation. /// </remarks> public object GetFormat(Type formatType) { // Determine whether custom formatting object is requested. if (formatType == typeof(ICustomFormatter)) { return this; } return null; } /// <summary> /// Determines whether the specified format is looking for a total, and formats it accordingly. /// If not, returns the default format for the given <para>format</para> of a TimeSpan. /// </summary> /// <returns> /// The formatted string for the given TimeSpan. /// </returns> /// <remarks> /// ICustomFormatter.Format implementation. /// </remarks> public string Format(string format, object arg, IFormatProvider formatProvider) { // only apply our format if there is a format and if the argument is a TimeSpan if (string.IsNullOrWhiteSpace(format) || formatProvider != this || // this should always be true, but just in case... !(arg is TimeSpan) || arg == null) { // return the default for whatever our format and argument are return GetDefault(format, arg); } TimeSpan span = (TimeSpan)arg; string[] formatSegments = format.Split(new char[] { ',' }, 2); string tsFormat = formatSegments[0]; // Get inner formatting which will be applied to the int or double value of the requested total. // Default number format is just to return the number plainly. string numberFormat = "{0}"; if (formatSegments.Length > 1) { numberFormat = string.Format(DefaultFormat, formatSegments[1]); } // We only handle two-character formats, and only when those characters' capitalization match // (eg 'TH' and 'th', but not 'tH'). Feel free to change this to suit your needs. if (tsFormat.Length != 2 || char.IsUpper(tsFormat[0]) != char.IsUpper(tsFormat[1])) { return GetDefault(format, arg); } // get the specified time segment from the TimeSpan as a double double valAsDouble; switch (char.ToLower(tsFormat[1])) { case 'd': valAsDouble = span.TotalDays; break; case 'h': valAsDouble = span.TotalHours; break; case 'm': valAsDouble = span.TotalMinutes; break; case 's': valAsDouble = span.TotalSeconds; break; case 'f': valAsDouble = span.TotalMilliseconds; break; default: return GetDefault(format, arg); } // figure out if we want a double or an integer switch (tsFormat[0]) { case 'T': // format Total as double return string.Format(numberFormat, valAsDouble); case 't': // format Total as int (rounded down) return string.Format(numberFormat, (int)valAsDouble); default: return GetDefault(format, arg); } } /// <summary> /// Returns the formatted value when we don't know what to do with their specified format. /// </summary> private string GetDefault(string format, object arg) { return string.Format(string.Format(DefaultFormat, format), arg); } }
请注意,正如在代码中所述, TimeSpan.ToString(format, myTimeSpanFormatter)
由于.NET Framework的怪异而不起作用,因此您将始终必须使用string.Format(format,myTimeSpanFormatter)来使用此类。 请参阅如何为DateTime创build和使用自定义的IFormatProvider? 。
编辑 :如果你真的,我的意思是真的 ,希望这与TimeSpan.ToString(string, TimeSpanFormatter)
,你可以添加到以上的TimeSpanFormatter
类:
/// <remarks> /// Update this as needed. /// </remarks> internal static string[] GetRecognizedFormats() { return new string[] { "td", "th", "tm", "ts", "tf", "TD", "TH", "TM", "TS", "TF" }; }
并在相同的命名空间中的某个地方添加以下类:
public static class TimeSpanFormatterExtensions { private static readonly string CustomFormatsRegex = string.Format(@"([^\\])?({0})(?:,{{([^(\\}})]+)}})?", string.Join("|", TimeSpanFormatter.GetRecognizedFormats())); public static string ToString(this TimeSpan timeSpan, string format, ICustomFormatter formatter) { if (formatter == null) { throw new ArgumentNullException(); } TimeSpanFormatter tsFormatter = (TimeSpanFormatter)formatter; format = Regex.Replace(format, CustomFormatsRegex, new MatchEvaluator(m => MatchReplacer(m, timeSpan, tsFormatter))); return timeSpan.ToString(format); } private static string MatchReplacer(Match m, TimeSpan timeSpan, TimeSpanFormatter formatter) { // the matched non-'\' char before the stuff we actually care about string firstChar = m.Groups[1].Success ? m.Groups[1].Value : string.Empty; string input; if (m.Groups[3].Success) { // has additional formatting input = string.Format("{0},{1}", m.Groups[2].Value, m.Groups[3].Value); } else { input = m.Groups[2].Value; } string replacement = formatter.Format(input, timeSpan, formatter); if (string.IsNullOrEmpty(replacement)) { return firstChar; } return string.Format("{0}\\{1}", firstChar, string.Join("\\", replacement.ToCharArray())); } }
在此之后,您可以使用
ICustomFormatter formatter = new TimeSpanFormatter(); string myStr = myTimeSpan.ToString(@"TH,{000.00}h\:tm\m\:ss\s", formatter);
在那里{000.00}
是你想要的TotalHours int或double被格式化。 请注意括号括起来,不应该在string.Format()的情况下。 另请注意, formatter
必须声明(或ICustomFormatter
)为ICustomFormatter
而不是TimeSpanFormatter
。
过多? 是。 真棒? 唔….
string.Format("{0}hr {1}mn {2}sec", (int) t.TotalHours, t.Minutes, t.Seconds);
您可能需要计算小时数。 TimeSpan.ToString中的小时数范围仅为0-23。
最糟糕的是你需要做原始string格式化一个Jon Skeet。
你可以试试这个:
TimeSpan ts = TimeSpan.FromSeconds(1254234568); Console.WriteLine($"{((int)ts.TotalHours).ToString("d2")}hr {ts.Minutes.ToString("d2")}mm {ts.Seconds.ToString("d2")}sec");
试试这个function:
Public Shared Function GetTimeSpanString(ByVal ts As TimeSpan) As String Dim output As New StringBuilder() Dim needsComma As Boolean = False If ts = Nothing Then Return "00:00:00" End If If ts.TotalHours >= 1 Then output.AppendFormat("{0} hr", Math.Truncate(ts.TotalHours)) If ts.TotalHours > 1 Then output.Append("s") End If needsComma = True End If If ts.Minutes > 0 Then If needsComma Then output.Append(", ") End If output.AppendFormat("{0} m", ts.Minutes) 'If ts.Minutes > 1 Then ' output.Append("s") 'End If needsComma = True End If Return output.ToString() End Function
将Timespan转换为小时和分钟
你不妨考虑使用野田时间的Duration
types。
例如:
Duration d = Duration.FromSeconds(sec);
要么
Duration d = Duration.FromTimeSpan(ts);
你可以简单地把它格式化为一个string,就像这样:
string result = d.ToString("H'hr' m'mn' s'sec'", CultureInfo.InvariantCulture);
或者,您也可以使用基于模式的API :
DurationPattern p = DurationPattern.CreateWithInvariantCulture("H'hr' m'mn' s'sec'"); string result = p.Format(d);
模式API的优点是您只需要创build一次模式。 如果您有很多parsing或格式化的值,可能会有显着的性能优势。
我的解决scheme是:
string text = Math.Floor(timeUsed.TotalHours) + "h " + ((int)timeUsed.TotalMinutes) % 60 + "min";
MS Excel的其他格式与.NET不同。
检查此链接http://www.paragon-inc.com/resources/blogs-posts/easy_excel_interaction_pt8
我创build了一个简单的函数,将DateTime中的TimeSpan转换为MS Excel格式
public static DateTime MyApproach(TimeSpan time) { return new DateTime(1900, 1, 1).Add(time).AddDays(-2); }
你需要像这样格式化单元格:
col.Style.Numberformat.Format = "[H]:mm:ss";