Как анализировать строку с часами больше 24 на TimeSpan?
Как анализировать строку, например 30:15, на TimeSpan в С#? 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]))));
Это не кажется слишком элегантным.
Ответы
Ответ 1
Если вы уверены, что формат всегда будет "HH: mm", попробуйте что-то вроде этого:
string span = "35:15";
TimeSpan ts = new TimeSpan(int.Parse(span.Split(':')[0]), // hours
int.Parse(span.Split(':')[1]), // minutes
0); // seconds
Ответ 2
Подобно Люку:
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
Я использую простой метод, который я разработал давно и только что опубликовал сегодня в своем блоге:
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());
}
Вы даже можете сделать его одним лайнером, если вы не против использования горизонтального состояния экрана...
Ответ 4
Как и в случае с Lukes, с гораздо большим количеством кода и возможностью для улучшения. НО это касается отрицательных часов ( "-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");
Ответ 5
Обычно используется 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);
(Но с некоторой проверкой ошибок.)
Три целых конструктора временного интервала позволяют считать часы >= 24 переполненными в количество дней.