简体   繁体   中英

How do I do division on HH:MM:SS format time strings in C#?

I have a series of times that are coming to me as strings from a web service. The times are formated as HH:MM:SS:000 (3 milisecond digits). I need to compare two times to determine if one is more than twice as long as the other:

if ( timeA / timeB > 2 )

What's the simplest way to work with the time strings?


If I was writing in Python this would be the answer to my question: Difference between two time intervals?

(Except the operator I need is division, not subtraction)


Edit: What I'm really looking for is a way to get the ratio of timeA to timeB, which requires division, not subtraction. Unfortunately, the DateTime structure doesn't appear to have a division operator. Updated the question title and body to reflect this.


Solution:

Based on the answer I picked below, which was the simplest of all the proposed methods so far, here is the working solution:

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:

Recently, this functionality was also required in JavaScript for an AJAX call, so, I had to write a conversion function after all (just not in C#). In case it's needed:

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;
}

Word to the wise: Make sure to specify the second argument of parseInt...

parseInt(string, 10)

...to specify that the string is a Base-10 number. Otherwise, if the string starts with 0 (common in HH:MM:SS formats), JavaScript decides it's a Base-8 number. This causes the strings "08" and "09" to be converted to decimal integer 0 (because 8 and 9 don't exist in Base-8), and the calculations get thrown off.

First you create a DateTime by parsing the string and then the math is easy :)

Note that subtracting two dates with the - operator will return a TimeSpan , check the MSDN docs for what those look like.

See the TimeSpan structure and then Calculate period of time with .NET

And actually, your code could be simplified thusly:

    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");

I think the easiest way to parse the strings is with TimeSpan.ParseExact in .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"));
    }

That will print True False . If you don't have .Net 4, you can use 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;
    }

使用DateTime.FormatExact()将您的字符串转换为DateTime,然后通过区别它们来获取一个TimeSpan进行播放。

I would just parse the strings into a timespan rather then converting to a DateTime first

Here's a sample of how you could do this:

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 );
    }
}

You could add some more validation to the above code as necessary based on how consistent you can expect the time strings to be.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM