.NETでカスタム形式でTimeSpanオブジェクトをString.Formatするにはどうすればよいですか?


回答:


247

注意:この回答は.Net 4.0以降を対象としています。.Net 3.5以下でTimeSpanをフォーマットする場合は、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

「:」文字を「\」でエスケープする必要があります(逐語的文字列を使用している場合を除き、文字自体はエスケープする必要があります)。

この「MSDN カスタムTimeSpanフォーマット文字列」ページからの抜粋では、「:」と「」のエスケープについて説明しています。フォーマット文字列の文字:

カスタムTimeSpan形式指定子には、日を時間から、時間を分から、または秒を小数秒から区切る記号などのプレースホルダー区切り記号は含まれません。代わりに、これらの記号は文字列リテラルとしてカスタムフォーマット文字列に含める必要があります。たとえば、 "dd.hh:mm"は、ピリオド(。)を日と時間の間の区切り文字として定義し、コロン(:)を時間と分の間の区切り文字として定義します。


7
@Andrei Rinea:2番目の段落の冒頭で述べたように、「。Net 4ではTimespanでカスタム形式の文字列を使用できます」。
ジョーンズ博士

1
@エドワード、それはまったく正しくない。あなたの例では、最初のmと最初のsをエスケープしているのでmyTimeSpan = new TimeSpan(15, 35, 54);、ステートメントの入力でmyTimeSpan .ToString("hh\\mm\\ss");結果はになり15m35s54ます。それはあなたの意図したものではないと思います。なぜなら、それはあなたの時間の後にmを置き、あなたの分の後にsを置くからです。
ジョーンズ博士

1
@Doctor Jones-ありがとう!つまり、myTimeSpan.ToString( "h \\ hm \\ ms \\ s"); またはmyTimeSpan.ToString(@ "h \ hm \ ms \ s"); 15h35m54s
Edward

2
営業時間一部が24以上であるとき、それは正常に動作しませんので、ちょうど、このソリューションには注意してください
ゾルタン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);

ジョンスキートの回答からバイト単位で取得したコード

.NET 4.0以降については、DoctaJonezの回答を参照してください。


はい、ありがとうございます。しかし、DateTimeでサポートされている任意の時刻形式で機能するため、DateTimeアプローチはよりカスタマイズ可能だと思います。このアプローチは、たとえばAM / PMの表示に使用するのは困難です。
Hosam Aly、

1
確かに、TimeSpanは、時刻ではなく期間を表すことを目的としています(DateTime.Now.TimeOfDayプロパティがそうでないと信じ込ませても)。特定の時刻を表す必要がある場合は、DateTimeクラスを引き続き使用することをお勧めします。
JohannesH

7
TimeSpanが24時間以上の場合は、誤ったフォーマットになることに注意してください。
JohannesH

31

1つの方法は、DateTimeオブジェクトを作成し、それをフォーマットに使用することです。

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

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

これは私が知っている方法です。誰かがもっと良い方法を提案してくれることを願っています。


14
これは、TimeSpanが1日未満の場合にのみ機能します。それはそれほどひどい制限ではないかもしれませんが、それが一般的な解決策になるのを防ぎます。
tvanfosson 2009

正しい値を返しますか?Dim ts As New TimeSpan(11、22、30、30):Dim sss As String = New DateTime(ts.Ticks).ToString( "dd.hh:mm:ss")
NeverHopeless

10

シンプル。TimeSpan.ToStringc、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の回答を参照
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

以下のコードを使用しました。長いですが、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; 私はいつも学んでいますが、改善されたコードを投稿してもよろしいですか?
パンパヴェル2016

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日2時間3分」などの文字列を返し、たとえば日数または分数が0で、それらを表示しない場合も考慮に入れたいと思いました。ジョンラッシュの答えをありがとう

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.