Skip to content

Commit

Permalink
[Apple-Mobile][Globalization] Refactoring of CalendarData.iOS and new…
Browse files Browse the repository at this point in the history
… DateTimeFormatInfo* tests (#102464)

* enable ShortDatePattern tests + refactor

* LongDatePattern correct format

* LongDatePattern tests

* fix EnumDatePatterns AddRange for Apple Hybrid

* remove duplicate invariant ShorDatePattern test

* remove duplicate en-US LongDatePattern case

* MonthDayPattern test cases

* add _ICU suffix to DatePattern names

* DayNames ICU test cases

* AbbreviatedDayNames ICU tests

* Move GetCalendarInfoNative to EnumCalendarInfo ICU

* MonthNames test suit for ICU

* AbbreviatedMonthGenitiveNames ICU test suit

* AbbreviatedMonthNames ICU test suit

* MonthGenitive ICU test suit

* refactor CalendarData.iOS.cs
to use more of the shared CalendarData.ICU code

* refactor new DateTiemFormatInfo* API tests
  • Loading branch information
matouskozak committed Jul 12, 2024
1 parent c09ec65 commit 42b2b19
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,12 @@ internal static unsafe bool EnumCalendarInfo(string localeName, CalendarId calen
#pragma warning disable CS8500 // takes address of managed type
private static unsafe bool EnumCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, IcuEnumCalendarsData* callbackContext)
{
#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS
callbackContext->Results.AddRange(GetCalendarInfoNative(localeName, calendarId, dataType).Split("||"));
return callbackContext->Results.Count > 0;
#else
return Interop.Globalization.EnumCalendarInfo(&EnumCalendarInfoCallback, localeName, calendarId, dataType, (IntPtr)callbackContext);
#endif
}
#pragma warning restore CS8500

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,15 @@ private bool LoadCalendarDataFromNative(string localeName, CalendarId calendarId

sNativeName = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.NativeName);
sMonthDay = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.MonthDay);
saShortDates = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.ShortDates).Split("||");
// Handle ShortDatePattern to have "yyyy" year format
List<string> shortDatePatternList = new List<string>(saShortDates);
for (int i = 0; i < shortDatePatternList.Count; i++)
{
shortDatePatternList[i] = NormalizeDatePattern(shortDatePatternList[i]);
}
FixDefaultShortDatePattern(shortDatePatternList);
saShortDates = shortDatePatternList.ToArray();

saLongDates = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.LongDates).Split("||");
saYearMonths = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.YearMonths).Split("||");
saDayNames = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.DayNames).Split("||");
saAbbrevDayNames = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.AbbrevDayNames).Split("||");
saSuperShortDayNames = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.SuperShortDayNames).Split("||");
EnumDatePatterns(localeName, calendarId, CalendarDataType.ShortDates, out this.saShortDates!);
EnumDatePatterns(localeName, calendarId, CalendarDataType.LongDates, out this.saLongDates!);
EnumDatePatterns(localeName, calendarId, CalendarDataType.YearMonths, out this.saYearMonths!);
EnumCalendarInfo(localeName, calendarId, CalendarDataType.DayNames, out this.saDayNames!);
EnumCalendarInfo(localeName, calendarId, CalendarDataType.AbbrevDayNames, out this.saAbbrevDayNames!);
EnumCalendarInfo(localeName, calendarId, CalendarDataType.SuperShortDayNames, out this.saSuperShortDayNames!);

