为什么 "DateTime.Now.ToString("hh tt", new CultureInfo("de"))" return 在不同版本的 .Net 中有不同的结果?

Why does "DateTime.Now.ToString("hh tt", new CultureInfo("de"))" return different results in different versions of .Net?

我很困惑。在读到 this answer 我们应该依赖内置本地化后,我对以下观察结果感到惊讶:

当我运行

using System;
using System.Globalization;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine(DateTime.Now.ToString("hh tt", new CultureInfo("de")));
    }
}

根据框架 and/or 编译器,我得到的结果非常不同。示例基于 10:00 UTC(上午 10 点)。

现在是有趣的部分:

它变得更奇怪了:我已经在本地使用控制台应用程序进行了尝试,并将示例扩展为

Console.WriteLine(DateTime.Now.ToString("hh tt", new CultureInfo("de")));
Console.WriteLine(DateTime.Now.ToString("hh tt", new CultureInfo("de-DE")));
Console.WriteLine(DateTime.Now.ToString("hh tt", new CultureInfo("fr")));

这些是结果 - 添加了 try-dotnet 以进行比较。

Culture .NET 5 .NET Core 3.1 .NET Core 2.0 .NET Framework 4.8 Mono try-dotnet
"de" 10 AM 10 10 10 10 vorm. 10 vorm.
"de-DE" 10 10 10 10 10 vorm. 10 vorm.
"fr" 10 AM 10 10 10 10 AM 10 AM

在 Mono 列中,结果来自使用 Mono 编译文件(Mono JIT 编译器版本 6.4.0),然后使用 Mono 运行编译它。 运行 没有 Mono 的 .exe 产生与第三列相同的结果。

这是从哪里来的,是编译器还是框架中的错误?它只是坏了还是故意设计的?

此重大更改是 the use of the ICU Libraries on Windows instead of the NLS Libraries 的结果。

您可以在 .net 5.0 应用程序中验证这一点,方法是将以下内容添加到项目中以从使用 ICU 库恢复为使用 NLS 库:

<ItemGroup>
    <RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" />
</ItemGroup>

在使用代码

将其添加到我的测试 .Net 5.0 控制台应用程序之后
Console.WriteLine(DateTime.Now.ToString("hh tt", new CultureInfo("de")));

输出从 11 AM 变为 11(在撰写本文时)。

See here for more details.