如何在.NET中使用自定义格式对TimeSpan对象进行String.Format格式化?


Answers:


246

请注意:此答案适用于.Net 4.0及更高版本。如果要在.Net 3.5或更低版本中格式化TimeSpan,请参阅JohannesH的答案

.Net 4.0中引入了自定义TimeSpan格式字符串。您可以在“ MSDN 自定义时间跨度格式字符串”页面上找到可用格式说明符的完整参考。

这是一个示例时间跨度格式字符串:

string.Format("{0:hh\\:mm\\:ss}", myTimeSpan); //example output 15:36:15

UPDATE),这是使用C#6字符串插值的示例:

$"{myTimeSpan:hh\\:mm\\:ss}"; //example output 15:36:15

您需要使用“ \”对“:”字符进行转义(除非使用逐字字符串,否则必须对自身进行转义)。

此摘录来自“ MSDN 自定义TimeSpan格式字符串”页面,它说明了如何转义“:”和“。”。格式字符串中的字符:

自定义TimeSpan格式说明符不包含占位符分隔符,例如将天与小时,小时与分钟或秒与小数秒分隔的符号。而是,这些符号必须作为字符串文字包含在自定义格式字符串中。例如,“ dd.hh:mm”将句点(。)定义为日期和小时之间的分隔符,将冒号(:)定义为小时和分钟之间的分隔符。


7
@Andrei Rinea:正确,如我第二段“ .Net 4允许您在Timespan中使用自定义格式字符串”所述。
琼斯医生

1
@爱德华,那是不对的。在您的示例中,您转义了前m和前s,因此输入myTimeSpan = new TimeSpan(15, 35, 54);该语句myTimeSpan .ToString("hh\\mm\\ss");将导致15m35s54。我认为这不是您想要的,因为它会在您的工作时间后放一个m,然后在您的分钟后放一个s。
琼斯医生

1
@琼斯医生-谢谢!我的意思是myTimeSpan.ToString(“ h \\ hm \\ ms \\ s”); 或myTimeSpan.ToString(@“ h \ hm \ ms \ s”); 这给出了15h35m54s
爱德华

2
请谨慎使用此解决方案,因为“小时数”部分超过24时,它将无法正常工作
Zoltan Tirinda

1
@QuarK,没有执行此操作的自定义格式说明符,它们都为您提供了不计入工作日的小时数。不过您可以这样做$"{myTimeSpan.TotalHours}:{myTimeSpan:mm\\:ss}"。从用户的角度来看,最好输出天数,但是没人希望从心理上弄清楚200个小时以上的天数。
琼斯医生

91

对于.NET 3.5及更低版本,您可以使用:

string.Format ("{0:00}:{1:00}:{2:00}", 
               (int)myTimeSpan.TotalHours, 
                    myTimeSpan.Minutes, 
                    myTimeSpan.Seconds);

从Jon Skeet 答案中获取的字节代码

对于.NET 4.0及更高版本,请参阅DoctaJonez 答案


是的,谢谢。但我认为DateTime方法更具可定制性,因为它适用于DateTime支持的任何时间格式。例如,这种方法很难用于显示AM / PM。
Hosam Aly

1
当然,TimeSpan表示一个时间段,而不是一天中的某个时间(即使DateTime.Now.TimeOfDay属性会让您不相信)。如果您需要代表一天中的特定时间,建议您继续使用DateTime类。
JohannesH 2009年

7
请记住,如果TimeSpan等于或大于24小时,您将获得错误的格式。
JohannesH

31

一种方法是创建一个DateTime对象并将其用于格式化:

new DateTime(myTimeSpan.Ticks).ToString(myCustomFormat)

// or using String.Format:
String.Format("{0:HHmmss}", new DateTime(myTimeSpan.Ticks))

这就是我所知道的方式。我希望有人可以提出更好的方法。


14
只有在TimeSpan少于一天的情况下,这才真正起作用。那可能不是一个如此可怕的限制,但它使它不再是一个通用的解决方案。
tvanfosson

它返回正确的值吗?将Dim ts作为新TimeSpan(11、22、30、30):将Dim sss作为字符串=新DateTime(ts.Ticks).ToString(“ dd.hh:mm:ss”)
NeverHopeless 2012年

