Search code examples
c#.netdatetimestring-formatting.net-8.0

Date formatting the month abbreviation behaves differently between .NET Framework 4.8 and .NET 8


This code behaves differently between .NET Framework 4.8 and .NET 5, 6, 7, 8

Console.WriteLine("CurrentCulture is {0}.", CultureInfo.CurrentCulture.Name);
Console.WriteLine("CurrentUICulture is {0}.", CultureInfo.CurrentUICulture.Name);
var date = new DateTime(2020, 1, 15);
for (int i = 0; i < 12; i++)
{
    Console.Write("{0}    ", date.ToString("MMM"));
    Console.WriteLine("{0}", date.ToString("d-MMM-yyyy"));
    date = date.AddMonths(1);
}

In .net framework 4.8 the output is

CurrentCulture is en-AU.
CurrentUICulture is en-US.
Jan    15-Jan-2020
Feb    15-Feb-2020
Mar    15-Mar-2020
Apr    15-Apr-2020
May    15-May-2020
Jun    15-Jun-2020
Jul    15-Jul-2020
Aug    15-Aug-2020
Sep    15-Sep-2020
Oct    15-Oct-2020
Nov    15-Nov-2020
Dec    15-Dec-2020

In .NET 5, 6, 7 & 8 I get this output:

CurrentCulture is en-AU.
CurrentUICulture is en-US.
Jan    15-Jan-2020
Feb    15-Feb-2020
Mar    15-Mar-2020
Apr    15-Apr-2020
May    15-May-2020
Jun    15-June-2020
Jul    15-July-2020
Aug    15-Aug-2020
Sep    15-Sept-2020
Oct    15-Oct-2020
Nov    15-Nov-2020
Dec    15-Dec-2020

Notice how June and July & September now give me a 4 letter abbreviation, but only when the date format string has the day and year. When I display the month on it's own I get the same behaviour between .NET Fx and .NET Core.

Does anyone know if this is intended? Is there a way to get consistent behaviour between .NET 4.8 and .NET 8?


Solution

  • .NET 5 has a breaking change - Globalization APIs use ICU libraries on Windows 10:

    Starting in .NET 5, if an app is running on Windows 10 May 2019 Update or later, .NET libraries use ICU globalization APIs, by default.

    Reason for change

    This change was introduced to unify .NET's globalization behavior across all supported operating systems. It also provides the ability for applications to bundle their own globalization libraries rather than depend on the operating system's built-in libraries.

    Which has affected globalization and culture-sensitive APIs.

    If you switch back to NLS you should get the desired output. For example by adding the following to .csproj:

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

    I would guess names come from this part of ICU

    See also: