Структуру System.TimeSpan

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

TimeSpan Объект представляет интервал времени (длительность времени или истекшего времени), измеряемый как положительное или отрицательное количество дней, часов, минут, секунд и дробей секунды. TimeSpan Структура также может использоваться для представления времени дня, но только в том случае, если время не связано с определенной датой. DateTime В противном случае следует использовать или DateTimeOffset структуру. (Дополнительные сведения об использовании TimeSpan структуры для отражения времени дня см. в разделе "Выбор между DateTime", DateTimeOffset, TimeSpan и TimeZoneInfo.)

Примечание.

TimeSpan Значение представляет интервал времени и может быть выражено в виде определенного количества дней, часов, минут, секунд и миллисекунд. Поскольку он представляет общий интервал без ссылки на определенную начальную или конечную точку, она не может быть выражена с точки зрения лет и месяцев, оба из которых имеют переменное число дней. Он отличается от DateTime значения, представляющего дату и время без ссылки на определенный часовой пояс или DateTimeOffset значение, представляющее определенный момент времени.

Самая большая единица времени, которую TimeSpan структура использует для измерения длительности в день. Интервалы времени измеряются в днях для согласованности, так как количество дней в больших единицах времени, таких как месяцы и годы, меняется.

Значение TimeSpan объекта — это число тиков, равных представленному интервалу времени. Галок равен 100 наносекундам или 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 значение. Например, можно создать экземпляр 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("{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
    
    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: {0}", 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 значения возвращаются арифметическими операторами и методами DateTimeи структурами, DateTimeOffsetа также 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("'{0}' --> {1}", value, ts);
       }
       catch (FormatException) {
          Console.WriteLine("Unable to parse '{0}'", value);
       }
       catch (OverflowException) {
          Console.WriteLine("'{0}' is outside the range of a TimeSpan.", value);
       }   
    }
    
    // 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 методы. Структура TimeSpan также включает Duration методы и Negate методы, которые преобразуют интервалы времени в положительные и отрицательные значения,

Диапазон значений TimeSpan равен MinValueMaxValue.

Форматирование значения TimeSpan

TimeSpan Значение может быть представлено как [-]d.hh:mm:ss.ff, где необязательный знак минус указывает отрицательный интервал времени, компонент d — дни, чх — это часы, измеряемые на 24-часовом часовом времени, мм — минуты, ss — секунды, а ff — доля секунды. То есть интервал времени состоит из положительного или отрицательного числа дней без времени дня, или числа дней с временем дня или только временем дня.

Начиная с платформа .NET Framework 4 TimeSpan структура поддерживает форматирование с учетом языка и региональных параметров через перегрузки методаToString, которое преобразует TimeSpan значение в строковое представление. Метод по умолчанию возвращает интервал времени с помощью инвариантного формата, идентичного значению TimeSpan.ToString() возвращаемого значения в предыдущих версиях платформа .NET Framework. Перегрузка TimeSpan.ToString(String) позволяет указать строку формата, которая определяет строковое представление интервала времени. Перегрузка TimeSpan.ToString(String, IFormatProvider) позволяет указать строку формата и язык и региональные параметры, соглашения о форматировании которых используются для создания строкового представления интервала времени. TimeSpan поддерживает как стандартные, так и настраиваемые строки формата. (Дополнительные сведения см. в разделе Стандартные строки форматирования TimeSpan и настраиваемые строки формата TimeSpan.) Однако только стандартные строки форматирования чувствительны к языку и региональных параметров.

Восстановление устаревшего форматирования TimeSpan

В некоторых случаях код, который успешно форматирует TimeSpan значения в платформа .NET Framework 3.5 и более ранних версиях, завершается сбоем в платформа .NET Framework 4. Это чаще всего в коде, который вызывает <метод элемента TimeSpan_LegacyFormatMode> для форматирования TimeSpan значения со строкой форматирования. Следующий пример успешно форматирует TimeSpan значение в платформа .NET Framework 3.5 и более ранних версиях, но создает исключение в платформа .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("{0} --> {1}", value, interval);
    }
    catch (FormatException)
    {
        Console.WriteLine("{0}: Bad Format", value);
    }
    catch (OverflowException)
    {
        Console.WriteLine("{0}: Overflow", value);
    }
}
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.