System.TimeSpan 構造体

この記事では、この API のリファレンス ドキュメントに補足的な解説を提供します。

TimeSpan オブジェクトは、正または負の日数、時間、分、秒、および秒の分数として測定される時間間隔 (時間または経過時間) を表します。 TimeSpan構造体は、時刻が特定の日付に関連付けられていない場合にのみ、時刻を表すためにも使用できます。 それ以外の場合は、代わりに DateTime または DateTimeOffset 構造体を使用する必要があります。 ( TimeSpan 構造体を使用して時刻を反映する方法の詳細については、「 DateTime、DateTimeOffset、TimeSpan、TimeZoneInfo の選択」を参照してください)。

TimeSpan値は時間間隔を表し、特定の日数、時間、分、秒、ミリ秒として表すことができます。 特定の始点または終点を参照せずに一般的な間隔を表すので、年と月の観点から表すことはできません。どちらも日数が可変です。 特定のタイム ゾーンを参照しない日付と時刻を表す DateTime 値や、特定の時刻を表す DateTimeOffset 値とは異なります。

TimeSpan構造体が期間の測定に使用する最大の時間単位は 1 日です。 時間間隔は、月や年など、より大きな時間単位の日数が異なるため、一貫性のために日数で測定されます。

TimeSpan オブジェクトの値は、表される時間間隔と等しいティック数です。 ティックは 100 ナノ秒、つまり 1000 万分の 1 秒に相当します。 TimeSpan オブジェクトの値は、TimeSpan.MinValueからTimeSpan.MaxValueまでの範囲で指定できます。

TimeSpan 値をインスタンス化する