10

简单。TimeSpan.ToString与c,g或G结合使用。在MSDN上的更多信息


1
谢谢您的回答。该方法显然是.NET 4中的新方法,在提出问题时不存在。它还不支持自定义格式。但是,这是对这些问题的答案的宝贵补充。再次感谢。
Hosam Aly



5

我个人喜欢这种方法:

TimeSpan ts = ...;
string.Format("{0:%d}d {0:%h}h {0:%m}m {0:%s}s", ts);

您可以根据需要将其自定义,没有问题:

string.Format("{0:%d}days {0:%h}hours {0:%m}min {0:%s}sec", ts);
string.Format("{0:%d}d {0:%h}h {0:%m}' {0:%s}''", ts);

5

这太棒了:

string.Format("{0:00}:{1:00}:{2:00}",
               (int)myTimeSpan.TotalHours,
               myTimeSpan.Minutes,
               myTimeSpan.Seconds);

1
您需要将myTimeSpan.TotalHours强制转换为int-否则可能会四舍五入。参见JohannesH的答案
10年

3

您还可以选择:

Dim ts As New TimeSpan(35, 21, 59, 59)  '(11, 22, 30, 30)    '
Dim TimeStr1 As String = String.Format("{0:c}", ts)
Dim TimeStr2 As String = New Date(ts.Ticks).ToString("dd.HH:mm:ss")

编辑:

您也可以查看Strings.Format

    Dim ts As New TimeSpan(23, 30, 59)
    Dim str As String = Strings.Format(New DateTime(ts.Ticks), "H:mm:ss")

3
if (timeSpan.TotalDays < 1)
    return timeSpan.ToString(@"hh\:mm\:ss");

return timeSpan.TotalDays < 2
    ? timeSpan.ToString(@"d\ \d\a\y\ hh\:mm\:ss")
    : timeSpan.ToString(@"d\ \d\a\y\s\ hh\:mm\:ss");

所有文字字符都必须转义。


1

我用下面的代码。它很长,但仍然是一个表达式,并且会产生非常友好的输出,因为如果它们的值为零,则不会输出天,小时,分钟或秒。

在示例中,它产生输出:“ 4天1小时3秒”。

TimeSpan sp = new TimeSpan(4,1,0,3);
string.Format("{0}{1}{2}{3}", 
        sp.Days > 0 ? ( sp.Days > 1 ? sp.ToString(@"d\ \d\a\y\s\ "): sp.ToString(@"d\ \d\a\y\ ")):string.Empty,
        sp.Hours > 0 ? (sp.Hours > 1 ? sp.ToString(@"h\ \h\o\u\r\s\ ") : sp.ToString(@"h\ \h\o\u\r\ ")):string.Empty,
        sp.Minutes > 0 ? (sp.Minutes > 1 ? sp.ToString(@"m\ \m\i\n\u\t\e\s\ ") :sp.ToString(@"m\ \m\i\n\u\t\e\ ")):string.Empty,
        sp.Seconds > 0 ? (sp.Seconds > 1 ? sp.ToString(@"s\ \s\e\c\o\n\d\s"): sp.ToString(@"s\ \s\e\c\o\n\d\s")):string.Empty);

现在有一种更好的方法来编写此代码!尝试重构所有常见的操作,您可以使此代码看起来好得多。
Hosam Aly 2014年

@Hosam Aly; 我一直在学习,您是否愿意发布改进的代码?
panpawel '16

String timeComponent(int value, String name) { return value > 0 ? value + " " + name + (value > 1 ? "s" : ""); }调用每个组件(例如timeComponent(sp.Days, "day")),然后使用String.join插入空格。
Hosam Aly

1

我用这种方法。我是比利时人,说荷兰语,所以小时和分钟的复数形式不仅在末尾加上了“ s”,而且几乎与单数不同。

