C# TimeSpan.Parse invalid format returns incorrect value instead of exception
Asked Answered
I

1

20

TimeSpan.Parse("23:00:00") returns 23 hours.

TimeSpan.Parse("24:00:00") returns 24 days!

I realize that I made a mistake in that the allowable range of hours is 0-23. But for minutes and seconds if you attempt to parse an out of range value you get an exception. In the case of hours with an out of range value, the parser incorrectly assumes you meant days instead of hours.

Can someone explain this?

This example here covers this very topic and indicates that http://msdn.microsoft.com/en-us/magazine/ee309881.aspx

The same appears to be true about TryParse. I get 24 days despite the docs stating that the parse should fail.

http://msdn.microsoft.com/en-us/library/3z48198e

//            String to Parse                TimeSpan
//            ---------------   ---------------------
//                          0        00:00:00
//                         14     14.00:00:00
//                      1:2:3        01:02:03
//                  0:0:0.250        00:00:00.2500000
//             10.20:30:40.50     10.20:30:40.5000000
//        99.23:59:59.9999999     99.23:59:59.9999999
//        0023:0059:0059.0099        23:59:59.0099000
//                     23:0:0        23:00:00
//                     24:0:0   Parse operation failed.
//                     0:59:0        00:59:00
//                     0:60:0   Parse operation failed.
//                     0:0:59        00:00:59
//                     0:0:60   Parse operation failed.
//                        10:   Parse operation failed.
//                       10:0        10:00:00
//                        :10   Parse operation failed.
//                       0:10        00:10:00
//                     10:20:   Parse operation failed.
//                    10:20:0        10:20:00
//                       .123   Parse operation failed.
//                    0.12:00        12:00:00
//                        10.   Parse operation failed.
//                      10.12   Parse operation failed.
//                   10.12:00     10.12:00:00

Did I find a bug or am I doing something wrong?

EDIT: I've tested this in LinqPad and using a Console app in .NET4 on Windows 7 64bit.

            var result = TimeSpan.Parse("24:00:00");
            Console.WriteLine(result);
            result = TimeSpan.Parse("24:00:00", CultureInfo.InvariantCulture);
            Console.WriteLine(result);

This results in:

24.00:00:00
24.00:00:00
Irrawaddy answered 22/6, 2012 at 14:3 Comment(7)
You are comparing result of TryParse and Parse. The TimeSpan.Parse(String) method tries to parse string (parameter) by using each of the culture-specific formats for the current culture. So you are getting days.Nga
It throws an exception for me. Maybe it's a culture thing? @Romil: Parse calls TryParse behind the scenes so they should have the same result.Jaclin
This reliably generates an OverflowException when I try it. Improve your question by documenting the .NET version, your culture and any overrides you may have applied in the Windows regional settings.Jerroldjerroll
Your question is not clear. Update your question with the code you are using.Herold
Compiling the exact code on the documentation page (msdn.microsoft.com/en-us/library/3z48198e), using .Net 4.0, returns 24 days for me as well. The applicable output line is 24:0:0 24.00:00:00, not 24:0:0 Parse operation failed.Lynnett
Confirmed with LinqPAD on Win7 64bit Italian culture. It return 24 days, but I have changed the default time sep from . to :Dominique
I updated the original post with platform info and the exact code that I used.Irrawaddy
G
13

What's going on is that TimeSpan.Parse attempts to parse ##:##:## using each of the following formats in order, stopping as soon as one succeeds:

  1. hh:mm:ss (invariant culture)
  2. d.hh:mm (invariant culture)
  3. hh:mm:ss (localized)
  4. d.hh:mm (localized; more details about the "." below)

So:

  • 23:08:09 is successfully parsed as 0d 23h 8m 9s in Step 1.
  • 24:08:09 is successfully parsed as 24d 8h 9m 0s in Step 4.

If this behavior doesn't suit you, you can use TimeSpan.ParseExact instead:

TimeSpan.ParseExact("23:00:00", "hh':'mm':'ss", null) // OK
TimeSpan.ParseExact("24:00:00", "hh':'mm':'ss", null) // OverflowException

UPDATE: According to the documentation for TimeSpan.Parse, the "." between "d" and "hh" is

A culture-sensitive symbol that separates days from hours. The invariant format uses a period (".") character.

However, I dug into the framework source with Reflector, and it turns out that, in the localized format, this alleged "culture-sensitive" symbol is always a colon! Here's an excerpt from the internal DateTimeFormatInfo.FullTimeSpanPositivePattern property:

string separator = new NumberFormatInfo(cultureData).NumberDecimalSeparator;
this.m_fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + separator + "'FFFFFFF";
Godfry answered 22/6, 2012 at 15:17 Comment(3)
How does "XX:00:00" match "d.HH:mm"? There is no period in the string! This still seems like an unexpected result.Irrawaddy
OK, this is the best explanation now. I can see why the code behaves like it does, but I'm of the opinion that this is not the documented (expected/intended?) behavior.Irrawaddy
I agree; the actual behavior is rather unfortunate and surprising.Godfry

© 2022 - 2024 — McMap. All rights reserved.