DateTime.Parse的奇怪行为

5
我们有一个庞大的应用程序,不幸的是,它经常使用DateTime.Parse(text)。目前无法将DateTime.Parse替换为更好的选项。
最近我升级了Windows(到Windows 10),并开始遇到问题。根据https://msdn.microsoft.com/en-us/library/system.datetime.parse(v=vs.110).aspx上的文档,该方法应该使用CultureInfo.CurrentCulture作为默认格式提供程序。除非我漏掉了什么明显的东西,否则在我的电脑上似乎不是这种情况。
以下代码两次调用一个函数,第一次不更改任何区域设置,然后在区域设置和ui-culture上都设置了挪威文化。出于某种原因,它能够解析以en-US格式(M/d/yyyy)给出的文本,在两种情况下均可行,但无法解析CultureInfo期望的格式的日期。
这是怎么回事?我希望我漏掉了一些明显的东西...
class Program
{
    static void Main(string[] args)
    {
        var norwegianCulture = new CultureInfo("nb-NO");

        Console.WriteLine("First");
        ParseDates();

        Console.WriteLine("\nSecond");
        Thread.CurrentThread.CurrentUICulture = norwegianCulture;
        ParseDates();

        Console.ReadKey();
    }

    private static void ParseDates()
    {
        Console.WriteLine($"CultureInfo.CurrentCulture: {CultureInfo.CurrentCulture}");
        Console.WriteLine($"CultureInfo.CurrentUICulture: {CultureInfo.CurrentUICulture}");
        Console.WriteLine($"{Thread.CurrentThread.CurrentCulture} - CurrentCulture - {Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern}");
        Console.WriteLine($"{Thread.CurrentThread.CurrentUICulture} - CurrentUICulture - {Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern}");
        var shortDateString = new DateTime(2015, 9, 5).ToShortDateString();
        WriteParsedDate(shortDateString);
        WriteParsedDate("1/2/2015");
        Console.WriteLine();
    }

    private static void WriteParsedDate(string shortDateString)
    {
        try
        {
            var d = DateTime.Parse(shortDateString, CultureInfo.CurrentCulture);
            Console.WriteLine($"The text {shortDateString} parsed to Year: {d.Year}, Month: {d.Month}, Day: {d.Day}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"The text {shortDateString} could not be parsed.");
            Console.WriteLine($"Error: {e.Message}");
        }
    }
}

将以下内容输出到控制台:

First
CultureInfo.CurrentCulture: nb-NO
CultureInfo.CurrentUICulture: en-US
nb-NO - CurrentCulture - dd.MM.yyyy
en-US - CurrentUICulture - M/d/yyyy
The text 05.09.2015 could not be parsed.
Error: String was not recognized as a valid DateTime.
The text 1/2/2015 parsed to Year: 2015, Month: 2, Day: 1


Second
CultureInfo.CurrentCulture: nb-NO
CultureInfo.CurrentUICulture: nb-NO
nb-NO - CurrentCulture - dd.MM.yyyy
nb-NO - CurrentUICulture - dd.MM.yyyy
The text 05.09.2015 could not be parsed.
Error: Strengen ble ikke gjenkjent som en gyldig DateTime.
The text 1/2/2015 parsed to Year: 2015, Month: 2, Day: 1

部分解决方案

正如shf301所写,这是由于Windows 10中的一个错误导致的。

我成功地使它工作了,通过将时间分隔符从“.”更改为“:” - 就像在早期版本的Windows中一样。我猜这个更改有效是因为我们只使用用户设置,而不是手动加载/指定它们。


这似乎也不是使用en-US,因为如果是的话,月份应该是1,日期是2,但你得到的结果恰好相反。 - jmcilhinney
1个回答

4
这是一个Connect上列出的公开漏洞。看起来日期解析在具有相同日期和时间分隔符的任何区域设置中都会失败。
Estonian (Estonia)
Finnish (Finland)
Norwegian Bokmål (Norway)
Norwegian Bokmål (Svalbard and Jan Mayen)
Serbian (Cyrillic, Kosovo)
Serbian (Latin, Montenegro)
Serbian (Latin, Serbia)
Serbian (Latin, Kosovo)

你的示例从未使用美国设置解析或格式化日期。首先,没有指定 IFormatProvider 的 DateTime.Parse 使用 CurrentCulture 而不是 CurrentUICulture,其次,你明确将 CurrentCulture 传递到 DateTime.Parse 中。这就是为什么两种情况下的输出完全相同的原因。
如果使用 en-US 规则解析 "1/2/2015",则会输出:
The text 1/2/2015 parsed to Year: 2015, Month: 1, Day: 2

DateTime.Parse很聪明,它假设您使用/作为日期分隔符而不是.,并将日期解析为d/M/yyyy

在此得到修复之前,您不幸地必须更改对DateTime.Parse的调用。或者切换到未受影响的.NET 3.5或更早版本。


1
谢谢!我真的希望这个问题能够尽快解决,因为现在它阻止了我们所有其他开发人员升级Windows。 - Steinar Herland
2
根据以下帖子,修复将在九月的Windows 10更新中发布:http://www.heikniemi.net/hardcoded/2015/08/windows-10-breaks-net-date-parsing-in-certain-locales/ - shf301
昨天的更新(https://support.microsoft.com/en-us/kb/3081455)对我来说并没有解决这个问题。 - Steinar Herland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接