它可能看起来很长,但我认为它可读性强:

 public static string SpanToReadableTime(TimeSpan span)
    {
        string[] values = new string[4];  //4 slots: days, hours, minutes, seconds
        StringBuilder readableTime = new StringBuilder();

        if (span.Days > 0)
        {
            if (span.Days == 1)
                values[0] = span.Days.ToString() + " dag"; //day
            else
                values[0] = span.Days.ToString() + " dagen";  //days

            readableTime.Append(values[0]);
            readableTime.Append(", ");
        }
        else
            values[0] = String.Empty;


        if (span.Hours > 0)
        {
            if (span.Hours == 1)
                values[1] = span.Hours.ToString() + " uur";  //hour
            else
                values[1] = span.Hours.ToString() + " uren";  //hours

            readableTime.Append(values[1]);
            readableTime.Append(", ");

        }
        else
            values[1] = string.Empty;

        if (span.Minutes > 0)
        {
            if (span.Minutes == 1)
                values[2] = span.Minutes.ToString() + " minuut";  //minute
            else
                values[2] = span.Minutes.ToString() + " minuten";  //minutes

            readableTime.Append(values[2]);
            readableTime.Append(", ");
        }
        else
            values[2] = string.Empty;

        if (span.Seconds > 0)
        {
            if (span.Seconds == 1)
                values[3] = span.Seconds.ToString() + " seconde";  //second
            else
                values[3] = span.Seconds.ToString() + " seconden";  //seconds

            readableTime.Append(values[3]);
        }
        else
            values[3] = string.Empty;


        return readableTime.ToString();
    }//end SpanToReadableTime

如果您编写需要翻译的软件,那么这几乎是可行的方法。标准的TimeSpan.ToString()对于普通的最终用户来说太笨拙了,尤其是当跨度超过一天时。
尼尔

1

这是我将自己用于条件格式的方法。我将其张贴在这里,因为我认为这是干净的方法。

$"{time.Days:#0:;;\\}{time.Hours:#0:;;\\}{time.Minutes:00:}{time.Seconds:00}"

输出示例:

00:00 (最低)

1:43:04 (如果我们有时间)

15:03:01 (当小时数超过1位数时)

2:4:22:04 (当我们有日子的时候。)

格式化很容易。time.Days:#0:;;\\之前的格式;;用于当值为正时。负值将被忽略。对于零值,我们必须;;\\将其隐藏在格式化的字符串中。请注意,必须使用转义的反斜杠,否则它将无法正确格式化。


1

这是我的扩展方法

public static string ToFormattedString(this TimeSpan ts)
{
    const string separator = ", ";

    if (ts.TotalMilliseconds < 1) { return "No time"; }

    return string.Join(separator, new string[]
    {
        ts.Days > 0 ? ts.Days + (ts.Days > 1 ? " days" : " day") : null,
        ts.Hours > 0 ? ts.Hours + (ts.Hours > 1 ? " hours" : " hour") : null,
        ts.Minutes > 0 ? ts.Minutes + (ts.Minutes > 1 ? " minutes" : " minute") : null,
        ts.Seconds > 0 ? ts.Seconds + (ts.Seconds > 1 ? " seconds" : " second") : null,
        ts.Milliseconds > 0 ? ts.Milliseconds + (ts.Milliseconds > 1 ? " milliseconds" : " millisecond") : null,
    }.Where(t => t != null));
}

示例调用:

string time = new TimeSpan(3, 14, 15, 0, 65).ToFormattedString();

输出:

3 days, 14 hours, 15 minutes, 65 milliseconds

1

这是VS 2010的痛苦,这是我的解决方法。

 public string DurationString
        {
            get 
            {
                if (this.Duration.TotalHours < 24)
                    return new DateTime(this.Duration.Ticks).ToString("HH:mm");
                else //If duration is more than 24 hours
                {
                    double totalminutes = this.Duration.TotalMinutes;
                    double hours = totalminutes / 60;
                    double minutes = this.Duration.TotalMinutes - (Math.Floor(hours) * 60);
                    string result = string.Format("{0}:{1}", Math.Floor(hours).ToString("00"), Math.Floor(minutes).ToString("00"));
                    return result;
                }
            } 
        }

1

Substring当您只需要Hours:Minutes:Seconds时,该方法可以完美地工作。它是简单,干净的代码,易于理解。

    var yourTimeSpan = DateTime.Now - DateTime.Now.AddMinutes(-2);

    var formatted = yourTimeSpan.ToString().Substring(0,8);// 00:00:00 

    Console.WriteLine(formatted);

