C# 为什么这个特定的TimeSpan格式字符串在.NET4中停止工作?
考虑以下代码(用示例预先填充): 这是我从.NET1.1开始工作的一段代码的代表 它在1.1到3.5中运行良好,具有以下输出(对于这些模拟输入): 但现在我看到它在.NET 4中消失,并显示错误消息:C# 为什么这个特定的TimeSpan格式字符串在.NET4中停止工作?,c#,.net,formatting,.net-4.0,timespan,C#,.net,Formatting,.net 4.0,Timespan,考虑以下代码(用示例预先填充): 这是我从.NET1.1开始工作的一段代码的代表 它在1.1到3.5中运行良好,具有以下输出(对于这些模拟输入): 但现在我看到它在.NET 4中消失,并显示错误消息: 输入字符串的格式不正确。 所以,就好像.NET4突然决定不喜欢这种时差格式。把线路改成,比如说 Console.WriteLine(string.Format( "{0}", ts.ToString("d.hh:mm:ss.ff") )); 也有同样的效果 现在我注意到,如果我只执行默认的.To
输入字符串的格式不正确。
所以,就好像.NET4突然决定不喜欢这种时差格式。把线路改成,比如说
Console.WriteLine(string.Format( "{0}", ts.ToString("d.hh:mm:ss.ff") ));
也有同样的效果
现在我注意到,如果我只执行默认的.ToString()
,我会得到相同的输出。我相信思考的过程是,这是针对未来版本中更改的默认格式的保险单。但现在看来这根本不是一个选择
有人知道为什么会发生这种变化,我是否做了错事,或者是否有一种最佳实践方法来完成我试图完成的任务吗?我粘贴了您的代码,这似乎是一个文化问题: 对于.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);
有一种方法可以恢复的旧行为。配置开关的另一种选择是与以前版本兼容的格式更改
Console.WriteLine(string.Format( "{0:hh\\:mm\\:ss.ff}", ts ));
此解决方案非常详细。事实上,您在代码中使用的复合格式字符串根本没有任何效果,因为
TimeSpan
不支持自定义格式字符串(.NET<4.0)
i、 e.无论格式字符串如何,TimeSpan的格式始终为30.00:00:28.3580246
从MSDN:
在.NET Framework的早期版本中,TimeSpan结构没有
未实现IFormattable,并且不支持格式字符串
然而,许多开发人员错误地认为TimeSpan确实支持
一组格式字符串,用于复合格式
使用String.Format等方法执行的操作。通常,如果一个类型
实现IFormattable并支持格式化字符串、调用
带有不受支持的格式字符串的格式化方法通常会抛出
格式化异常。但是,因为TimeSpan没有实现
IFormattable,则运行时忽略格式字符串,而调用
TimeSpan.ToString()方法这意味着,虽然
字符串对格式化操作没有影响,但它们的存在对格式化操作没有影响
不会导致格式异常。
正如Mitch Wheat和Saeb Amini在中所指出的,
TimeSpan
没有实现.NET 4.0之前的IFormattable
。因此,格式字符串对TimeSpan.ToString()
输出没有影响,因为它们被忽略了
但是,由于TimeSpan没有实现IFormattable,运行时忽略了格式字符串,而是调用了TimeSpan.ToString方法。这意味着,尽管格式字符串对格式化操作没有影响,但它们的存在不会导致FormatException
也就是说,如果希望在.NET framework的所有版本中格式化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
我想你已经了解了文化,但是,让我感到适合的不是日期时间线,而是时间跨度格式字符串。即使我在TimeSpan-ToString和这两个DateTime.Parse方法中指定了区域性,我仍然得到了相同的结果。所以基本上,格式字符串一直没有做任何事情。杰出的。谢谢你,真的。在.NET3.5及更早版本中,
TimeSpan
结构不是IFormattable
。当string.Format
和相关方法看到类似{0:something}
的内容,并且提供的参数不是IFormattable
时,它们没有地方放置该格式字符串,只需丢弃它。在.NET4.0出现之前,您的代码就是这样的。这为我修复了它:)
Console.WriteLine(string.Format( "{0:hh\\:mm\\:ss.ff}", ts ));
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