Làm cách nào tôi có thể String.Format một đối tượng TimeSpan với định dạng tùy chỉnh trong .NET?


184

Cách định dạng TimeSpancác đối tượng được đề xuất thành một chuỗi với định dạng tùy chỉnh là gì?

Câu trả lời:


246

Xin lưu ý: câu trả lời này dành cho .Net 4.0 trở lên. Nếu bạn muốn định dạng TimeSpan bằng .Net 3.5 trở xuống, vui lòng xem câu trả lời của JohannesH .

Chuỗi định dạng TimeSpan tùy chỉnh đã được giới thiệu trong .Net 4.0. Bạn có thể tìm thấy một tài liệu tham khảo đầy đủ về các chỉ định định dạng có sẵn tại trang Chuỗi định dạng thời gian tùy chỉnh MSDN .

Dưới đây là một chuỗi định dạng thời gian ví dụ:

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

( CẬP NHẬT ) và đây là một ví dụ sử dụng phép nội suy chuỗi C # 6:

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

Bạn cần thoát ký tự ":" bằng "\" (chính nó phải được thoát trừ khi bạn đang sử dụng chuỗi nguyên văn).

Đoạn trích này từ trang Chuỗi định dạng thời gian tùy chỉnh MSDN giải thích về việc thoát ":" và "." các ký tự trong một chuỗi định dạng:

Các chỉ định định dạng TimeSpan tùy chỉnh không bao gồm các ký hiệu phân tách giữ chỗ, chẳng hạn như các ký hiệu phân tách ngày từ giờ, giờ từ phút hoặc giây từ giây phân đoạn. Thay vào đó, các ký hiệu này phải được bao gồm trong chuỗi định dạng tùy chỉnh dưới dạng chuỗi ký tự. Ví dụ: "dd.hh: mm" định nghĩa một khoảng thời gian (.) Là dấu phân cách giữa ngày và giờ và dấu hai chấm (:) là dấu phân cách giữa giờ và phút.


7
@Andrei Rinea: Đúng, như đã nêu ở đầu đoạn thứ hai của tôi ".Net 4 cho phép bạn sử dụng các chuỗi định dạng tùy chỉnh với Timespan".
Bác sĩ Jones

1
@Edward, điều đó không hoàn toàn đúng. Trong ví dụ của bạn, bạn đang thoát khỏi m đầu tiên và s đầu tiên, do đó, với một đầu vào của myTimeSpan = new TimeSpan(15, 35, 54);câu lệnh myTimeSpan .ToString("hh\\mm\\ss");sẽ dẫn đến 15m35s54. Tôi không nghĩ đó là những gì bạn dự định vì nó sẽ đặt một m sau giờ của bạn và một giây sau phút của bạn.
Bác sĩ Jones

1
@Doctor Jones - Cảm ơn bạn! Ý tôi là myTimeSpan.ToString ("h \\ hm \\ ms \\ s"); hoặc myTimeSpan.ToString (@ "h \ hm \ ms \ s"); trong đó cho 15h35m54s
Edward

2
chỉ cần cẩn thận với giải pháp này, vì nó sẽ không hoạt động chính xác khi phần Giờ nhiều hơn 24
Zoltan Tirinda 17/03/2016

1
@QuarK, không có công cụ định dạng tùy chỉnh nào thực hiện điều đó, tất cả đều cung cấp cho bạn số giờ không được tính là một phần của ngày. Bạn có thể làm điều này thay vì mặc dù $"{myTimeSpan.TotalHours}:{myTimeSpan:mm\\:ss}". Từ quan điểm của người dùng, có thể tốt hơn là xuất ra các ngày mặc dù, không ai muốn tìm hiểu về mặt tinh thần có bao nhiêu ngày trong hơn 200 giờ.
Bác sĩ Jones

91

Đối với .NET 3.5 trở xuống, bạn có thể sử dụng:

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

Mã được lấy từ câu trả lời của Jon Skeet trên byte

Đối với .NET 4.0 trở lên, hãy xem câu trả lời của DoctaJonez .


Vâng, cảm ơn. Nhưng tôi nghĩ rằng cách tiếp cận DateTime có thể tùy chỉnh nhiều hơn, vì nó sẽ hoạt động cho bất kỳ định dạng thời gian nào được DateTime hỗ trợ. Cách tiếp cận này khó sử dụng để hiển thị AM / PM chẳng hạn.
Hosam Aly

1
Chắc chắn, TimeSpan có nghĩa là đại diện cho một khoảng thời gian, không phải là thời gian trong ngày (Mặc dù thuộc tính DateTime.Now.TimeOfDay sẽ khiến bạn tin tưởng khác). Nếu bạn cần đại diện cho một thời gian cụ thể trong ngày, tôi khuyên bạn nên tiếp tục sử dụng lớp DateTime.
JulianH

7
Chỉ cần nhớ rằng nếu TimeSpan bằng hoặc hơn 24 giờ bạn sẽ nhận được định dạng không chính xác.
JulianH

31

Một cách là tạo một DateTimeđối tượng và sử dụng nó để định dạng:

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

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

Đây là cách tôi biết. Tôi hy vọng ai đó có thể đề xuất một cách tốt hơn.


14
Điều này thực sự chỉ hoạt động nếu TimeSpan chưa đầy một ngày. Đó có thể không phải là một hạn chế khủng khiếp như vậy, nhưng nó giữ cho nó không phải là một giải pháp chung.
tvanfosson