string? leapHebrewMonthName = null;
saMonthNames = NormalizeMonthArray(GetCalendarInfoNative(localeName, calendarId, CalendarDataType.MonthNames).Split("||"), calendarId, ref leapHebrewMonthName);
EnumMonthNames(localeName, calendarId, CalendarDataType.MonthNames, out this.saMonthNames!, ref leapHebrewMonthName);
if (leapHebrewMonthName != null)
{
Debug.Assert(saMonthNames != null);
Expand All @@ -51,62 +42,19 @@ private bool LoadCalendarDataFromNative(string localeName, CalendarId calendarId
saMonthNames[6] = leapHebrewMonthName;

}
saAbbrevMonthNames = NormalizeMonthArray(GetCalendarInfoNative(localeName, calendarId, CalendarDataType.AbbrevMonthNames).Split("||"), calendarId, ref leapHebrewMonthName);
saMonthGenitiveNames = NormalizeMonthArray(GetCalendarInfoNative(localeName, calendarId, CalendarDataType.MonthGenitiveNames).Split("||"), calendarId, ref leapHebrewMonthName);
saAbbrevMonthGenitiveNames = NormalizeMonthArray(GetCalendarInfoNative(localeName, calendarId, CalendarDataType.AbbrevMonthGenitiveNames).Split("||"), calendarId, ref leapHebrewMonthName);
EnumMonthNames(localeName, calendarId, CalendarDataType.AbbrevMonthNames, out this.saAbbrevMonthNames!, ref leapHebrewMonthName);
EnumMonthNames(localeName, calendarId, CalendarDataType.MonthGenitiveNames, out this.saMonthGenitiveNames!, ref leapHebrewMonthName);
EnumMonthNames(localeName, calendarId, CalendarDataType.AbbrevMonthGenitiveNames, out this.saAbbrevMonthGenitiveNames!, ref leapHebrewMonthName);

saEraNames = NormalizeEraNames(calendarId, GetCalendarInfoNative(localeName, calendarId, CalendarDataType.EraNames).Split("||"));
saAbbrevEraNames = Array.Empty<string>();
EnumEraNames(localeName, calendarId, CalendarDataType.EraNames, out this.saEraNames!);
EnumEraNames(localeName, calendarId, CalendarDataType.AbbrevEraNames, out this.saAbbrevEraNames!);

return sNativeName != null && saShortDates != null && saLongDates != null && saYearMonths != null &&
saDayNames != null && saAbbrevDayNames != null && saSuperShortDayNames != null && saMonthNames != null &&
saAbbrevMonthNames != null && saMonthGenitiveNames != null && saAbbrevMonthGenitiveNames != null &&
saEraNames != null && saAbbrevEraNames != null;
}

private static string[] NormalizeEraNames(CalendarId calendarId, string[]? eraNames)
{
// .NET expects that only the Japanese calendars have more than 1 era.
// So for other calendars, only return the latest era.
if (calendarId != CalendarId.JAPAN && calendarId != CalendarId.JAPANESELUNISOLAR && eraNames?.Length > 0)
return new string[] { eraNames![eraNames.Length - 1] };

return eraNames ?? Array.Empty<string>();
}

private static string[] NormalizeMonthArray(string[] months, CalendarId calendarId, ref string? leapHebrewMonthName)
{
if (months.Length == 13)
return months;

string[] normalizedMonths = new string[13];
// the month-name arrays are expected to have 13 elements. If only returns 12, add an
// extra empty string to fill the array.
if (months.Length == 12)
{
normalizedMonths[12] = "";
months.CopyTo(normalizedMonths, 0);
return normalizedMonths;
}

if (months.Length > 13)
{
Debug.Assert(calendarId == CalendarId.HEBREW && months.Length == 14);

if (calendarId == CalendarId.HEBREW)
{
leapHebrewMonthName = months[13];
}
for (int i = 0; i < 13; i++)
{
normalizedMonths[i] = months[i];
}
return normalizedMonths;
}

throw new Exception("CalendarData.GetCalendarInfoNative() returned an unexpected number of month names.");
}

