Skip to content

Commit a9363bf

Browse files
authored
[browser][non-icu] HybridGlobalization calendar data (#89255)
* Calendar WIP. * Genitive months. * Short pattern. * NativeCalendarName does not exist on WebAPI - use EnglishCalendarName. * Fix failures in Locales caused by calendars data removal. * Fix to previous commit. * Whitespace. * Implemented Eras. * Populate NativeName with EnglishName. * Fix tests. * Typos + comments removal + block failing test. * AM/PM designators are not in ICU anymore. * ShortTimePattern is ready. * Fix some failing tests. * LongTimePatterns is ready. * Ask about all culture info from JS at once. * Fix remaining tests. * Calendar Globalization tests fixed. * Adding test files to projects. * Build fix. * Fix the fix. * . * Fix tests. * Load locale info on request + fix Browser scenario tests. * Fix test on v8. * Forgotten clean-up. * Small cleanup in ts. * V8 11 is behaves more like browser. * Fixed skipped failing tests. * Syntax * V8 returns the same as Browser. * This API is not affected, no need to test. + Add documentation. * Revert unintentional change. * Feedback. * @radical's feedback + fix after removing unnecessary set. * Fix. * Feedback. * Fix tests.
1 parent 6029c30 commit a9363bf

File tree

45 files changed

+4861
-25
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+4861
-25
lines changed

docs/design/features/globalization-hybrid-mode.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,61 @@ Using `IgnoreNonSpace` for these two with `HybridGlobalization` off, also return
272272
new CultureInfo("de-DE").CompareInfo.IndexOf("strasse", "stra\u00DFe", 0, CompareOptions.IgnoreNonSpace); // 0 or -1
273273
```
274274

275+
**Calandars**
276+
277+
Affected public APIs:
278+
- DateTimeFormatInfo.AbbreviatedDayNames
279+
- DateTimeFormatInfo.GetAbbreviatedDayName()
280+
- DateTimeFormatInfo.AbbreviatedMonthGenitiveNames
281+
- DateTimeFormatInfo.AbbreviatedMonthNames
282+
- DateTimeFormatInfo.GetAbbreviatedMonthName()
283+
- DateTimeFormatInfo.AMDesignator
284+
- DateTimeFormatInfo.CalendarWeekRule
285+
- DateTimeFormatInfo.DayNames
286+
- DateTimeFormatInfo.GetDayName
287+
- DateTimeFormatInfo.GetAbbreviatedEraName()
288+
- DateTimeFormatInfo.GetEraName()
289+
- DateTimeFormatInfo.FirstDayOfWeek
290+
- DateTimeFormatInfo.FullDateTimePattern
291+
- DateTimeFormatInfo.LongDatePattern
292+
- DateTimeFormatInfo.LongTimePattern
293+
- DateTimeFormatInfo.MonthDayPattern
294+
- DateTimeFormatInfo.MonthGenitiveNames
295+
- DateTimeFormatInfo.MonthNames
296+
- DateTimeFormatInfo.GetMonthName()
297+
- DateTimeFormatInfo.NativeCalendarName
298+
- DateTimeFormatInfo.PMDesignator
299+
- DateTimeFormatInfo.ShortDatePattern
300+
- DateTimeFormatInfo.ShortestDayNames
301+
- DateTimeFormatInfo.GetShortestDayName()
302+
- DateTimeFormatInfo.ShortTimePattern
303+
- DateTimeFormatInfo.YearMonthPattern
304+
305+
306+
The Hybrid responses may differ because they use Web API functions. To better ilustrate the mechanism we provide an example for each endpoint. All exceptions cannot be listed, for reference check the response of specific version of Web API on your host.
307+
| **API** | **Functions used** | **Example of difference for locale** | **non-Hybrid** | **Hybrid** |
308+
|:-----------------------------:|:----------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------:|:------------------:|:-----------------:|
309+
| AbbreviatedDayNames | `Date.prototype.toLocaleDateString(locale, { weekday: "short" })` | en-CA | Sun. | Sun |
310+
| AbbreviatedMonthGenitiveNames | `Date.prototype.toLocaleDateString(locale, { month: "short", day: "numeric"})` | kn-IN | ಆಗ | ಆಗಸ್ಟ್ |
311+
| AbbreviatedMonthNames | `Date.prototype.toLocaleDateString(locale, { month: "short" })` | lt-LT | saus. | 01 |
312+
| AMDesignator | `Date.prototype.toLocaleTimeString(locale, { hourCycle: "h12"})`; `Date.prototype.toLocaleTimeString(locale, { hourCycle: "h24"})` | sr-Cyrl-RS | пре подне | AM |
313+
| CalendarWeekRule | `Intl.Locale.prototype.getWeekInfo().minimalDay` | none | - | - |
314+
| DayNames | `Date.prototype.toLocaleDateString(locale, { weekday: "long" })` | none | - | - |
315+
| GetAbbreviatedEraName() | `Date.prototype.toLocaleDateString(locale, { era: "narrow" })` | bn-IN | খৃষ্টাব্দ | খ্রিঃ |
316+
| GetEraName() | `Date.prototype.toLocaleDateString(locale, { era: "short" })` | vi-VI | sau CN | CN |
317+
| FirstDayOfWeek | `Intl.Locale.prototype.getWeekInfo().firstDay` | zn-CN | Sunday | Monday |
318+
| FullDateTimePattern | `LongDatePattern` and `LongTimePattern` | - | | |
319+
| LongDatePattern | `Intl.DateTimeFormat(locale, { weekday: "long", year: "numeric", month: "long", day: "numeric"}).format(date)` | en-BW | dddd, dd MMMM yyyy | dddd, d MMMM yyyy |
320+
| LongTimePattern | `Intl.DateTimeFormat(locale, { timeStyle: "medium" })` | zn-CN | tth:mm:ss | HH:mm:ss |
321+
| MonthDayPattern | `Date.prototype.toLocaleDateString(locale, { month: "long", day: "numeric"})` | en-PH | d MMMM | MMMM d |
322+
| MonthGenitiveNames | `Date.prototype.toLocaleDateString(locale, { month: "long", day: "numeric"})` | ca-AD | de gener | gener |
323+
| MonthNames | `Date.prototype.toLocaleDateString(locale, { month: "long" })` | el-GR | Ιανουαρίου | Ιανουάριος |
324+
| NativeCalendarName | `Intl.Locale.prototype.getCalendars()` | for all locales it has English names | Gregorian Calendar | gregory |
325+
| PMDesignator | `Date.prototype.toLocaleTimeString(locale, { hourCycle: "h12"})`; `Date.prototype.toLocaleTimeString(locale, { hourCycle: "h24"})` | mr-IN | म.उ. | PM |
326+
| ShortDatePattern | `Date.prototype.toLocaleDateString(locale, {dateStyle: "short"})` | en-CH | dd.MM.yyyy | dd/MM/yyyy |
327+
| ShortestDayNames | `Date.prototype.toLocaleDateString(locale, { weekday: "narrow" })` | none | - | - |
328+
| ShortTimePattern | `Intl.DateTimeFormat(locale, { timeStyle: "medium" })` | bg-BG | HH:mm | H:mm |
329+
| YearMonthPattern | `Date.prototype.toLocaleDateString(locale, { year: "numeric", month: "long" })` | ar-SA | MMMM yyyy | MMMM yyyy g |
275330

276331
### OSX
277332

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Globalization;
5+
using System.Runtime.CompilerServices;
6+
7+
internal static partial class Interop
8+
{
9+
internal static unsafe partial class JsGlobalization
10+
{
11+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
12+
internal static extern unsafe int GetCalendarInfo(in string culture, CalendarId calendarId, char* buffer, int bufferLength, out int exceptionalResult, out object result);
13+
}
14+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Runtime.CompilerServices;
5+
6+
internal static partial class Interop
7+
{
8+
internal static unsafe partial class JsGlobalization
9+
{
10+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
11+
internal static extern unsafe int GetCultureInfo(in string culture, char* buffer, int bufferLength, out int exceptionalResult, out object result);
12+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
13+
internal static extern unsafe int GetFirstDayOfWeek(in string culture, out int exceptionalResult, out object result);
14+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
15+
internal static extern unsafe int GetFirstWeekOfYear(in string culture, out int exceptionalResult, out object result);
16+
}
17+
}

src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ public static string GetDistroVersionString()
366366
public static bool IsNotHybridGlobalizationOnBrowser => !IsHybridGlobalizationOnBrowser;
367367
public static bool IsNotInvariantGlobalization => !IsInvariantGlobalization;
368368
public static bool IsIcuGlobalization => ICUVersion > new Version(0, 0, 0, 0);
369+
public static bool IsIcuGlobalizationAndNotHybridOnBrowser => IsIcuGlobalization && IsNotHybridGlobalizationOnBrowser;
369370
public static bool IsNlsGlobalization => IsNotInvariantGlobalization && !IsIcuGlobalization;
370371

371372
public static bool IsSubstAvailable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFrameworks>$(NetCoreAppCurrent)-browser</TargetFrameworks>
4+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
5+
<TestRuntime>true</TestRuntime>
6+
<HybridGlobalization>true</HybridGlobalization>
7+
</PropertyGroup>
8+
<ItemGroup>
9+
<Compile Include="..\System\Globalization\CalendarTestBase.cs" />
10+
<Compile Include="..\System\Globalization\ChineseLunisolarCalendarTests.cs" />
11+
<Compile Include="..\System\Globalization\EastAsianLunisolarCalendarTestBase.cs" />
12+
<Compile Include="..\System\Globalization\GregorianCalendarTests.cs" />
13+
<Compile Include="..\System\Globalization\HebrewCalendarTests.cs" />
14+
<Compile Include="..\System\Globalization\HijriCalendarTests.cs" />
15+
<Compile Include="..\System\Globalization\JapaneseCalendarTests.cs" />
16+
<Compile Include="..\System\Globalization\JapaneseLunisolarCalendarTests.cs" />
17+
<Compile Include="..\System\Globalization\JulianCalendarTests.cs" />
18+
<Compile Include="..\System\Globalization\KoreanCalendarTests.cs" />
19+
<Compile Include="..\System\Globalization\KoreanLunisolarCalendarTests.cs" />
20+
<Compile Include="..\System\Globalization\PersianCalendarTests.cs" />
21+
<Compile Include="..\System\Globalization\TaiwanCalendarTests.cs" />
22+
<Compile Include="..\System\Globalization\TaiwanLunisolarCalendarTests.cs" />
23+
<Compile Include="..\System\Globalization\ThaiBuddhistCalendarTests.cs" />
24+
<Compile Include="..\System\Globalization\UmAlQuraCalendarTests.cs" />
25+
<Compile Include="..\GregorianCalendar\GregorianCalendarAddMonths.cs" />
26+
<Compile Include="..\GregorianCalendar\GregorianCalendarAddYears.cs" />
27+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetDayOfMonth.cs" />
28+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetDayOfWeek.cs" />
29+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetDayOfYear.cs" />
30+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetDaysInMonth.cs" />
31+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetDaysInYear.cs" />
32+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetEra.cs" />
33+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetMonth.cs" />
34+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetLeapMonth.cs" />
35+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetMonthsInYear.cs" />
36+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetWeekOfYear.cs" />
37+
<Compile Include="..\GregorianCalendar\GregorianCalendarGetYear.cs" />
38+
<Compile Include="..\GregorianCalendar\GregorianCalendarIsLeapDay.cs" />
39+
<Compile Include="..\GregorianCalendar\GregorianCalendarIsLeapMonth.cs" />
40+
<Compile Include="..\GregorianCalendar\GregorianCalendarIsLeapYear.cs" />
41+
<Compile Include="..\GregorianCalendar\GregorianCalendarTests.Utilities.cs" />
42+
<Compile Include="..\GregorianCalendar\GregorianCalendarToDateTime.cs" />
43+
<Compile Include="..\GregorianCalendar\GregorianCalendarToFourDigitYear.cs" />
44+
<Compile Include="..\GregorianCalendar\GregorianCalendarTwoDigitYearMax.cs" />
45+
<Compile Include="..\ISOWeek\ISOWeekTests.cs" />
46+
<Compile Include="..\JapaneseCalendar\JapaneseCalendarAddMonths.cs" />
47+
<Compile Include="..\JapaneseCalendar\JapaneseCalendarToFourDigitYear.cs" />
48+
<Compile Include="..\JapaneseCalendar\JapaneseCalendarTwoDigitYearMax.cs" />
49+
<Compile Include="..\KoreanCalendar\KoreanCalendarToDateTime.cs" />
50+
<Compile Include="..\KoreanCalendar\KoreanCalendarAddMonths.cs" />
51+
<Compile Include="..\KoreanCalendar\KoreanCalendarAddYears.cs" />
52+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetDayOfMonth.cs" />
53+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetDayOfWeek.cs" />
54+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetDayOfYear.cs" />
55+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetDaysInMonth.cs" />
56+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetDaysInYear.cs" />
57+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetEra.cs" />
58+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetMonth.cs" />
59+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetMonthsInYear.cs" />
60+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetWeekOfYear.cs" />
61+
<Compile Include="..\KoreanCalendar\KoreanCalendarGetYear.cs" />
62+
<Compile Include="..\KoreanCalendar\KoreanCalendarIsLeapDay.cs" />
63+
<Compile Include="..\KoreanCalendar\KoreanCalendarIsLeapMonth.cs" />
64+
<Compile Include="..\KoreanCalendar\KoreanCalendarIsLeapYear.cs" />
65+
<Compile Include="..\KoreanCalendar\KoreanCalendarToFourDigitYear.cs" />
66+
<Compile Include="..\KoreanCalendar\KoreanCalendarTwoDigitYearMax.cs" />
67+
<Compile Include="..\Misc\MiscCalendars.cs" />
68+
<Compile Include="..\Misc\Calendars.cs" />
69+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarUtilities.cs" />
70+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarAddMonths.cs" />
71+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarAddYears.cs" />
72+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarDaysAndMonths.cs" />
73+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetDayOfMonth.cs" />
74+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetDayOfWeek.cs" />
75+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetDayOfYear.cs" />
76+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetDaysInMonth.cs" />
77+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetDaysInYear.cs" />
78+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetEra.cs" />
79+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetMonth.cs" />
80+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetMonthsInYear.cs" />
81+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetWeekOfYear.cs" />
82+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarGetYear.cs" />
83+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarIsLeapDay.cs" />
84+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarIsLeapMonth.cs" />
85+
<Compile Include="..\TaiwanCalendar\TaiWanCalendarIsLeapYear.cs" />
86+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarToDateTime.cs" />
87+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarToFourDigitYear.cs" />
88+
<Compile Include="..\TaiwanCalendar\TaiwanCalendarTwoDigitYearMax.cs" />
89+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarAddMonths.cs" />
90+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarAddYears.cs" />
91+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetDayOfMonth.cs" />
92+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetDayOfWeek.cs" />
93+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetDayOfYear.cs" />
94+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetDaysInMonth.cs" />
95+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetDaysInYear.cs" />
96+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetEra.cs" />
97+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetMonth.cs" />
98+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetMonthsInYear.cs" />
99+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetWeekOfYear.cs" />
100+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarGetYear.cs" />
101+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarIsLeapDay.cs" />
102+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarIsLeapMonth.cs" />
103+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarIsLeapYear.cs" />
104+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarToDateTime.cs" />
105+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarToFourDigitYear.cs" />
106+
<Compile Include="..\ThaiBuddhistCalendar\ThaiBuddhistCalendarTwoDigitYearMax.cs" />
107+
<Compile Include="$(CommonTestPath)System\RandomDataGenerator.cs" />
108+
</ItemGroup>
109+
</Project>

src/libraries/System.Globalization.Calendars/tests/System/Globalization/CalendarTestBase.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,10 @@ public void GetEra_Invalid_ThrowsArgumentOutOfRangeException()
430430
Assert.All(DateTime_TestData(calendar), dt =>
431431
{
432432
// JapaneseCalendar throws on ICU, but not on NLS
433-
if ((calendar is JapaneseCalendar && PlatformDetection.IsNlsGlobalization) || calendar is HebrewCalendar || calendar is TaiwanLunisolarCalendar || calendar is JapaneseLunisolarCalendar)
433+
if ((calendar is JapaneseCalendar && PlatformDetection.IsNlsGlobalization) ||
434+
calendar is HebrewCalendar ||
435+
calendar is TaiwanLunisolarCalendar ||
436+
calendar is JapaneseLunisolarCalendar)
434437
{
435438
calendar.GetEra(dt);
436439
}

src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ public void TestCreationWithTemporaryLCID(int lcid)
442442
[InlineData("de-DE-u-co-phonebk-t-xx", "de-DE-t-xx", "de-DE-t-xx_phoneboo")]
443443
[InlineData("de-DE-u-co-phonebk-t-xx-u-yy", "de-DE-t-xx-u-yy", "de-DE-t-xx-u-yy_phoneboo")]
444444
[InlineData("de-DE", "de-DE", "de-DE")]
445-
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))]
445+
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalizationAndNotHybridOnBrowser))]
446446
public void TestCreationWithMangledSortName(string cultureName, string expectedCultureName, string expectedSortName)
447447
{
448448
CultureInfo ci = CultureInfo.GetCultureInfo(cultureName);
@@ -457,7 +457,7 @@ public void TestCreationWithMangledSortName(string cultureName, string expectedC
457457
[InlineData("qps-plocm", "qps-PLOCM")] // ICU normalize this name to "qps--plocm" which we normalize it back to "qps-plocm"
458458
[InlineData("zh_CN", "zh_cn")]
459459
[InlineData("km_KH", "km_kh")]
460-
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization), nameof(PlatformDetection.IsNotWindowsServerCore))]
460+
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalizationAndNotHybridOnBrowser), nameof(PlatformDetection.IsNotWindowsServerCore))]
461461
public void TestCreationWithICUNormalizedNames(string cultureName, string expectedCultureName)
462462
{
463463
CultureInfo ci = CultureInfo.GetCultureInfo(cultureName);

0 commit comments

Comments
 (0)