TimeSpan値は、さまざまな方法でインスタンス化できます。

  • 暗黙的なパラメーターなしのコンストラクターを呼び出すこと。 これにより、次の例に示すように、値が TimeSpan.Zeroオブジェクトが作成されます。

    TimeSpan interval = new TimeSpan();
    Console.WriteLine(interval.Equals(TimeSpan.Zero));    // Displays "True".
    
    let interval = TimeSpan()
    printfn $"{interval.Equals TimeSpan.Zero}"    // Displays "True".
    
    Dim interval As New TimeSpan()
    Console.WriteLine(interval.Equals(TimeSpan.Zero))     ' Displays "True".
    
  • 明示的なコンストラクターのいずれかを呼び出すこと。 次の例では、指定した時間、分、秒の数に TimeSpan 値を初期化します。

    TimeSpan interval = new TimeSpan(2, 14, 18);
    Console.WriteLine(interval.ToString());              
    
    // Displays "02:14:18".
    
    let interval = TimeSpan(2, 14, 18)
    printfn $"{interval}"              
    
    // Displays "02:14:18".
    
    Dim interval As New TimeSpan(2, 14, 18)
    Console.WriteLine(interval.ToString())                ' Displays "02:14:18".
    
  • メソッドを呼び出すか、 TimeSpan 値を返す操作を実行します。 たとえば、次の例に示すように、2 つの日付と時刻の値の間隔を表す TimeSpan 値をインスタンス化できます。

    DateTime departure = new DateTime(2010, 6, 12, 18, 32, 0);
    DateTime arrival = new DateTime(2010, 6, 13, 22, 47, 0);
    TimeSpan travelTime = arrival - departure;  
    Console.WriteLine($"{arrival} - {departure} = {travelTime}");      
    
    // The example displays the following output:
    //       6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00
    
    let departure = DateTime(2010, 6, 12, 18, 32, 0)
    let arrival = DateTime(2010, 6, 13, 22, 47, 0)
    let travelTime = arrival - departure  
    printfn $"{arrival} - {departure} = {travelTime}"
    
    // The example displays the following output:
    //       6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00
    
    Dim departure As DateTime = #06/12/2010 6:32PM#
    Dim arrival As DateTime = #06/13/2010 10:47PM#
    Dim travelTime As TimeSpan = arrival - departure
    Console.WriteLine("{0} - {1} = {2}", arrival, departure, travelTime)
    ' The example displays the following output:
    '       6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00
    

    次の例に示すように、この方法で TimeSpan オブジェクトをゼロタイム値に初期化することもできます。

    Random rnd = new Random();
    
    TimeSpan timeSpent = TimeSpan.Zero;
    
    timeSpent += GetTimeBeforeLunch();
    timeSpent += GetTimeAfterLunch();
    
    Console.WriteLine($"Total time: {timeSpent}");
    
    TimeSpan GetTimeBeforeLunch()
    {
        return new TimeSpan(rnd.Next(3, 6), 0, 0);
    }
    
    TimeSpan GetTimeAfterLunch()
    {
        return new TimeSpan(rnd.Next(3, 6), 0, 0);
    }
    
    // The example displays output like the following:
    //        Total time: 08:00:00
    
    open System
    
    let rnd = Random()
    
    let getTimeBeforeLunch () =
        TimeSpan(rnd.Next(3, 6), 0, 0)
    
    let getTimeAfterLunch() =
        TimeSpan(rnd.Next(3, 6), 0, 0)
    
    do
        let timeSpent = TimeSpan.Zero
    
        let timeSpent = timeSpent + getTimeBeforeLunch ()
        let timeSpent = timeSpent + getTimeAfterLunch ()
    
        printfn $"Total time: {timeSpent}"
    
    
    // The example displays output like the following:
    //        Total time: 08:00:00
    
    Module Example
       Dim rnd As New Random()
       
       Public Sub Main()
          Dim timeSpent As TimeSpan = TimeSpan.Zero
    
          timeSpent += GetTimeBeforeLunch()
          timeSpent += GetTimeAfterLunch()
    
          Console.WriteLine("Total time: {0}", timeSpent)
       End Sub
       
       Private Function GetTimeBeforeLunch() As TimeSpan
          Return New TimeSpan(rnd.Next(3, 6), 0, 0)
       End Function
       
       Private Function GetTimeAfterLunch() As TimeSpan
          Return New TimeSpan(rnd.Next(3, 6), 0, 0)
       End Function
    End Module
    ' The example displays output like the following:
    '       Total time: 08:00:00
    

    TimeSpan 値は、 DateTimeDateTimeOffset、および TimeSpan 構造体の算術演算子とメソッドによって返されます。

  • TimeSpan値の文字列形式を解析する。 ParseメソッドとTryParse メソッドを使用して、時間間隔を含む文字列をTimeSpan値に変換できます。 次の例では、 Parse メソッドを使用して、文字列の配列を TimeSpan 値に変換します。

    string[] values = { "12", "31.", "5.8:32:16", "12:12:15.95", ".12"};
    foreach (string value in values)
    {
       try {
          TimeSpan ts = TimeSpan.Parse(value);
          Console.WriteLine($"'{value}' --> {ts}");
       }
       catch (FormatException) {
          Console.WriteLine($"Unable to parse '{value}'");
       }
       catch (OverflowException) {
          Console.WriteLine($"'{value}' is outside the range of a TimeSpan.");
       }   
    }
    
    // The example displays the following output:
    //       '12' --> 12.00:00:00
    //       Unable to parse '31.'
    //       '5.8:32:16' --> 5.08:32:16
    //       '12:12:15.95' --> 12:12:15.9500000
    //       Unable to parse '.12'
    
    let values = [| "12"; "31."; "5.8:32:16"; "12:12:15.95"; ".12" |]
    for value in values do
        try
            let ts = TimeSpan.Parse value
            printfn $"'{value}' --> {ts}"
        with 
        | :? FormatException ->
            printfn $"Unable to parse '{value}'"
        | :? OverflowException ->
            printfn $"'{value}' is outside the range of a TimeSpan."
    
    // The example displays the following output:
    //       '12' --> 12.00:00:00
    //       Unable to parse '31.'
    //       '5.8:32:16' --> 5.08:32:16
    //       '12:12:15.95' --> 12:12:15.9500000
    //       Unable to parse '.12'
    
    Dim values() As String = {"12", "31.", "5.8:32:16", "12:12:15.95", ".12"}
    For Each value As String In values
        Try
            Dim ts As TimeSpan = TimeSpan.Parse(value)
            Console.WriteLine("'{0}' --> {1}", value, ts)
        Catch e As FormatException
            Console.WriteLine("Unable to parse '{0}'", value)
        Catch e As OverflowException
            Console.WriteLine("'{0}' is outside the range of a TimeSpan.", value)
        End Try
    Next
    ' The example displays the following output:
    '       '12' --> 12.00:00:00
    '       Unable to parse '31.'
    '       '5.8:32:16' --> 5.08:32:16
    '       '12:12:15.95' --> 12:12:15.9500000
    '       Unable to parse '.12'
    

    さらに、TimeSpanメソッドまたはParseExact メソッドを呼び出すことによって、解析してTryParseExact値に変換する入力文字列の正確な形式を定義できます。