private static string GetCalendarInfoNative(string localeName, CalendarId calendarId, CalendarDataType calendarDataType)
{
Debug.Assert(localeName != null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public static IEnumerable<object[]> AbbreviatedDayNames_Set_TestData()
yield return new object[] { new string[] { "", "", "", "", "", "", "" } };
}

public static IEnumerable<object[]> AbbreviatedDayNames_Get_TestData_ICU()
{
yield return new object[] { CultureInfo.GetCultureInfo("en-US").DateTimeFormat, new string[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } };
yield return new object[] { CultureInfo.GetCultureInfo("fr-FR").DateTimeFormat, new string[] { "dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam." } };
}

public static IEnumerable<object[]> AbbreviatedDayNames_Get_TestData_HybridGlobalization()
{
// see the comments on the right to check the non-Hybrid result, if it differs
Expand Down Expand Up @@ -86,6 +92,13 @@ public static IEnumerable<object[]> AbbreviatedDayNames_Get_TestData_HybridGloba
yield return new object[] { "zh-CN", new string[] { "周日", "周一", "周二", "周三", "周四", "周五", "周六" } };
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))]
[MemberData(nameof(AbbreviatedDayNames_Get_TestData_ICU))]
public void AbbreviatedDayNames_Get_ReturnsExpected_ICU(DateTimeFormatInfo format, string[] expected)
{
Assert.Equal(expected, format.AbbreviatedDayNames);
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))]
[MemberData(nameof(AbbreviatedDayNames_Get_TestData_HybridGlobalization))]
public void AbbreviatedDayNames_Get_ReturnsExpected_HybridGlobalization(string cultureName, string[] expected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ namespace System.Globalization.Tests
{
public class DateTimeFormatInfoAbbreviatedMonthGenitiveNames
{
public static IEnumerable<object[]> AbbreviatedMonthGenitiveNames_Get_TestData_ICU()
{
yield return new object[] { CultureInfo.GetCultureInfo("en-US").DateTimeFormat, new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" } };
yield return new object[] { CultureInfo.GetCultureInfo("fr-FR").DateTimeFormat, new string[] { "janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc.", "" } };
}
public static IEnumerable<object[]> AbbreviatedMonthGenitiveNames_Get_TestData_HybridGlobalization()
{
// see the comments on the right to check the non-Hybrid result, if it differs
Expand Down Expand Up @@ -209,6 +214,13 @@ public static IEnumerable<object[]> AbbreviatedMonthGenitiveNames_Get_TestData_H
yield return new object[] { "zh-TW", new string[] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "" } };
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))]
[MemberData(nameof(AbbreviatedMonthGenitiveNames_Get_TestData_ICU))]
public void AbbreviatedMonthGenitiveNames_Get_ReturnsExpected_ICU(DateTimeFormatInfo format, string[] expected)
{
Assert.Equal(expected, format.AbbreviatedMonthGenitiveNames);
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))]
[MemberData(nameof(AbbreviatedMonthGenitiveNames_Get_TestData_HybridGlobalization))]
public void AbbreviatedMonthGenitiveNames_Get_ReturnsExpected_HybridGlobalization(string cultureName, string[] expected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ public static IEnumerable<object[]> AbbreviatedMonthNames_Set_TestData()
yield return new object[] { new string[] { "", "", "", "", "", "", "", "", "", "", "", "", "" } };
}

public static IEnumerable<object[]> AbbreviatedMonthNames_Get_TestData_ICU()
{
yield return new object[] { CultureInfo.GetCultureInfo("en-US").DateTimeFormat, new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" } };
yield return new object[] { CultureInfo.GetCultureInfo("fr-FR").DateTimeFormat, new string[] { "janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc.", "" } };
}


public static IEnumerable<object[]> AbbreviatedMonthNames_Get_TestData_HybridGlobalization()
{
// see the comments on the right to check the non-Hybrid result, if it differs
Expand Down Expand Up @@ -232,6 +239,13 @@ public static IEnumerable<object[]> AbbreviatedMonthNames_Get_TestData_HybridGlo
yield return new object[] { "zh-TW", new string[] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "" } };
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))]
[MemberData(nameof(AbbreviatedMonthNames_Get_TestData_ICU))]
public void AbbreviatedMonthNames_Get_ReturnsExpected_ICU(DateTimeFormatInfo format, string[] expected)
{
Assert.Equal(expected, format.AbbreviatedMonthNames);
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))]
[MemberData(nameof(AbbreviatedMonthNames_Get_TestData_HybridGlobalization))]
public void AbbreviatedMonthNames_Get_ReturnsExpected_HybridGlobalization(string cultureName, string[] expected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public static IEnumerable<object[]> DayNames_Set_TestData()
yield return new object[] { new string[] { "", "", "", "", "", "", "" } };
}

public static IEnumerable<object[]> DayNames_Get_TestData_ICU()
{
yield return new object[] { CultureInfo.GetCultureInfo("en-US").DateTimeFormat, new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } };
yield return new object[] { CultureInfo.GetCultureInfo("fr-FR").DateTimeFormat, new string[] { "dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi" } };
}

public static IEnumerable<object[]> DayNames_Get_TestData_HybridGlobalization()
{
yield return new object[] { "ar-SA", new string[] { "الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت" } };
Expand Down Expand Up @@ -78,6 +84,13 @@ public static IEnumerable<object[]> DayNames_Get_TestData_HybridGlobalization()
yield return new object[] { "zh-TW", new string[] { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" } };
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))]
[MemberData(nameof(DayNames_Get_TestData_ICU))]
public void DayNames_Get_ReturnsExpected_ICU(DateTimeFormatInfo format, string[] expected)
{
Assert.Equal(expected, format.DayNames);
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))]
[MemberData(nameof(DayNames_Get_TestData_HybridGlobalization))]
public void DayNames_Get_ReturnsExpected_HybridGlobalization(string cultureName, string[] expected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ public static IEnumerable<object[]> LongDatePattern_Set_TestData()
yield return new object[] { "dddd, dd MMMM yyyy" };
}