Liệu nó trả về giá trị chính xác? Ts Dim As New TimeSpan (11, 22, 30, 30): Dim sss As String = New DateTime (ts.Ticks) ToString ( "dd.hh: mm: ss")
NeverHopeless

10

Đơn giản. Sử dụng TimeSpan.ToStringvới c, g hoặc G. Thêm thông tin tại MSDN


1
Cảm ơn bạn vì câu trả lời. Phương pháp này rõ ràng là mới trong .NET 4 và không tồn tại khi câu hỏi được hỏi. Nó cũng không hỗ trợ các định dạng tùy chỉnh. Tuy nhiên, đó là một bổ sung có giá trị cho câu trả lời cho câu hỏi này. Cảm ơn một lần nữa.
Hosam Aly

8

Tôi sẽ đi với

myTimeSpan.ToString("hh\\:mm\\:ss");

Đơn giản và sạch sẽ! một thay thế là @ "hh \: mm \: ss"
Xilmiki


5

Cá nhân, tôi thích cách tiếp cận này:

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

Bạn có thể thực hiện điều này tùy chỉnh tùy thích mà không gặp vấn đề gì:

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

Đây là một trong những tuyệt vời:

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

1
Bạn cần truyền myTimeSpan.TotalHours thành int - nếu không nó có thể bị làm tròn. Xem câu trả lời của
JulianH

3

Bạn cũng có thể đi với:

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")

BIÊN TẬP:

Bạn cũng có thể nhìn vào String.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");

Tất cả các nhân vật theo nghĩa đen phải được trốn thoát.


1

Tôi đã sử dụng mã dưới đây. Nó dài, nhưng vẫn là một biểu thức và tạo ra đầu ra rất thân thiện, vì nó không xuất ra ngày, giờ, phút hoặc giây nếu chúng có giá trị bằng 0.

Trong mẫu, nó tạo ra đầu ra: "4 ngày 1 giờ 3 giây".

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);

Bây giờ có một cách tốt hơn để viết này! Cố gắng cấu trúc lại tất cả các hoạt động phổ biến và bạn có thể làm cho mã này trông tốt hơn nhiều.
Hosam Aly

@Hosam Aly; Tôi đang học mọi lúc, bạn có quan tâm để đăng mã cải tiến của mình không?
panpawel

String timeComponent(int value, String name) { return value > 0 ? value + " " + name + (value > 1 ? "s" : ""); }Gọi đó cho từng thành phần (ví dụ timeComponent(sp.Days, "day")), sau đó sử dụng String.joinđể chèn khoảng trắng.
Hosam Aly

1

Tôi sử dụng phương pháp này. Tôi là người Bỉ và nói tiếng Hà Lan nên số nhiều giờ và phút không chỉ thêm 's' vào cuối mà gần như là một từ khác với số ít.

Nó có vẻ dài nhưng tôi nghĩ nó rất dễ đọc:

 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

Nếu bạn viết phần mềm cần dịch, thì đây là cách tốt nhất để đi. TimeSpan.ToString () tiêu chuẩn quá khó hiểu đối với người dùng cuối bình thường, đặc biệt là khi khoảng thời gian nếu hơn một ngày.
Neil

1

Đây là cách tiếp cận tôi sử dụng bản thân với định dạng có điều kiện. và tôi đăng nó ở đây vì tôi nghĩ đây là cách sạch sẽ.

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

ví dụ về đầu ra:

00:00 (tối thiểu)

1:43:04 (khi chúng ta có giờ)

15:03:01 (khi số giờ nhiều hơn 1 chữ số)

2:4:22:04 (khi chúng ta có ngày.)

Các định dạng là dễ dàng. time.Days:#0:;;\\định dạng trước ;;là khi giá trị dương. giá trị âm được bỏ qua. và đối với các giá trị 0, chúng ta có ;;\\để ẩn nó trong chuỗi được định dạng. lưu ý rằng dấu gạch chéo ngược đã thoát là cần thiết nếu không nó sẽ không định dạng chính xác.


1

Đây là phương pháp mở rộng của tôi :

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));
}

Cuộc gọi ví dụ:

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

Đầu ra:

3 days, 14 hours, 15 minutes, 65 milliseconds

1

Đây là một nỗi đau trong VS 2010, đây là giải pháp khắc phục của tôi.

 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

Các Substringphương pháp hoạt động hoàn hảo khi bạn chỉ muốn Giờ: Phút: Giây. Đó là mã đơn giản, sạch sẽ và dễ hiểu.

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

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

    Console.WriteLine(formatted);

0

Đây là phiên bản của tôi. Nó chỉ hiển thị càng nhiều càng cần thiết, xử lý số nhiều, phủ định và tôi đã cố gắng làm cho nó nhẹ.

Ví dụ đầu ra

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

Nếu bạn muốn định dạng thời lượng tương tự như youtube, hãy cho số giây

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));
}

Đầu ra:

     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

Tôi muốn trả về một chuỗi như "1 ngày 2 giờ 3 phút" và cũng tính đến nếu ví dụ ngày hoặc số lần rút là 0 và sau đó không hiển thị chúng. cảm ơn John Rasch vì câu trả lời của anh ấy mà tôi chỉ là một phần mở rộng của

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 ");
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.