Convert.ToDateTime 在下午的日期/时间值上导致 FormatException

发布于 2024-08-08 05:16:35 字数 1041 浏览 5 评论 0原文

我们有一个应用程序解析以下格式的日期/时间值:

2009-10-10 09:19:12.124
2009-10-10 12:13:14.852
2009-10-10 13:00:00
2009-10-10 15:23:32.022

一台特定服务器突然(今天)开始无法解析 13:00:00 或之后的任何时间。该特定客户端有五台服务器,只有一台出现问题。我们还有数十个其他客户端,总共数百台服务器都没有出现问题。

System.FormatException: String was not recognized as a valid DateTime.
at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
at System.DateTime.Parse(String s, IFormatProvider provider)
at System.Convert.ToDateTime(String value, IFormatProvider provider)
at System.String.System.IConvertible.ToDateTime(IFormatProvider provider)
at System.Convert.ToDateTime(Object value)

我使用 DateTime.Parse(s, CultureInfo.CurrentCulture) 与 DateTime.Parse(s, CultureInfo.InvariantCulture) 进行比较,进行了测试,问题仅出现在 CurrentCulture 中。然而,CurrentCulture 是“en-US”,就像所有其他服务器一样,我在区域或语言设置中找不到任何不同之处。

有人见过这个吗?与我可以研究的内容相关的建议?

编辑:感谢您到目前为止的回答。但是,我正在寻找有关要研究哪些配置的建议,这些配置可能会导致其行为突然改变并在运行多年并在数百台其他服务器上运行时停止工作。我已经在下一个版本中更改了它,但我正在寻找配置更改来在当前安装的过渡期间修复此问题。

We have an application parsing date/time values in the following format:

2009-10-10 09:19:12.124
2009-10-10 12:13:14.852
2009-10-10 13:00:00
2009-10-10 15:23:32.022

One particular server all of the sudden (today) started failing to parse any times 13:00:00 or later. This particular client has five servers and only one has the problem. We have dozens of other clients with a total of hundreds of servers without the problem.

System.FormatException: String was not recognized as a valid DateTime.
at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
at System.DateTime.Parse(String s, IFormatProvider provider)
at System.Convert.ToDateTime(String value, IFormatProvider provider)
at System.String.System.IConvertible.ToDateTime(IFormatProvider provider)
at System.Convert.ToDateTime(Object value)

I ran a test using DateTime.Parse(s, CultureInfo.CurrentCulture) comapred to DateTime.Parse(s, CultureInfo.InvariantCulture) and the problem only shows up with CurrentCulture. However, CurrentCulture is "en-US" just like all the other servers and there's nothing different that I can find in regional or language settings.

Has anyone seen this before? Suggestions related to what I can look into?

EDIT: Thank you for the answers so far. However, I'm looking for suggestions on what configuration to look into that could have caused this to suddenly change behavior and stop working when it's worked for years and works on hundreds of other servers. I've already changed it for the next version, but I'm looking for a configuration change to fix this in the interim for the current installation.

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

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

发布评论

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

