ฉันจะ String.Format วัตถุ TimeSpan ด้วยรูปแบบที่กำหนดเองใน. NET ได้อย่างไร


คำตอบ:


247

โปรดทราบ: คำตอบนี้มีไว้สำหรับ. Net 4.0 ขึ้นไป หากคุณต้องการจัดรูปแบบ TimeSpan ในสุทธิ 3.5 หรือต่ำกว่าโปรดดูคำตอบของ JohannesH

สตริงรูปแบบที่กำหนดเอง TimeSpan ถูกนำมาใช้ใน. Net 4.0 คุณสามารถค้นหาข้อมูลอ้างอิงทั้งหมดของตัวระบุรูปแบบที่มีอยู่ได้ที่หน้าสตริงรูปแบบการกำหนดรูปแบบ MSDN กำหนดเอง

ต่อไปนี้เป็นสตริงรูปแบบ timespan ตัวอย่าง:

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

( UPDATE ) และนี่คือตัวอย่างการใช้การแก้ไขสตริง C # 6:

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

คุณต้องหลีกเลี่ยงอักขระ ":" ด้วย "\" (ซึ่งตัวเองต้องถูกยกเว้นยกเว้นว่าคุณกำลังใช้สตริง verbatim)

ข้อความที่ตัดตอนมาจากหน้าสตริงการจัดรูปแบบเวลาที่กำหนดเองของ MSDN อธิบายเกี่ยวกับการหลีกเลี่ยง ":" และ " อักขระในสตริงรูปแบบ:

ตัวระบุรูปแบบ TimeSpan ที่กำหนดเองไม่รวมสัญลักษณ์ตัวคั่นตำแหน่งแทนเช่นสัญลักษณ์ที่แยกวันจากชั่วโมงชั่วโมงจากนาทีหรือวินาทีจากเศษส่วนวินาที สัญลักษณ์เหล่านี้ต้องรวมอยู่ในสตริงรูปแบบที่กำหนดเองเป็นตัวอักษรสตริง ตัวอย่างเช่น "dd.hh: mm" กำหนดจุด (.) เป็นตัวคั่นระหว่างวันและชั่วโมงและเครื่องหมายโคลอน (:) เป็นตัวคั่นระหว่างชั่วโมงและนาที


7
@Andrei Rinea: ถูกต้องตามที่ระบุไว้ในตอนต้นของย่อหน้าที่สอง ". Net 4 ช่วยให้คุณสามารถใช้สตริงรูปแบบที่กำหนดเองกับ Timespan"
หมอโจนส์

1
@Edward นั่นไม่ถูกต้องนัก ในตัวอย่างของคุณกำลังหลบหนีเมตรครั้งแรกและเป็นครั้งแรกเพื่อให้มีการป้อนข้อมูลของmyTimeSpan = new TimeSpan(15, 35, 54);คำสั่งจะมีผลในmyTimeSpan .ToString("hh\\mm\\ss"); 15m35s54ฉันไม่คิดว่านั่นคือสิ่งที่คุณตั้งใจไว้เพราะจะวาง m หลังจากชั่วโมงของคุณและหลังจากนาทีของคุณ
หมอโจนส์

1
@Doctor Jones - ขอบคุณ! ฉันหมายถึง myTimeSpan.ToString ("h \\ hm \\ ms \\ s"); หรือ myTimeSpan.ToString (@ "h \ hm \ ms \ s"); ซึ่งให้ 15h35m54s
Edward

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.Now.TimeOfDay คุณจะเชื่อเป็นอย่างอื่น) หากคุณต้องการแสดงเวลาเฉพาะของวันฉันขอแนะนำให้คุณใช้คลาส DateTime ต่อไป
JohannesH

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

มันคืนค่าที่ถูกต้องหรือไม่? ติ่มซำเป็น TimeSpan ใหม่ (11, 22, 30, 30): Dim sss As String = ใหม่ DateTime (ts.Ticks) .ToString ("dd.hh: mm: ss")
NeverHopeless เมื่อ

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 ทั้งหมดไปที่ int - มิฉะนั้นอาจทำให้เกิดการปัดเศษขึ้น ดูคำตอบของ JohannesH
codeulike

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

@Hosam Aly; ฉันเรียนรู้อยู่ตลอดเวลาคุณสนใจที่จะโพสต์โค้ดที่ปรับปรุงแล้วของคุณหรือไม่?
panpawel

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 มาตรฐาน () เป็นเพียง clunky เกินไปสำหรับผู้ใช้ทั่วไปที่จะเข้าใจโดยเฉพาะอย่างยิ่งเมื่อขยายถ้าเกินวัน
Neil

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วิธีการทำงานอย่างสมบูรณ์แบบเมื่อคุณต้องการสิ่งที่ชั่วโมง: นาที: วินาที มันเรียบง่ายสะอาดตาและเข้าใจง่าย

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

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

    Console.WriteLine(formatted);

0

นี่คือรุ่นของฉัน มันแสดงให้เห็นเท่าที่จำเป็นเท่านั้นจัดการ pluralization, negatives และฉันพยายามทำให้มันเบา

ตัวอย่างผลลัพธ์

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 วัน 2 ชั่วโมง 3 นาที" และควรคำนึงถึงด้วยเช่นถ้าจำนวนวันหรือนาทีเป็น 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 ");
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.