TimeSpan 値に対して操作を実行する

Addition演算子とSubtraction演算子を使用するか、AddメソッドとSubtractメソッドを呼び出すことによって、時間の継続時間を加算および減算できます。 CompareCompareTo、およびEqualsメソッドを呼び出すことで、2 つの期間を比較することもできます。 TimeSpan構造体には、時間間隔を正と負の値に変換するDurationメソッドとNegateメソッドも含まれています。

TimeSpan値の範囲はMinValueからMaxValueまで。

TimeSpan 値の書式設定

TimeSpan値は [-]d として表すことができます。hh:mm:ssオプションのマイナス記号は負の時間間隔を示し、d 成分は日、hh は 24 時間時計で測定された時間、mm は分、ss は秒、ff は秒の分数を示します。 つまり、時間間隔は、時刻のない正または負の日数、または 1 日の時刻を持つ日数、または 1 日の時刻のみで構成されます。

.NET Framework 4 以降では、 TimeSpan 構造体は、 ToString メソッドのオーバーロードを使用してカルチャに依存する書式設定をサポートし、 TimeSpan 値を文字列形式に変換します。 既定の TimeSpan.ToString() メソッドは、.NET Framework の以前のバージョンの戻り値と同じインバリアント形式を使用して時間間隔を返します。 TimeSpan.ToString(String)オーバーロードを使用すると、時間間隔の文字列表現を定義する書式指定文字列を指定できます。 TimeSpan.ToString(String, IFormatProvider)オーバーロードを使用すると、時間間隔の文字列表現を作成するために書式設定規則を使用する書式指定文字列とカルチャを指定できます。 TimeSpan では、標準書式指定文字列とカスタム書式指定文字列の両方がサポートされます。 (詳細については、「 標準 TimeSpan 書式指定文字列 」および 「カスタム TimeSpan 書式指定文字列」を参照してください)。ただし、カルチャに依存するのは標準の書式指定文字列のみです。

従来の TimeSpan 形式を復元する

場合によっては、.NET Framework 3.5 以前のバージョンの TimeSpan 値の書式設定に成功したコードが.NET Framework 4 で失敗することがあります。 これは、 <TimeSpan_LegacyFormatMode> 要素 メソッドを呼び出して TimeSpan 値を書式設定文字列で書式設定するコードで最も一般的です。 次の例では、.NET Framework 3.5 以前のバージョンでは TimeSpan の値が正しく書式設定されますが、.NET Framework 4 以降のバージョンでは例外を投げます。 サポートされていない書式指定子を使用して TimeSpan 値の書式設定を試みます。これは、.NET Framework 3.5 以前のバージョンでは無視されます。

ShowFormattingCode();
// Output from .NET Framework 3.5 and earlier versions:
//       12:30:45
// Output from .NET Framework 4:
//       Invalid Format    

Console.WriteLine("---");

ShowParsingCode();
// Output:
//       000000006 --> 6.00:00:00

void ShowFormattingCode()
{
    TimeSpan interval = new TimeSpan(12, 30, 45);
    string output;
    try
    {
        output = String.Format("{0:r}", interval);
    }
    catch (FormatException)
    {
        output = "Invalid Format";
    }
    Console.WriteLine(output);
}

void ShowParsingCode()
{
    string value = "000000006";
    try
    {
        TimeSpan interval = TimeSpan.Parse(value);
        Console.WriteLine($"{value} --> {interval}");
    }
    catch (FormatException)
    {
        Console.WriteLine($"{value}: Bad Format");
    }
    catch (OverflowException)
    {
        Console.WriteLine($"{value}: Overflow");
    }
}
let showFormattingCode () =
    let interval = TimeSpan(12, 30, 45)
    try
        $"{interval:r}"
    with :? FormatException ->
        "Invalid Format"
    |> printfn "%s"

