Search code examples
c#androidunity-game-enginemonocultureinfo

DateTimeFormatInfo.DayNames returns extra, empty, day name on Android


I got the following list of cultures that I want to get the day names of, in their respective language

CultureInfo[] newCultures = {new CultureInfo("de-DE"),
                             new CultureInfo("en-US"),
                             new CultureInfo("en-GB"),
                             new CultureInfo("es-ES"),
                             new CultureInfo("fr-FR"),
                             new CultureInfo("nl-NL")};

I loop through all of their DateTimeFormat.DayNames and print them out

foreach (CultureInfo culture in newCultures)
{
   foreach (string day in culture.DateTimeFormat.DayNames)
   {
       Debug.Log(culture.Name + ": " + day);
   }
   Debug.Log("----------------");
}

When running this in the editor on Windows 10 with Unity 2019.1.8f1, Mono .NET 4.x runtime equivalent, with IL2CPP scripting backend it performs as expected and prints all the day names from sun -> sat (inclusive) in the console.

Things start to get messy when I build for Android though.

When running the exact same code on Android (tested on both Android 7.0 and Android 9.0) results are different though.

Instead of just printing the days sun -> sat (inclusive) it has an 8th entry for every language. That is empty.

en-GB: Sunday
en-GB: Monday
en-GB: Tuesday
en-GB: Wednesday
en-GB: Thursday
en-GB: Friday
en-GB: Saturday
en-GB: <blank>

I tried this with a bunch of language (de-DE, en-US, en-EN, es-ES, fr-FR, nl-NL) and they all produced an 8th empty day.

However it doesn't just end there. When I loop through CultureInfo.CurrentCulture instead, the eight day isn't there.

foreach (string day in CultureInfo.CurrentCulture.DateTimeFormat.DayNames)
{
   Debug.Log(CultureInfo.CurrentCulture.Name + ": " + day);
}
//Results
//en-GB: Sunday
//en-GB: Monday
//en-GB: Tuesday
//en-GB: Wednesday
//en-GB: Thursday
//en-GB: Friday
//en-GB: Saturday

Alternatively to using new CultureInfo I tried it using CultureInfo.CreateSpecificCulture instead, but this yielded the same results of having an extra 8th, empty day.

CultureInfo[] createCultures = {CultureInfo.CreateSpecificCulture("de-DE"),
                                CultureInfo.CreateSpecificCulture("en-US"),
                                CultureInfo.CreateSpecificCulture("en-GB"),
                                CultureInfo.CreateSpecificCulture("es-ES"),
                                CultureInfo.CreateSpecificCulture("fr-FR"),
                                CultureInfo.CreateSpecificCulture("nl-NL")};

foreach (CultureInfo culture in createCultures)
{
    foreach (string day in culture.DateTimeFormat.DayNames)
    {
        Debug.Log(culture.Name + ": " + day);
    }
    Debug.Log("----------------");
}

is this expected behaviour? if so why is this 8th empty day there? and is there a way to not include that day without having to remove it afterward?

It seems to be a problem that only occurs with Unity in combination with Android (or the specific version of Mono Unity uses, but I couldn't determine which version exactly they use, and think it is a modified version).


I build a new empty Xamarin for Android application in Visual studio, which didn't have the issue (mono version: --version Mono JIT compiler version 5.18.0 (Visual Studio built mono))

MainActivity.cs:

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
    CultureInfo[] newCultures = {new CultureInfo("de-DE"),
                                 new CultureInfo("en-US"),
                                 new CultureInfo("en-GB"),
                                 new CultureInfo("es-ES"),
                                 new CultureInfo("fr-FR"),
                                 new CultureInfo("nl-NL")};

    List<string> results = new List<string>();

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.activity_main);

        TextView text;

        text = FindViewById<TextView>(Resource.Id.textView1);

        foreach (CultureInfo culture in newCultures)
        {
            foreach (string day in culture.DateTimeFormat.DayNames)
            {
                results.Add(culture.Name + ": " + day + "\n");
                text.Text += culture.Name + ": " + day + "\n";
            }
            text.Text += "--------\n";
        }

        //text.Text = results.;

    }
}

Activity_main.axml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:text="Text"
        android:textSize="5sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minWidth="25px"
        android:minHeight="25px"
        android:id="@+id/textView1" />
</LinearLayout>

Solution

  • It appears to be a bug in the IL2CPP scripting backend of Unity 2019.x (Tested on 2019.1.8 and 2019.2.5). Setting scripting backend back to Mono fixes the issue. I will be making a bug report out of it.

    The bug does not limit itself to just Android and weekdays. When trying to get the names of the months this will also include the empty entry at the end, resulting in a year having 13 months. When using months Windows builds are also affected, as well as at the CurrentCulture.

    Weirdly enough weekdays do not show this behaviour on windows or when using CurrentCulture.

    The abbreviated versions behave the same way as their non-abbreviated versions.

    Made a showcase repo for it here