考虑这段代码(预先填写一个例子):
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()
,我会得到相同的输出。我认为思考过程是这是针对未来版本中默认格式变化的保险政策。但现在它看起来并不像是一种选择。
有谁知道为什么会改变这种情况,如果我做错了什么或者是否有最佳实践方法来做我想要完成的事情?
答案 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。
那就是说,如果你希望在所有版本的.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);