0

这是我的版本。它仅显示必要的内容,可以处理复数形式,否定形式,而我试图使其轻量化。

输出范例

0 seconds
1.404 seconds
1 hour, 14.4 seconds
14 hours, 57 minutes, 22.473 seconds
1 day, 14 hours, 57 minutes, 22.475 seconds

public static class TimeSpanExtensions
{
    public static string ToReadableString(this TimeSpan timeSpan)
    {
        int days = (int)(timeSpan.Ticks / TimeSpan.TicksPerDay);
        long subDayTicks = timeSpan.Ticks % TimeSpan.TicksPerDay;

        bool isNegative = false;
        if (timeSpan.Ticks < 0L)
        {
            isNegative = true;
            days = -days;
            subDayTicks = -subDayTicks;
        }

        int hours = (int)((subDayTicks / TimeSpan.TicksPerHour) % 24L);
        int minutes = (int)((subDayTicks / TimeSpan.TicksPerMinute) % 60L);
        int seconds = (int)((subDayTicks / TimeSpan.TicksPerSecond) % 60L);
        int subSecondTicks = (int)(subDayTicks % TimeSpan.TicksPerSecond);
        double fractionalSeconds = (double)subSecondTicks / TimeSpan.TicksPerSecond;

        var parts = new List<string>(4);

        if (days > 0)
            parts.Add(string.Format("{0} day{1}", days, days == 1 ? null : "s"));
        if (hours > 0)
            parts.Add(string.Format("{0} hour{1}", hours, hours == 1 ? null : "s"));
        if (minutes > 0)
            parts.Add(string.Format("{0} minute{1}", minutes, minutes == 1 ? null : "s"));
        if (fractionalSeconds.Equals(0D))
        {
            switch (seconds)
            {
                case 0:
                    // Only write "0 seconds" if we haven't written anything at all.
                    if (parts.Count == 0)
                        parts.Add("0 seconds");
                    break;

                case 1:
                    parts.Add("1 second");
                    break;

                default:
                    parts.Add(seconds + " seconds");
                    break;
            }
        }
        else
        {
            parts.Add(string.Format("{0}{1:.###} seconds", seconds, fractionalSeconds));
        }

        string resultString = string.Join(", ", parts);
        return isNegative ? "(negative) " + resultString : resultString;
    }
}

0

如果您希望持续时间格式类似于youtube,则以秒为单位

int[] duration = { 0, 4, 40, 59, 60, 61, 400, 4000, 40000, 400000 };
foreach (int d in duration)
{
    Console.WriteLine("{0, 6} -> {1, 10}", d, d > 59 ? TimeSpan.FromSeconds(d).ToString().TrimStart("00:".ToCharArray()) : string.Format("0:{0:00}", d));
}

输出:

     0 ->       0:00
     4 ->       0:04
    40 ->       0:40
    59 ->       0:59
    60 ->       1:00
    61 ->       1:01
   400 ->       6:40
  4000 ->    1:06:40
 40000 ->   11:06:40
400000 -> 4.15:06:40

0

我想返回一个字符串,例如“ 1 day 2 hours 3 minutes”,并且还要考虑到天数或分钟数是否为0,然后不显示它们。感谢约翰·拉施(John Rasch)的回答,而我的回答几乎不是

TimeSpan timeLeft = New Timespan(0, 70, 0);
String.Format("{0}{1}{2}{3}{4}{5}",
    Math.Floor(timeLeft.TotalDays) == 0 ? "" : 
    Math.Floor(timeLeft.TotalDays).ToString() + " ",
    Math.Floor(timeLeft.TotalDays) == 0 ? "" : Math.Floor(timeLeft.TotalDays) == 1 ? "day " : "days ",
    timeLeft.Hours == 0 ? "" : timeLeft.Hours.ToString() + " ",
    timeLeft.Hours == 0 ? "" : timeLeft.Hours == 1 ? "hour " : "hours ",
    timeLeft.Minutes == 0 ? "" : timeLeft.Minutes.ToString() + " ",
    timeLeft.Minutes == 0 ? "" : timeLeft.Minutes == 1 ? "minute " : "minutes ");
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.