代码之家  ›  专栏  ›  技术社区  ›  Samuel Neff

Convert.ToDateTime导致下午日期/时间值发生FormatException

  •  11
  • Samuel Neff  · 技术社区  · 15 年前

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

    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”,我在区域或语言设置中找不到任何不同之处。

    编辑:谢谢你迄今为止的答案。然而,我正在寻找建议,看看什么配置可能导致它突然改变行为并停止工作,当它工作多年并在数百台其他服务器上工作时。我已经在下一个版本中对其进行了更改,但我正在寻找一个配置更改,以便在当前安装的过渡期间修复此问题。

    8 回复  |  直到 15 年前
        1
  •  3
  •   Nemesh    15 年前

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

        2
  •  7
  •   Jon Skeet    15 年前

    如果您确切知道格式,请告诉应用程序它是什么-使用 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);
        }
    }
    
        3
  •  3
  •   Brian Begley    15 年前

    我们有一个运行在Windows2003服务器上的C#.NET2.0Web服务。这项服务已经运行了两年多。我们最近开始在该应用程序中遇到错误。错误消息为“字符串未被识别为有效的日期时间”。另一个web服务返回一个日期,该函数应该返回如下值

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

    不正确的返回值在末尾有空格,并且没有AM。

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

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

    而不是

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

    我们还检查了文化设置。

    很明显,问题是从应用程序池回收开始的,但我不知道在回收过程中会发生什么。大多数时候,回收没有负面影响,当错误确实发生时,下一次回收总是停止错误。

        4
  •  2
  •   Henk Holterman    15 年前

    CultureInfo.InvariantCulture . 对于示例数据,这是唯一明智的做法。

    我知道这并不能解释差异,但你的软件确实不应该依赖“默认”文化(除了UI)。

        5
  •  1
  •   Paul Williams    12 年前

    我刚刚找到了一些导致此问题的信息。我们的C#客户端将业务日期(仅日期)作为字符串值发送给web服务。web服务将SqlParameter中的该字符串传递给SqlCommand,并将其传递给接受 datetime 业务日期的参数。

    WAITFOR DELAY '00:01:00' . 然后,当web服务调用此存储过程时,我获取了它的内存转储。

    检查内存转储时,我发现客户端在参数数据集中传入了正确的日期字符串“2012-10-25 00:00:00”。web服务调用存储过程时,不知怎的把这些日期的转换搞砸了。我在转储中找到了SqlCommand,并检查了与存储过程的日期参数相对应的SqlParameter。该值为“2012年10月25日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()
    

    // 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 . 链接的文章说它只适用于WindowsServer2003,并且有一个可用的修补程序。

        6
  •  0
  •   Christopher Nobles    15 年前

    听起来文化对象似乎不理解军事时间符号。老实说,我不确定从那里走到哪里,但这可能会给你一个起点。

        7
  •  0
  •   Dan Diplo    15 年前

    这本书的价值是什么 CultureInfo.DateTimeFormat According to MSDN :

    与 通过Windows的当前文化 控制面板的安装。例如 以不同的格式或使用 默认值以外的货币 文化。

    指定的区域性与当前 Windows的文化性,文化信息 属性的设置 已返回DateTimeFormatInfo实例 NumberFormatInfo的性质 财产。如果用户设置为 与CultureInfo关联,例如 没有一个可选日历 方法和数值的结果

    DateTimeFormat的值 属性和NumberFormat属性 直到您的 用户可以更改当前设置 应用程序正在运行,然后 应用程序访问 DateTimeFormat或NumberFormat 新文化的默认设置 而不是 原始文化。保存 原始当前文件的覆盖 DateTimeFormat和NumberFormat 属性,然后再更改当前 文化。”

    可能是因为某些用户设置超越了这一点?

        8
  •  0
  •   Christian Hayter    15 年前

    这是一个大胆的猜测,但可能是类似这一系列事件造成了问题:

    1. 管理员仅在其中一台服务器上回收应用程序池(或IIS服务或计算机)。

    回收服务器上的所有新ASP.NET工作线程现在都将看到更改的时间格式及其 DateTime.Parse DateTimeFormatInfo .

    这是一个非常不可能的情况,但同样,你有一个非常不可能的情况。您可以尝试在所有服务器上回收相关的应用程序池,看看是否有任何变化。