Home > OS >  In Blazor WebAssembly in a component, how can I make DateTime.ToString use the date format of the cu
In Blazor WebAssembly in a component, how can I make DateTime.ToString use the date format of the cu

Time:10-13

I have temporarily set my browser language and locale to English - United Kingdom even though I am in the United States. I have removed "en-US" and now have "en-GB" as my only language preference.

In my Blazor WebAssembly site, on a component, I have a property that returns a string: myDate.ToString("d") System.Globalization.CultureInfo.CurrentCulture.DisplayName; that renders on my page as 6/27/2020en (GB), where myDate is a DateTime set to June 27, 2020 at 00:00:00.000. My Blazor site has app.UseRequestLocalization(...) middleware set up.

Isn't is supposed to show the date in UK format, namely 27/06/2020? I can only guess that ShortDatePattern isn't getting properly set from CultureInfo.CurrentCulture. What could it be?

UPDATE: All WebAssembly component outputs show me that DateTimeFormatInfo.CurrentInfo.ShortDatePattern == "M/d/yyyy" even though CultureInfo.CurrentCulture.Name == "en-GB". Why might that be? What sets ShortDatePattern from the culture and can I "re-initialize" it?

An explicit call to myDate.ToString("d", System.Globalization.CultureInfo.GetCultureInfo("en-GB")); still strangely outputs the M/d/yyyy format (U.S. format). Why might that be?

UPDATE 2: I created a minimal example: File-New Project, Blazor Web Assembly, .NET 5 ASP.NET Core hosted. I replaced App.Razor with the following:

<div> current culture @(System.Globalization.CultureInfo.CurrentCulture.Name) </div>
<div> current date format @(System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern) </div>
<div> today @DateTime.Now.ToString("d") </div>

That results in (unexpectedly):

enter image description here

Firefox browser settings (Edge and Chrome are similar and show the same issue):

enter image description here

That results in sending Accept-Language: en-GB,en-US;q=0.7,en;q=0.3--which seems to be the correct way to "prefer en-GB" and results in CultureInfo.CurrentCulture having the correct value.

I've tried it with Microsoft.AspNetCore.Components.WebAssembly.* nuget packages version 5.0.9, 5.0.11 - both show the same incorrect result.

UPDATE 3: The same minimal project in 6.0.0-rc.1 works and gives the right date format! Is this really a Blazor 5 bug that they never fixed?

CodePudding user response:

I could not find the root cause, so I needed to code this workaround, which needs to be called explicitly when needed. Obviously this is undesirable if we can find a better solution to allow the use of DateTime.ToString as intended.

/// <summary>
/// Returns a short date-only string from a date/time value, based on the user's current culture.
/// </summary>
public static string ToLocalShortDate(this DateTime value)
{
    // this is needed because I can't get localization to work -- see https://stackoverflow.com/q/69542125/7453
    //   (if we can fix, better to use DateTime.ToString("d"))

    string format;
    // countries taken from https://en.wikipedia.org/wiki/Date_format_by_country
    if (CurrentCulture.Name.EndsWithAny("US", "CA", "ZA", "KE", "GH", "en"))
        format = "MM/dd/yyyy";
    else if (CurrentCulture.Name.EndsWithAny("CN", "JP", "KR", "KP", "TW", "HU", "MN", "LT", "BT"))
        format = "yyyy-MM-dd";
    else format = "dd/MM/yyyy";

    return value.ToString(format);
}
        
/// <summary>
/// Returns true if and only if a string ends with any of some strings.
/// The value will not match a null reference.
/// </summary>
public static bool EndsWithAny(this string value, params string[] allowedValues) =>
    allowedValues != null && value != null && allowedValues.Any(s => CurrentCulture.Name.EndsWith(s));

CodePudding user response:

No repro.

I used the below code in both .net5 and .net6 preview and in both versions the output is correctly determined by the top language set in the browser (I used Chrome, Firefox and Edge).

<p>@theData</p>

@code
{
   string theData => $"{DateTime.Now} {System.Globalization.CultureInfo.CurrentCulture.DisplayName}";
}

So, if you still have a problem: create a mre. Something else might be going on.

  • Related