评论(8

妄司 2024-08-15 05:16:35

如果您确切地知道格式,请告诉应用程序它是什么 - 使用 DateTime.ParseExact 而不仅仅是 DateTime.Parse。 (正如其他人所说,还要指定不变的区域性,以消除更多的变化。)这给了你更多的控制权:

using System;
using System.Globalization;

class Test
{
    static void Main()
    {
        Parse("2009-10-10 09:19:12.124");
        Parse("2009-10-10 12:13:14.852");
        Parse("2009-10-10 13:00:00");
        Parse("2009-10-10 15:23:32.022");
    }

    static readonly string ShortFormat = "yyyy-MM-dd HH:mm:ss";
    static readonly string LongFormat = "yyyy-MM-dd HH:mm:ss.fff";

    static readonly string[] Formats = { ShortFormat, LongFormat };

    static void Parse(string text)
    {
        // Adjust styles as per requirements
        DateTime result = DateTime.ParseExact(text, Formats, 
                                              CultureInfo.InvariantCulture,
                                              DateTimeStyles.AssumeUniversal);
        Console.WriteLine(result);
    }
}

If you know the format exactly, tell the application what it is - use DateTime.ParseExact instead of just DateTime.Parse. (And as others have said, specify the invariant culture as well, to take away any more variation.) That gives you much more control:

using System;
using System.Globalization;

class Test
{
    static void Main()
    {
        Parse("2009-10-10 09:19:12.124");
        Parse("2009-10-10 12:13:14.852");
        Parse("2009-10-10 13:00:00");
        Parse("2009-10-10 15:23:32.022");
    }

    static readonly string ShortFormat = "yyyy-MM-dd HH:mm:ss";
    static readonly string LongFormat = "yyyy-MM-dd HH:mm:ss.fff";

    static readonly string[] Formats = { ShortFormat, LongFormat };

    static void Parse(string text)
    {
        // Adjust styles as per requirements
        DateTime result = DateTime.ParseExact(text, Formats, 
                                              CultureInfo.InvariantCulture,
                                              DateTimeStyles.AssumeUniversal);
        Console.WriteLine(result);
    }
}
随遇而安 2024-08-15 05:16:35

我们也遇到了同样的问题。只需回收您的应用程序池即可。

We also encountered the same problem. Just recycle your application pool.

万水千山粽是情ミ 2024-08-15 05:16:35

我们有一个在 Windows 2003 服务器上运行的 C# .NET 2.0 Web 服务。该服务已经运行了两年多。我们最近开始在该应用程序中遇到错误。错误消息是“字符串未被识别为有效的日期时间”。另一个网络服务返回一个日期,该函数应该返回一个类似的值

“2010 年 5 月 10 日 12:00:00 上午”

当发生错误时函数返回

“2010年5月10日12:00:00”

错误的返回末尾有空格且没有 AM。

在接下来的几周内,这个问题多次出现又消失。检查 Windows 日志后,我们注意到错误的开始和结束时间与设置(默认情况下)每 29 小时发生一次的应用程序池回收时间一致(在一两分钟内)。此问题仅出现在生产 Web 服务器上,而不会出现在开发或测试服务器上。我们尝试更换服务器,一个月没有出现任何错误。现在错误又开始了。我们手动重置池,问题立即消失。我们不希望将此视为可接受的解决方案,因为池会定期回收。我们不知道是否需要池回收,但我们的理解是定期回收有助于提高应用程序性能。

Web 应用程序已经使用 ParseExact(),但格式字符串如下所示:

“yyyy-MM-ddHH:mm:ss.0Z”

而不是

“yyyy-MM-dd HH:mm:ss”

Jon Skeet 在此线程中建议 。我不知道这是否会产生很大的影响。

我们还检查了文化设置。

很明显,问题始于应用程序池回收,但我不知道回收期间幕后发生了什么。大多数情况下,回收不会产生负面影响,并且当错误确实发生时,下一次回收总是会停止错误。

We have an C# .NET 2.0 web service running on a Windows 2003 server. That service has been running for more than two years. We recently srtarted experiencing errors in that application. The error message is "String was not recognized as a valid DateTime". Another web servie returns a date, and that function should return a value like

"5/10/2010 12:00:00 AM"

When the errors are occurring the function returns

"5/10/2010 12:00:00 "

The incorrect return has white space at the end and no AM.

This problem appeared and disappeared several times over the next couple of weeks. After examining the windows logs, we noticed that the start and end times of the errors coincided (within a minute or two) of an application pool recycle that is set (by default) to occur every 29 hours. This problem only occurred on the production web server, and not on the development or test servers. We tried replacing the server, and there were no errors for a month. Now the errors have started again. We manually reset the pool and the problem disappeared immediately. We would rather not view this as an acceptable solution, as the pool recycles regularly. We don't know if we need the pool recycle, but it is our understanding that regular recycles help with application performance.

The web application uses ParseExact() already, but the format string looks like this:

"yyyy-MM-ddHH:mm:ss.0Z"

instead of

"yyyy-MM-dd HH:mm:ss"

suggested by Jon Skeet in this thread. I don't know if this would make much difference.

We also checked the culture settings.

It seems clear that the problem begins with the application pool recycle, but I have no idea what occurs under the hood during that recycle. Most of the time the recycle has no negative effect, and when the errors do occur, the next recycle has always stopped the errors.

不羁少年 2024-08-15 05:16:35

解决方案非常简单,使用CultureInfo.InvariantCulture。对于样本数据,这是唯一明智的做法。

我知道这并不能解释其中的差异,但你的软件确实不应该依赖于“默认”文化(也许在用户界面中除外)。

The solution is very simple, use CultureInfo.InvariantCulture. For the sample data that is the only sensible thing to do.

I know this doesn't explain the difference, but your software really shouldn't rely on the 'default' culture (except maybe in the UI).

孤独岁月 2024-08-15 05:16:35

我刚刚找到了一些有关导致此问题的原因的信息。我们的 C# 客户端将业务日期(仅日期)作为字符串值发送到 Web 服务。 Web 服务将 SqlParameter 中的此字符串传递给 SqlCommand 以及接受业务日期的 datetime 参数的存储过程。

客户的系统突然出现异常。我使用 SQL Server Profiler 观察 RPC 调用,并注意到日期参数突然包含了时间部分。这应该是仅日期值 - 即 10/27/2012 12:00:00 AM。

我修改了存储过程以添加 WAITFOR DELAY '00:01:00'。然后,当 Web 服务调用该存储过程时,我获取了该 Web 服务的内存转储。

检查内存转储,我发现客户端在参数数据集中传入了正确的日期字符串“2012-10-25 00:00:00”。 Web 服务在调用存储过程时以某种方式搞乱了这些日期的转换。我在转储中找到了 SqlCommand,并检查了与存储过程的日期参数相对应的 SqlParameter。该值为“10/25/2012 12:00:00 PM”。

查看所有 CultureInfo 对象,我发现“en-US”的区域设置 1033 有一个很长的字符串“h:mm:ss tt”。 AMDesignator 是“AM”,但是PMDesignator 是一个空字符串!我通过运行以下命令验证了这是 C# 中错误日期的原因:

// clear the PM designator
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = ""
// this will yield "12/25/2012 12:00:00 " (note the extra space at the end)
Convert.ToDateTime("10/25/2012").ToString()

结果是“10/25/2012 12:00:00”,这与 Brian Begley 的答案相对应。使用不变格式会产生非常相似的结果:

// clear the PM designator
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = ""
// this will yield "10/25/2012 12:00:00"
Convert.ToDateTime("10/25/2012").ToString(System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat)
// restore the PM designator to "PM"
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = "PM"
// this will yield "10/25/2012 00:00:00"
Convert.ToDateTime("10/25/2012").ToString(System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat)

我尚未确定导致 CultureInfo 损坏的原因。

请注意,Microsoft 已意识到此问题。链接的文章说它仅适用于 Windows Server 2003,并且有一个可用的修补程序。

I've just found some information about what is causing this issue. Our C# client sends a business date (date only) as a string value to a web service. The web service passes this string in a SqlParameter to a SqlCommand to a stored procedure that accepts a datetime parameter for the business date.

A customer's system was suddenly misbehaving. I used the SQL Server Profiler to watch the RPC calls and noticed that the date parameter suddenly had a time component. This is supposed to be a date only value-- i.e. 10/27/2012 12:00:00 AM.

I modified the stored procedure to add a WAITFOR DELAY '00:01:00'. I then acquired a memory dump of the web service while it was making the call to this stored procedure.

Examining the memory dump, I found that the client had passed in the correct date string of "2012-10-25 00:00:00" in a DataSet of parameters. The web service somehow messed up the conversion of these dates when it called the stored procedure. I found the SqlCommand in the dump and examined the SqlParameter corresponding to the stored procedure's date parameter. The value was "10/25/2012 12:00:00 PM".

Looking at all the CultureInfo objects, I found locale 1033 for "en-US" had a long time string of "h:mm:ss tt". The AMDesignator was "AM", but the PMDesignator was an empty string! I verified this was the cause of the bad date in C# by running the following command:

// clear the PM designator
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = ""
// this will yield "12/25/2012 12:00:00 " (note the extra space at the end)
Convert.ToDateTime("10/25/2012").ToString()

The result was "10/25/2012 12:00:00 " which corresponds to what Brian Begley in his answer. Using the invariant format yields a very similar result:

// clear the PM designator
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = ""
// this will yield "10/25/2012 12:00:00"
Convert.ToDateTime("10/25/2012").ToString(System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat)
// restore the PM designator to "PM"
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = "PM"
// this will yield "10/25/2012 00:00:00"
Convert.ToDateTime("10/25/2012").ToString(System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat)

I have yet to determine what is causing the CultureInfo to be corrupted.

Note that Microsoft is aware of this issue. The article linked says it applies only to Windows Server 2003, and there is a hotfix available.

故事未完 2024-08-15 05:16:35

听起来好像文化对象不理解军事时间符号。老实说,我不确定从哪里开始,但它可能会给你一个起点。

It sounds like somehow the culture object isn't understanding military time notation. I'm honestly not sure where to go from there, but it may give you a starting point.

韶华倾负 2024-08-15 05:16:35

CultureInfo.DateTimeFormat 属性的值是多少? 根据 MSDN

“用户可能会选择覆盖
一些与相关的值
当前的 Windows 文化
区域和语言选项部分
控制面板。例如,
用户可以选择显示日期
以不同的格式或使用
默认货币以外的货币
文化。

如果 UseUserOverride 为 true 并且
指定的文化与当前的文化相匹配
Windows 文化,CultureInfo
使用这些覆盖,包括用户
的属性设置
返回 DateTimeFormatInfo 实例
通过 DateTimeFormat 属性,以及
NumberFormatInfo 的属性
NumberFormat 返回的实例
财产。如果用户设置是
与文化不相容
与 CultureInfo 相关联,对于
例如,如果所选日历是
不是可选日历之一,
方法的结果和值
的属性未定义。

DateTimeFormat 的值
属性和 NumberFormat 属性
直到您的
应用程序访问该属性。如果
用户可以改变当前
文化转变为新文化,同时
应用程序正在运行,然后
应用程序访问
日期时间格式或数字格式
属性,应用程序检索
新文化的默认设置
而不是覆盖
原始文化。为了保存
覆盖原始电流
文化,应用程序应该访问
日期时间格式和数字格式
更改当前属性之前
文化。”

可能是某些用户设置覆盖了这一点?

What's the value of the CultureInfo.DateTimeFormat property? According to MSDN:

"The user might choose to override
some of the values associated with the
current culture of Windows through the
regional and language options portion
of Control Panel. For example, the
user might choose to display the date
in a different format or to use a
currency other than the default for
the culture.

If UseUserOverride is true and the
specified culture matches the current
culture of Windows, the CultureInfo
uses those overrides, including user
settings for the properties of the
DateTimeFormatInfo instance returned
by the DateTimeFormat property, and
the properties of the NumberFormatInfo
instance returned by the NumberFormat
property. If the user settings are
incompatible with the culture
associated with the CultureInfo, for
example, if the selected calendar is
not one of the OptionalCalendars, the
results of the methods and the values
of the properties are undefined.

The value of the DateTimeFormat
property and the NumberFormat property
is not calculated until your
application accesses the property. If
the user can change the current
culture to a new culture while the
application is running and then the
application accesses the
DateTimeFormat or NumberFormat
property, the application retrieves
the defaults for the new culture
instead of the overrides for the
original culture. To preserve the
overrides for the original current
culture, the application should access
the DateTimeFormat and NumberFormat
properties before changing the current
culture."

Could it be some user setting is over-riding this?

甜妞爱困 2024-08-15 05:16:35

这是一个疯狂的猜测,但也许像这样的事件序列可能导致了问题:

  1. 管理员进入所有服务器上的控制面板国际设置并将时间格式从“HH:mm:ss”更改为“hh:mm:ss” tt”。
  2. 管理员仅在其中一台服务器上回收应用程序池(或IIS服务,或机器)。

回收的服务器上的所有新 ASP.NET 工作线程现在都将看到更改后的时间格式,并且它们的 DateTime.Parse 方法将失败。但是,如果其他服务器仍在使用原始工作线程,则它们尚未检测到当前区域性 DateTimeFormatInfo 的更改。

这是一种非常不可能的情况,但话又说回来,你遇到了一种非常不可能的情况。您可以尝试回收所有服务器上的相关应用程序池,看看是否有任何变化。

It's a wild guess, but maybe something like this sequence of events might have caused the problem:

  1. An administrator goes into Control Panel International settings on all servers and changes the time format from "HH:mm:ss" to "hh:mm:ss tt".
  2. The administrator recycles the application pool (or the IIS service, or the machine) on only one of the servers.

All new ASP.NET worker threads on the recycled server will now see the changed time format and their DateTime.Parse methods will fail. However, if the other servers are still using the original worker threads, then they have not yet detected the changes to the current culture DateTimeFormatInfo.

It's a very unlikely scenario, but then again, you have a very unlikely situation. You could try recycling the relevant application pool on all the servers and see if anything changes.

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