为什么这个特定的TimeSpan格式字符串在.NET 4中停止工作?

时间:2010-07-30 15:38:25

标签: c# .net formatting .net-4.0 timespan

考虑这段代码(预先填写一个例子):

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}", ts ));

这是我至少从.NET 1.1开始工作的一段代码的代表。

它在1.1到3.5中运行良好,输出如下(对于这些dummied up输入):

30.00:00:28.3580246

但是现在我看到它在.NET 4中死了,并显示错误消息:

Input string was not in a correct format.

因此,就好像.NET 4突然决定它不喜欢这种格式的时差。将行更改为,例如

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

具有相同的效果。

现在我注意到的事情是,如果我只是执行默认.ToString(),我会得到相同的输出。我认为思考过程是这是针对未来版本中默认格式变化的保险政策。但现在它看起来并不像是一种选择。

有谁知道为什么会改变这种情况,如果我做错了什么或者是否有最佳实践方法来做我想要完成的事情?

5 个答案:

答案 0 :(得分:6)

有一个configuration switch可以恢复TimeSpan的旧行为。

答案 1 :(得分:3)

配置开关的替代方案是格式更改,与以前的版本兼容。

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

此解决方案详细here

答案 2 :(得分:1)

事实上,您在代码中使用的复合格式字符串根本没有任何影响,因为TimeSpan 不支持支持自定义格式化字符串(.NET< 4.0)。

即。无论格式字符串是什么,您的TimeSpan都会被格式化为30.00:00:28.3580246

来自MSDN:

  

在以前版本的.NET Framework中,TimeSpan结构确实如此   没有实现IFormattable并且不支持格式字符串。

     

然而,许多开发人员错误地认为TimeSpan确实支持   一组格式字符串,并在复合格式中使用它们   使用String.Format等方法进行操作。通常,如果是一种类型   实现IFormattable并支持格式字符串,调用   使用不受支持的格式字符串的格式化方法通常会抛出   出现FormatException。但是,因为TimeSpan没有实现   IFormattable,运行时忽略格式字符串而是调用   TimeSpan.ToString()方法。 这意味着,虽然格式   字符串对格式化操作没有影响,它们的存在确实如此   不会导致FormatException。

答案 3 :(得分:1)

正如Mitch Wheat和Saeb Amini在their answers中指出的那样,TimeSpan在.NET 4.0之前没有实现IFormattable。因此,格式字符串对TimeSpan.ToString()输出无影响,因为它们被忽略了。

  

但是,由于TimeSpan没有实现IFormattable,运行时忽略了格式字符串,而是调用了TimeSpan.ToString方法。这意味着,虽然格式字符串对格式化操作没有影响,但它们的存在不会导致FormatException。

     

Source

那就是说,如果你希望在所有版本的.NET框架中格式化TimeSpan值,那么将TimeSpan值转换为DateTime然后格式化就好了结果如下图所示:

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

答案 4 :(得分:0)

我已经粘贴了你的代码,这似乎是一个文化问题:

使用.NET 2也会抛出FormatException

如果我指定了美国文化(文化默认为fr-FR),则代码可以工作:

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

您还可以指定不变文化来忽略文化

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