let showParsingCode () =
    let value = "000000006"
    try
        let interval = TimeSpan.Parse value
        printfn $"{value} --> {interval}"
    with
    | :? FormatException ->
        printfn $"{value}: Bad Format"
    | :? OverflowException ->
        printfn $"{value}: Overflow"

showFormattingCode ()
// Output from .NET Framework 3.5 and earlier versions:
//       12:30:45
// Output from .NET Framework 4:
//       Invalid Format    

printfn "---"

showParsingCode ()
// Output:
//       000000006 --> 6.00:00:00
Dim interval As New TimeSpan(12, 30, 45)
Dim output As String
Try
    output = String.Format("{0:r}", interval)
Catch e As FormatException
    output = "Invalid Format"
End Try
Console.WriteLine(output)
' Output from .NET Framework 3.5 and earlier versions:
'       12:30:45
' Output from .NET Framework 4:
'       Invalid Format

コードを変更できない場合は、次のいずれかの方法で TimeSpan 値の従来の書式を復元できます。

  • <TimeSpan_LegacyFormatMode>要素を含む構成ファイルを作成します。 この要素の enabled 属性を true に設定すると、アプリケーションごとに従来の TimeSpan の書式設定が復元されます。

  • アプリケーション ドメインの作成時に "NetFx40_TimeSpanLegacyFormatMode" 互換性スイッチを設定します。 これにより、アプリケーション ドメインごとに従来の TimeSpan の書式設定が可能になります。 次の例では、従来の TimeSpan 形式を使用するアプリケーション ドメインを作成します。

    using System;
    
    public class Example2
    {
        public static void Main()
        {
            AppDomainSetup appSetup = new AppDomainSetup();
            appSetup.SetCompatibilitySwitches(new string[] { "NetFx40_TimeSpanLegacyFormatMode" });
            AppDomain legacyDomain = AppDomain.CreateDomain("legacyDomain",
                                                            null, appSetup);
            legacyDomain.ExecuteAssembly("ShowTimeSpan.exe");
        }
    }
    
    open System
    
    let appSetup = AppDomainSetup()
    appSetup.SetCompatibilitySwitches [| "NetFx40_TimeSpanLegacyFormatMode" |]
    let legacyDomain = AppDomain.CreateDomain("legacyDomain", null, appSetup)
    legacyDomain.ExecuteAssembly "ShowTimeSpan.exe" |> ignore
    
    Module Example3
        Public Sub Main()
            Dim appSetup As New AppDomainSetup()
            appSetup.SetCompatibilitySwitches({"NetFx40_TimeSpanLegacyFormatMode"})
            Dim legacyDomain As AppDomain = AppDomain.CreateDomain("legacyDomain",
                                                                 Nothing, appSetup)
            legacyDomain.ExecuteAssembly("ShowTimeSpan.exe")
        End Sub
    End Module
    

    次のコードが新しいアプリケーション ドメインで実行されると、従来の TimeSpan 書式設定の動作に戻ります。

    using System;
    
    public class Example3
    {
       public static void Main()
       {
          TimeSpan interval = DateTime.Now - DateTime.Now.Date;
          string msg = String.Format("Elapsed Time Today: {0:d} hours.",
                                     interval);
          Console.WriteLine(msg);
       }
    }
    // The example displays the following output:
    //       Elapsed Time Today: 01:40:52.2524662 hours.
    
    open System
    
    let interval = DateTime.Now - DateTime.Now.Date
    printfn $"Elapsed Time Today: {interval:d} hours."
    // The example displays the following output:
    //       Elapsed Time Today: 01:40:52.2524662 hours.
    
    Module Example4
        Public Sub Main()
            Dim interval As TimeSpan = Date.Now - Date.Now.Date
            Dim msg As String = String.Format("Elapsed Time Today: {0:d} hours.",
                                             interval)
            Console.WriteLine(msg)
        End Sub
    End Module
    ' The example displays output like the following:
    '       Elapsed Time Today: 01:40:52.2524662 hours.