public static IEnumerable<object[]> LongDatePattern_Get_TestData_ICU()
{
yield return new object[] { CultureInfo.GetCultureInfo("en-US").DateTimeFormat, "dddd, MMMM d, yyyy" };
yield return new object[] { CultureInfo.GetCultureInfo("fr-FR").DateTimeFormat, "dddd d MMMM yyyy" };
}

public static IEnumerable<object[]> LongDatePattern_Get_TestData_HybridGlobalization()
{
// see the comments on the right to check the non-Hybrid result, if it differs
Expand Down Expand Up @@ -218,6 +224,13 @@ public static IEnumerable<object[]> LongDatePattern_Get_TestData_HybridGlobaliza
yield return new object[] {"zh-TW", "yyyy年M月d日 dddd" };
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))]
[MemberData(nameof(LongDatePattern_Get_TestData_ICU))]
public void LongDatePattern_Get_ReturnsExpected_ICU(DateTimeFormatInfo format, string expected)
{
Assert.Equal(expected, format.LongDatePattern);
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))]
[MemberData(nameof(LongDatePattern_Get_TestData_HybridGlobalization))]
public void LongDatePattern_Get_ReturnsExpected_HybridGlobalization(string cultureName, string expected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ public static IEnumerable<object[]> MonthDayPattern_Set_TestData()
yield return new object[] { "m" };
}

public static IEnumerable<object[]> MonthDayPattern_Get_TestData_ICU()
{
yield return new object[] { CultureInfo.GetCultureInfo("en-US").DateTimeFormat, "MMMM d" };
yield return new object[] { CultureInfo.GetCultureInfo("fr-FR").DateTimeFormat, "d MMMM" };
}

public static IEnumerable<object[]> MonthDayPattern_Get_TestData_HybridGlobalization()
{
// see the comments on the right to check the non-Hybrid result, if it differs
Expand Down Expand Up @@ -149,7 +155,6 @@ public static IEnumerable<object[]> MonthDayPattern_Get_TestData_HybridGlobaliza
yield return new object[] { new CultureInfo("en-ZA").DateTimeFormat, "d MMMM" };
yield return new object[] { new CultureInfo("en-ZM").DateTimeFormat, "d MMMM" };
yield return new object[] { new CultureInfo("en-ZW").DateTimeFormat, "d MMMM" };
yield return new object[] { new CultureInfo("en-US").DateTimeFormat, "MMMM d" };
yield return new object[] { new CultureInfo("es-419").DateTimeFormat, "d de MMMM" }; // d 'de' MMMM
yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, "d de MMMM" }; // d 'de' MMMM
yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, "d de MMMM" }; // d 'de' MMMM
Expand Down Expand Up @@ -216,6 +221,13 @@ public static IEnumerable<object[]> MonthDayPattern_Get_TestData_HybridGlobaliza
yield return new object[] { new CultureInfo("zh-HK").DateTimeFormat, "M月d日" };
yield return new object[] { new CultureInfo("zh-TW").DateTimeFormat, "M月d日" };
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))]
[MemberData(nameof(MonthDayPattern_Get_TestData_ICU))]
public void MonthDayPattern_Get_ReturnsExpected_ICU(DateTimeFormatInfo format, string expected)
{
Assert.Equal(expected, format.MonthDayPattern);
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))]
[MemberData(nameof(MonthDayPattern_Get_TestData_HybridGlobalization))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static IEnumerable<object[]> MonthGenitiveNames_Get_TestData()
yield return new object[] { DateTimeFormatInfo.InvariantInfo, new string[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" } };
yield return new object[]
{
new CultureInfo("ru-RU").DateTimeFormat,
CultureInfo.GetCultureInfo("ru-RU").DateTimeFormat,
new string[]
{
"\u044F\u043D\u0432\u0430\u0440\u044F",
Expand All @@ -31,6 +31,11 @@ public static IEnumerable<object[]> MonthGenitiveNames_Get_TestData()
""
}
};
if (PlatformDetection.IsIcuGlobalization)
{
yield return new object[] { CultureInfo.GetCultureInfo("en-US").DateTimeFormat, new string[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" } };
yield return new object[] { CultureInfo.GetCultureInfo("fr-FR").DateTimeFormat, new string[] { "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre", "" } };
}
if (PlatformDetection.IsHybridGlobalizationOnBrowser)
{
// see the comments on the right to check the non-Hybrid result, if it differs
Expand Down
Loading

0 comments on commit 42b2b19

Please sign in to comment.