Как разобрать строку с часами больше 24 на TimeSpan? - PullRequest
25 голосов
/ 28 апреля 2010

Как разобрать строку как 30:15 в TimeSpan в C #? 30:15 означает 30 часов и 15 минут.

string span = "30:15";
TimeSpan ts = TimeSpan.FromHours(
    Convert.ToDouble(span.Split(':')[0])).
  Add(TimeSpan.FromMinutes(
    Convert.ToDouble((span.Split(':')[1]))));

Это не кажется слишком элегантным.

Ответы [ 5 ]

27 голосов
/ 28 апреля 2010

Если вы уверены, что формат всегда будет «ЧЧ: мм», попробуйте что-то вроде этого:

string span = "35:15";
TimeSpan ts = new TimeSpan(int.Parse(span.Split(':')[0]),    // hours
                           int.Parse(span.Split(':')[1]),    // minutes
                           0);                               // seconds
4 голосов
/ 28 апреля 2010

Аналогично ответу Люка:

String span = "123:45";
Int32 colon = span.IndexOf(':');
TimeSpan timeSpan = new TimeSpan(Int32.Parse(span.Substring(0, colon - 1)),
                                 Int32.Parse(span.Substring(colon + 1)), 0);

Очевидно, что предполагается, что исходная строка имеет правильную форму (состоит из двух частей, разделенных двоеточием и разбираемых на целое число).

3 голосов
/ 22 июня 2011

Я использую простой метод, который я разработал давным-давно и только что опубликовал сегодня в своем блоге:

public static class TimeSpanExtensions
{
    static int[] weights = { 60 * 60 * 1000, 60 * 1000, 1000, 1 };

    public static TimeSpan ToTimeSpan(this string s)
    {
        string[] parts = s.Split('.', ':');
        long ms = 0;
        for (int i = 0; i < parts.Length && i < weights.Length; i++)
            ms += Convert.ToInt64(parts[i]) * weights[i];
        return TimeSpan.FromMilliseconds(ms);
    }
}

Это может справиться с гораздо большим количеством ситуаций, чем простые решения, представленные ранее, но имеет свои недостатки. Я обсуждаю это далее здесь .

Теперь, если вы находитесь в .NET 4, вы можете сократить реализацию ToTimeSpan до:

public static TimeSpan ToTimeSpan(this string s)
{
    return TimeSpan.FromMilliseconds(s.Split('.', ':')
        .Zip(weights, (d, w) => Convert.ToInt64(d) * w).Sum());
}

Вы даже можете сделать его однострочным, если не возражаете против использования горизонтального состояния экрана ...

1 голос
/ 17 мая 2017

Аналогично ответу Люка, с гораздо большим количеством кода и возможностей для улучшения. НО он также имеет дело с негативными часами («-30: 15»), поэтому, возможно, он может кому-то помочь.

public static double GetTotalHours(String s)
    {
        bool isNegative = false;
        if (s.StartsWith("-"))
            isNegative = true;

        String[] splitted = s.Split(':');
        int hours = GetNumbersAsInt(splitted[0]);
        int minutes = GetNumbersAsInt(splitted[1]);

        if (isNegative)
        {
            hours = hours * (-1);
            minutes = minutes * (-1);
        }
        TimeSpan t = new TimeSpan(hours, minutes, 0);
        return t.TotalHours;
    }

public static int GetNumbersAsInt(String input)
        {
            String output = String.Empty;
            Char[] chars = input.ToCharArray(0, input.Length);
            for (int i = 0; i < chars.Length; i++)
            {
                if (Char.IsNumber(chars[i]) == true)
                    output = output + chars[i];
            }
            return int.Parse(output);
        }

использование

double result = GetTotalHours("30:15");
double result2 = GetTotalHours("-30:15");
0 голосов
/ 28 апреля 2010

Обычно можно использовать TimeSpan.ParseExact, где требуется определенный формат. Но можно указывать только форматы часов как части дней (см. Строки пользовательского формата TimeSpan ).

Поэтому вам нужно будет выполнить работу самостоятельно:

string input = "30:24";
var parts = input.Split(':');
var hours = Int32.Parse(parts[0]);
var minutes = Int32.Parse(parts[1]);
var result = new TimeSpan(hours, minutes, 0);

(но с некоторой проверкой ошибок.)

Три целочисленных конструктора timespan допускают переполнение часов> = 24 в число дней.

...