Как сделать деление на строки времени формата ЧЧ: ММ: СС в C #? - PullRequest
1 голос
/ 12 января 2011

У меня есть ряд раз, которые приходят ко мне как строки из веб-службы. Время указывается в формате ЧЧ: ММ: СС: 000 (3 милисекундные цифры). Мне нужно сравнить два раза, чтобы определить, является ли один более чем в два раза длиннее другого:

if ( timeA / timeB > 2 )

Какой самый простой способ работы со строками времени?


Если бы я писал на Python, это было бы ответом на мой вопрос: Разница между двумя временными интервалами?

(кроме оператора, который мне нужен, это деление, а не вычитание)


Редактировать: Что я действительно ищу, так это способ получить соотношение времени A к времени B, которое требует деления, а не вычитания. К сожалению, структура DateTime не имеет оператора деления. Обновлен заголовок вопроса и текст, чтобы отразить это.


Решение:

Основываясь на ответе, который я выбрал ниже, который был самым простым из всех предложенных методов, вот рабочее решение:

DateTime timeA;
DateTime timeB;
DateTime.TryParse(webServiceTimeString_A, out timeA);
DateTime.TryParse(webServiceTimeString_B, out timeB);

// TimeA is more than twice the duration of TimeB.
if ( (double)timeA.TimeOfDay.Ticks / (double)timeB.TimeOfDay.Ticks > 2.0f )
{
    // Do stuff.
}
else
{
    // Do different stuff.
}

JavaScript:

В последнее время эта функция также требовалась в JavaScript для вызова AJAX, поэтому мне все-таки пришлось написать функцию преобразования (только не в C #). В случае, если это необходимо:

if (_timeInSeconds(timeA) / _timeInSeconds(timeB) > 2) {
    // Do stuff.
}

// Convert HH:MM:SS:000 string to a number of seconds so we can do math on it.
function _timeInSeconds(stringTime) {
    var timeArray = stringTime.split(":");
    var timeInSeconds = 0;

    //HH
    timeInSeconds += (parseInt(timeArray[0], 10) * 3600);

    //MM
    timeInSeconds += (parseInt(timeArray[1], 10) * 60);

    //SS
    timeInSeconds += (parseInt(timeArray[2], 10));

    //Milliseconds
    timeInSeconds += (parseInt(timeArray[3], 10) / 1000);

    return timeInSeconds;
}

Слово мудрым: обязательно укажите второй аргумент parseInt ...

parseInt(string, 10)

... чтобы указать, что строка является числом Base-10. В противном случае, если строка начинается с 0 (обычно в форматах ЧЧ: ММ: СС), JavaScript решает, что это число Base-8. Это приводит к тому, что строки "08" и "09" преобразуются в десятичное целое число 0 (поскольку 8 и 9 не существуют в Base-8), и вычисления сбрасываются.

Ответы [ 5 ]

3 голосов
/ 12 января 2011

См. Структуру TimeSpan , а затем Расчет периода времени с помощью .NET

А на самом деле ваш код можно упростить таким образом:

    DateTime timeA = DateTime.Now;
    DateTime timeB = DateTime.Now.AddHours(-10.0);

    if ( (double)timeA.TimeOfDay.Ticks / (double)timeB.TimeOfDay.Ticks > 2.0f )
        Console.WriteLine("Time A is more than twice time B");
    else
        Console.WriteLine("Time A is NOT more than twice time B");
3 голосов
/ 12 января 2011

Сначала вы создаете DateTime путем разбора строки , а затем математика проста :)

Обратите внимание, что вычитание двух дат с помощью оператора - вернет TimeSpan, проверьте документы MSDN на то, как они выглядят.

1 голос
/ 12 января 2011

Я думаю, что самый простой способ анализа строк - это TimeSpan.ParseExact в .Net 4:

    public static bool MoreThanDouble(string t1, string t2)
    {
        const string format = @"%h\:mm\:ss\:fff";
        long ticks1 = TimeSpan.ParseExact(t1, format, null).Ticks,
             ticks2 = TimeSpan.ParseExact(t2, format, null).Ticks;
        return ticks1 - ticks2 > ticks2;
    }

    static void Main(string[] args)
    {
        Console.WriteLine(MoreThanDouble("10:11:12:123", "1:23:45:000"));
        Console.WriteLine(MoreThanDouble("10:11:12:123", "9:23:45:000"));
    }

Это напечатает True False. Если у вас нет .Net 4, вы можете использовать DateTime:

    public static bool MoreThanDouble2(string t1, string t2)
    {
        const string format = @"%h\:mm\:ss\:fff";
        long ticks1 = DateTime.ParseExact(t1, format, null,
             System.Globalization.DateTimeStyles.NoCurrentDateDefault).Ticks,
             ticks2 = DateTime.ParseExact(t2, format, null,
             System.Globalization.DateTimeStyles.NoCurrentDateDefault).Ticks;
        return ticks1 - ticks2 > ticks2;
    }
0 голосов
/ 12 января 2011

Я бы просто проанализировал строки в промежуток времени, а не конвертировал бы в DateTime сначала

Вот пример того, как вы могли бы сделать это:

class Program
{
    static void Main( string[] args )
    {
        Console.WriteLine( ( "02:00:00:001".ToTimeSpan().TotalMilliseconds / "01:00:00:000".ToTimeSpan().TotalMilliseconds ) > 2 );
        Console.WriteLine( ( "02:00:00:001".ToTimeSpan().TotalMilliseconds / "00:60:00:000".ToTimeSpan().TotalMilliseconds ) > 2 );
        Console.WriteLine( ( "02:00:00:000".ToTimeSpan().TotalMilliseconds / "01:00:00:001".ToTimeSpan().TotalMilliseconds ) > 2 );
        Console.WriteLine( ( "25:12:60:002".ToTimeSpan().TotalMilliseconds / "12:12:60:002".ToTimeSpan().TotalMilliseconds ) > 2 );
    }
}

public static class Helpers
{
    public static TimeSpan ToTimeSpan(this string time )
    {
        var split = time.Split( ':' );
        if( split.Length != 4 )
        {
            throw new InvalidOperationException("Invalid format");
        }
        //First posistion is days.
        return new TimeSpan(0, split[ 0 ].ToInt(), split[ 1 ].ToInt(), split[ 2 ].ToInt(), split[ 3 ].ToInt() );
    }

    public static int ToInt( this string str )
    {
        return Convert.ToInt32( str );
    }
}

Вы можете добавить дополнительную проверку в приведенный выше код по мере необходимости, основываясь на том, насколько последовательными вы можете ожидать, что строки времени будут.

0 голосов
/ 12 января 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...