开发者

Why has this particular TimeSpan format string stopped working in .NET 4?

开发者 https://www.devze.com 2023-01-09 19:53 出处:网络
Consider this code (prestuffed with an example): DateTime dt1 = DateTime.Parse(\"7/30/2010 9:33:29.1234567 AM\");

Consider this code (prestuffed with an example):

DateTime dt1 = DateTime.Parse("7/30/2010 9:33:29.1234567 AM");
DateTime dt2 = DateTime.Parse("6/30/2010 9:33:00.7654321 AM");

TimeSpan ts = dt1 - dt2;

Console.WriteLine(string.For开发者_如何学Cmat( "{0:d.hh:mm:ss.ff}", ts ));

This is representative of a piece of code that I've had working since .NET 1.1 at least.

It worked fine in 1.1 through 3.5 with the following output (for these dummied up inputs):

30.00:00:28.3580246

But now I'm seeing that it dies in .NET 4 with the error message:

Input string was not in a correct format.

So it's as if .NET 4 has suddenly decided it doesn't like this format for time differences. Changing the line to, say

Console.WriteLine(string.Format( "{0}", ts.ToString("d.hh:mm:ss.ff") ));

has the same effect.

Now the thing I've noticed is that if I just do the default .ToString() I get the same output. I believe the thought process was that this was an insurance policy against the default format changing in a future version. But now it doesn't look like that's even an option.

Does anyone know why this changed and if I'm doing something wrong or if there's a best practices way to do what I'm trying to accomplish?


There is a configuration switch to restore the old behaviour of TimeSpan.


An alternative to the configuration switch is a format change that is compatible with previous versions.

Console.WriteLine(string.Format( "{0:hh\\:mm\\:ss.ff}", ts )); 

This solution is detail here.


In fact, the composite format string you've been using in your code did not have any effect at all, because TimeSpan does not support custom format strings (.NET < 4.0).

i.e. Your TimeSpan would have always been formatted like 30.00:00:28.3580246 regardless of format string.

From MSDN:

In previous versions of the .NET Framework, the TimeSpan structure did not implement IFormattable and did not support format strings.

However, many developers mistakenly assumed that TimeSpan did support a set of format strings and used them in composite formatting operations with methods such as String.Format. Ordinarily, if a type implements IFormattable and supports format strings, calls to formatting methods with unsupported format strings usually throw a FormatException. However, because TimeSpan did not implement IFormattable, the runtime ignored the format string and instead called the TimeSpan.ToString() method. This means that, although the format strings had no effect on the formatting operation, their presence did not result in a FormatException.


As indicated by Mitch Wheat and Saeb Amini in their answers, TimeSpan does not implement IFormattable prior to .NET 4.0. Consequently, format strings have no effect on the TimeSpan.ToString() output since they were ignored.

However, because TimeSpan did not implement IFormattable, the runtime ignored the format string and instead called the TimeSpan.ToString method. This means that, although the format strings had no effect on the formatting operation, their presence did not result in a FormatException.

Source

That said, fi you desire to format a TimeSpan value across all versions of the .NET framework, it is much better to convert the TimeSpan value to DateTime and then format that result as shown below:

DateTime dt1 = DateTime.Parse("7/30/2010 9:33:29.1234567 AM");
DateTime dt2 = DateTime.Parse("6/30/2010 9:33:00.7654321 AM");

TimeSpan ts = dt1 - dt2;

Console.WriteLine(String.Format("{0:d.hh:mm:ss.ff}", new DateTime(ts.Ticks))) 
// prints 30.00:00:28.36


I've pasted your piece of code and it seems to be a culture problem :

with .NET 2 an FormatException is thrown too

If I specified the us culture (culture is fr-FR by default) , the code works :

DateTime dt1 = DateTime.Parse("7/30/2010 9:33:29.1234567 AM", CultureInfo.GetCultureInfo("en-US"));

You can also specified an Invariant culture to ignore the culture

DateTime dt1 = DateTime.Parse("7/30/2010 9:33:29.1234567 AM", CultureInfo.InvariantCulture);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号