我们有一个应用程序以下列格式解析日期/时间值:
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”,并且在区域或语言设置中没有什么不同。
有没有人见过这个?有关我可以研究的建议?
编辑:谢谢你到目前为止的答案。但是,我正在寻找有关可能导致这种情况突然改变行为并在其工作多年并在数百个其他服务器上工作时停止工作的配置的建议。我已经为下一个版本更改了它,但我正在寻找配置更改以在当前安装的临时期间修复此问题。答案 0 :(得分:7)
如果您完全了解格式,请告诉应用程序它是什么 - 使用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);
}
}
答案 1 :(得分:3)
我们也遇到了同样的问题。只需回收您的应用程序池。
答案 2 :(得分:3)
我们在Windows 2003服务器上运行了一个C#.NET 2.0 Web服务。该服务已经运行了两年多。我们最近在该应用程序中遇到了错误。错误消息是“字符串未被识别为有效的DateTime”。另一个Web服务返回一个日期,该函数应该返回一个像
这样的值“5/10/2010 12:00:00 AM”
当错误发生时,函数返回
“5/10/2010 12:00:00”
错误的返回结尾有空格,没有AM。
这个问题在接下来的几周内出现并消失了好几次。在检查了Windows日志之后,我们注意到错误的开始和结束时间与应用程序池回收一致(在一两分钟内)(默认情况下)设置为每29小时一次。此问题仅发生在生产Web服务器上,而不是在开发或测试服务器上。我们尝试更换服务器,一个月没有错误。现在错误再次开始。我们手动重置池,问题立即消失。我们宁愿不将此视为可接受的解决方案,因为游泳池会定期回收。我们不知道我们是否需要池回收,但我们的理解是定期回收有助于应用程序性能。
Web应用程序已使用ParseExact(),但格式字符串如下所示:
“YYYY-MM-ddHH:MM:ss.0Z”
而不是
“yyyy-MM-dd HH:mm:ss”
我们还检查了文化设置。
似乎很明显问题始于应用程序池回收,但我不知道在回收期间发生了什么。大多数情况下,回收没有负面影响,当错误发生时,下一次回收总是停止错误。
答案 3 :(得分:2)
解决方案非常简单,使用CultureInfo.InvariantCulture
。对于样本数据来说,这是唯一明智的做法。
我知道这并没有解释其中的区别,但是你的软件真的不应该依赖于'默认'文化(除了可能在UI中)。
答案 4 :(得分:1)
我刚刚找到了一些有关导致此问题的原因的信息。我们的C#客户端将业务日期(仅限日期)作为字符串值发送到Web服务。 Web服务将SqlParameter中的此字符串传递给SqlCommand,并将其传递给接受业务日期datetime
参数的存储过程。
客户的系统突然行为不端。我使用SQL Server Profiler来监视RPC调用,并注意到date参数突然有一个时间组件。这应该是仅限日期的值 - 即10/27/2012 12:00:00 AM。
我修改了存储过程以添加WAITFOR DELAY '00:01:00'
。然后,我在调用此存储过程时获取了Web服务的内存转储。
检查内存转储,我发现客户端在参数的DataSet中传递了正确的日期字符串“2012-10-25 00:00:00”。 Web服务在调用存储过程时以某种方式搞砸了这些日期的转换。我在转储中找到了SqlCommand并检查了与存储过程的date参数对应的SqlParameter。该值为“10/25/2012 12:00:00 PM”。
查看所有CultureInfo对象,我发现“en-US”的语言环境1033有一段很长的字符串“h:mm:ss tt”。 AMD签名者是“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 is aware of this issue。链接的文章说它仅适用于Windows Server 2003,并且有一个可用的修补程序。
答案 5 :(得分:0)
听起来好像文化对象不理解军事时间符号。老实说,我不确定从哪里开始,但它可能会给你一个起点。
答案 6 :(得分:0)
CultureInfo.DateTimeFormat
属性的价值是多少? According to MSDN:
“用户可能会选择覆盖 一些与之相关的价值观 当前的Windows文化通过 区域和语言选择部分 控制面板。例如, 用户可能会选择显示日期 以不同的格式或使用 除默认值以外的货币 文化。
如果UseUserOverride为true且为 指定的文化符合当前 Windows文化,CultureInfo 使用那些覆盖,包括用户 设置的属性 返回DateTimeFormatInfo实例 通过DateTimeFormat属性,和 NumberFormatInfo的属性 NumberFormat返回的实例 属性。如果用户设置是 与文化不相容 与CultureInfo相关联的 例如,如果选择的日历是 不是OptionalCalendars之一 方法和值的结果 属性未定义。
DateTimeFormat的值 property和NumberFormat属性 直到你的 应用程序访问该属性。如果 用户可以改变当前 文化到新文化的同时 应用程序正在运行然后 应用程序访问 DateTimeFormat或NumberFormat 属性,应用程序检索 新文化的默认值 而不是覆盖 原始文化。为了保护 覆盖原始电流 文化,应用程序应该访问 DateTimeFormat和NumberFormat 改变当前的属性 培养物“。
可能是某些用户设置超出了这个范围吗?
答案 7 :(得分:0)
这是一个疯狂的猜测,但也许像这一系列事件可能导致了这个问题:
回收服务器上的所有新ASP.NET工作线程现在都会看到更改的时间格式,并且它们的DateTime.Parse
方法将失败。但是,如果其他服务器仍在使用原始工作线程,则它们尚未检测到对当前区域DateTimeFormatInfo
的更改。
这是一个非常不可能的情况,但话又说回来,你的情况非常不可能。您可以尝试在所有服务器上回收相关的应用程序池,看看是否有任何更改。