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

发布于 2024-09-12 08:01:22 字数 804 浏览 4 评论 0原文

考虑这段代码(带有示例):

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 中运行良好,输出如下(对于这些虚拟输入):

30.00:00:28.3580246

但现在我看到它在 .NET 4 中终止并显示错误消息:

输入字符串格式不正确。< /code>

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

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

具有相同的效果。

现在我注意到的是,如果我只执行默认的 .ToString() 我会得到相同的输出。我相信这个思考过程是,这是针对未来版本中默认格式更改的保险政策。但现在看来这甚至不是一个选择。

有谁知道为什么会发生这种变化,以及我是否做错了什么,或者是否有最佳实践方法来完成我想要完成的任务?

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.Format( "{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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

倚栏听风 2024-09-19 08:01:22

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

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

此解决方案的详细信息此处< /a>.

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.

谁许谁一生繁华 2024-09-19 08:01:22

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

ie 无论格式字符串如何,您的 TimeSpan 的格式始终如 30.00:00:28.3580246

来自 MSDN:

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

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

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.

完美的未来在梦里 2024-09-19 08:01:22

正如 Mitch Wheat 和 Saeb Amini 在 他们的 答案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

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
国粹 2024-09-19 08:01:22

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

对于.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);

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文