diff options
Diffstat (limited to 'src/mscorlib/src/System/Globalization/CalendarData.cs')
-rw-r--r-- | src/mscorlib/src/System/Globalization/CalendarData.cs | 274 |
1 files changed, 117 insertions, 157 deletions
diff --git a/src/mscorlib/src/System/Globalization/CalendarData.cs b/src/mscorlib/src/System/Globalization/CalendarData.cs index d66331b31d..0991149e07 100644 --- a/src/mscorlib/src/System/Globalization/CalendarData.cs +++ b/src/mscorlib/src/System/Globalization/CalendarData.cs @@ -2,159 +2,136 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics; + namespace System.Globalization { - - using System; - using System.Runtime.InteropServices; - using System.Runtime.CompilerServices; - using System.Runtime.Versioning; - using System.Diagnostics; - using System.Diagnostics.Contracts; - // // List of calendar data // Note the we cache overrides. // Note that localized names (resource names) aren't available from here. // // NOTE: Calendars depend on the locale name that creates it. Only a few - // properties are available without locales using CalendarData.GetCalendar(int) + // properties are available without locales using CalendarData.GetCalendar(CalendarData) - // StructLayout is needed here otherwise compiler can re-arrange the fields. - // We have to keep this in-sync with the definition in calendardata.h - // - // WARNING WARNING WARNING - // - // WARNING: Anything changed here also needs to be updated on the native side (object.h see type CalendarDataBaseObject) - // WARNING: The type loader will rearrange class member offsets so the mscorwks!CalendarDataBaseObject - // WARNING: must be manually structured to match the true loaded class layout - // - internal class CalendarData + internal partial class CalendarData { // Max calendars internal const int MAX_CALENDARS = 23; // Identity - internal String sNativeName ; // Calendar Name for the locale + internal String sNativeName; // Calendar Name for the locale // Formats - internal String[] saShortDates ; // Short Data format, default first - internal String[] saYearMonths ; // Year/Month Data format, default first - internal String[] saLongDates ; // Long Data format, default first - internal String sMonthDay ; // Month/Day format + internal String[] saShortDates; // Short Data format, default first + internal String[] saYearMonths; // Year/Month Data format, default first + internal String[] saLongDates; // Long Data format, default first + internal String sMonthDay; // Month/Day format // Calendar Parts Names - internal String[] saEraNames ; // Names of Eras - internal String[] saAbbrevEraNames ; // Abbreviated Era Names - internal String[] saAbbrevEnglishEraNames ; // Abbreviated Era Names in English - internal String[] saDayNames ; // Day Names, null to use locale data, starts on Sunday - internal String[] saAbbrevDayNames ; // Abbrev Day Names, null to use locale data, starts on Sunday - internal String[] saSuperShortDayNames ; // Super short Day of week names - internal String[] saMonthNames ; // Month Names (13) - internal String[] saAbbrevMonthNames ; // Abbrev Month Names (13) - internal String[] saMonthGenitiveNames ; // Genitive Month Names (13) - internal String[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13) - internal String[] saLeapYearMonthNames ; // Multiple strings for the month names in a leap year. + internal String[] saEraNames; // Names of Eras + internal String[] saAbbrevEraNames; // Abbreviated Era Names + internal String[] saAbbrevEnglishEraNames; // Abbreviated Era Names in English + internal String[] saDayNames; // Day Names, null to use locale data, starts on Sunday + internal String[] saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday + internal String[] saSuperShortDayNames; // Super short Day of week names + internal String[] saMonthNames; // Month Names (13) + internal String[] saAbbrevMonthNames; // Abbrev Month Names (13) + internal String[] saMonthGenitiveNames; // Genitive Month Names (13) + internal String[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13) + internal String[] saLeapYearMonthNames; // Multiple strings for the month names in a leap year. // Integers at end to make marshaller happier - internal int iTwoDigitYearMax=2029 ; // Max 2 digit year (for Y2K bug data entry) - internal int iCurrentEra=0 ; // current era # (usually 1) + internal int iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry) + internal int iCurrentEra = 0; // current era # (usually 1) // Use overrides? - internal bool bUseUserOverrides ; // True if we want user overrides. + internal bool bUseUserOverrides; // True if we want user overrides. // Static invariant for the invariant locale - internal static CalendarData Invariant; + internal static readonly CalendarData Invariant = CreateInvariant(); // Private constructor - private CalendarData() {} + private CalendarData() { } - // Invariant constructor - static CalendarData() + // Invariant factory + private static CalendarData CreateInvariant() { - // Set our default/gregorian US calendar data // Calendar IDs are 1-based, arrays are 0 based. CalendarData invariant = new CalendarData(); // Set default data for calendar // Note that we don't load resources since this IS NOT supposed to change (by definition) - invariant.sNativeName = "Gregorian Calendar"; // Calendar Name + invariant.sNativeName = "Gregorian Calendar"; // Calendar Name // Year - invariant.iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry) - invariant.iCurrentEra = 1; // Current era # + invariant.iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry) + invariant.iCurrentEra = 1; // Current era # // Formats - invariant.saShortDates = new String[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format - invariant.saLongDates = new String[] { "dddd, dd MMMM yyyy"}; // long date format - invariant.saYearMonths = new String[] { "yyyy MMMM" }; // year month format - invariant.sMonthDay = "MMMM dd"; // Month day pattern + invariant.saShortDates = new String[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format + invariant.saLongDates = new String[] { "dddd, dd MMMM yyyy" }; // long date format + invariant.saYearMonths = new String[] { "yyyy MMMM" }; // year month format + invariant.sMonthDay = "MMMM dd"; // Month day pattern // Calendar Parts Names - invariant.saEraNames = new String[] { "A.D." }; // Era names - invariant.saAbbrevEraNames = new String[] { "AD" }; // Abbreviated Era names - invariant.saAbbrevEnglishEraNames=new String[] { "AD" }; // Abbreviated era names in English - invariant.saDayNames = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names - invariant.saAbbrevDayNames = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names - invariant.saSuperShortDayNames = new String[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names - invariant.saMonthNames = new String[] { "January", "February", "March", "April", "May", "June", + invariant.saEraNames = new String[] { "A.D." }; // Era names + invariant.saAbbrevEraNames = new String[] { "AD" }; // Abbreviated Era names + invariant.saAbbrevEnglishEraNames = new String[] { "AD" }; // Abbreviated era names in English + invariant.saDayNames = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names + invariant.saAbbrevDayNames = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names + invariant.saSuperShortDayNames = new String[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names + invariant.saMonthNames = new String[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", String.Empty}; // month names - invariant.saAbbrevMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + invariant.saAbbrevMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", String.Empty}; // abbreviated month names - invariant.saMonthGenitiveNames = invariant.saMonthNames; // Genitive month names (same as month names for invariant) - invariant.saAbbrevMonthGenitiveNames=invariant.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant) - invariant.saLeapYearMonthNames = invariant.saMonthNames; // leap year month names are unused in Gregorian English (invariant) + invariant.saMonthGenitiveNames = invariant.saMonthNames; // Genitive month names (same as month names for invariant) + invariant.saAbbrevMonthGenitiveNames = invariant.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant) + invariant.saLeapYearMonthNames = invariant.saMonthNames; // leap year month names are unused in Gregorian English (invariant) - invariant.bUseUserOverrides = false; + invariant.bUseUserOverrides = false; - // Calendar was built, go ahead and assign it... - Invariant = invariant; + return invariant; } - - // // Get a bunch of data for a calendar // - internal CalendarData(String localeName, int calendarId, bool bUseUserOverrides) + internal CalendarData(String localeName, CalendarId calendarId, bool bUseUserOverrides) { - // Call nativeGetCalendarData to populate the data this.bUseUserOverrides = bUseUserOverrides; - if (!nativeGetCalendarData(this, localeName, calendarId)) + + Debug.Assert(!GlobalizationMode.Invariant); + + if (!LoadCalendarDataFromSystem(localeName, calendarId)) { - Debug.Assert(false, "[CalendarData] nativeGetCalendarData call isn't expected to fail for calendar " + calendarId + " locale " +localeName); - + Debug.Assert(false, "[CalendarData] LoadCalendarDataFromSystem call isn't expected to fail for calendar " + calendarId + " locale " + localeName); + // Something failed, try invariant for missing parts // This is really not good, but we don't want the callers to crash. - if (this.sNativeName == null) this.sNativeName = String.Empty; // Calendar Name for the locale. - + if (this.sNativeName == null) this.sNativeName = String.Empty; // Calendar Name for the locale. + // Formats - if (this.saShortDates == null) this.saShortDates = Invariant.saShortDates; // Short Data format, default first - if (this.saYearMonths == null) this.saYearMonths = Invariant.saYearMonths; // Year/Month Data format, default first - if (this.saLongDates == null) this.saLongDates = Invariant.saLongDates; // Long Data format, default first - if (this.sMonthDay == null) this.sMonthDay = Invariant.sMonthDay; // Month/Day format - + if (this.saShortDates == null) this.saShortDates = Invariant.saShortDates; // Short Data format, default first + if (this.saYearMonths == null) this.saYearMonths = Invariant.saYearMonths; // Year/Month Data format, default first + if (this.saLongDates == null) this.saLongDates = Invariant.saLongDates; // Long Data format, default first + if (this.sMonthDay == null) this.sMonthDay = Invariant.sMonthDay; // Month/Day format + // Calendar Parts Names - if (this.saEraNames == null) this.saEraNames = Invariant.saEraNames; // Names of Eras - if (this.saAbbrevEraNames == null) this.saAbbrevEraNames = Invariant.saAbbrevEraNames; // Abbreviated Era Names + if (this.saEraNames == null) this.saEraNames = Invariant.saEraNames; // Names of Eras + if (this.saAbbrevEraNames == null) this.saAbbrevEraNames = Invariant.saAbbrevEraNames; // Abbreviated Era Names if (this.saAbbrevEnglishEraNames == null) this.saAbbrevEnglishEraNames = Invariant.saAbbrevEnglishEraNames; // Abbreviated Era Names in English - if (this.saDayNames == null) this.saDayNames = Invariant.saDayNames; // Day Names, null to use locale data, starts on Sunday - if (this.saAbbrevDayNames == null) this.saAbbrevDayNames = Invariant.saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday - if (this.saSuperShortDayNames == null) this.saSuperShortDayNames = Invariant.saSuperShortDayNames; // Super short Day of week names - if (this.saMonthNames == null) this.saMonthNames = Invariant.saMonthNames; // Month Names (13) - if (this.saAbbrevMonthNames == null) this.saAbbrevMonthNames = Invariant.saAbbrevMonthNames; // Abbrev Month Names (13) + if (this.saDayNames == null) this.saDayNames = Invariant.saDayNames; // Day Names, null to use locale data, starts on Sunday + if (this.saAbbrevDayNames == null) this.saAbbrevDayNames = Invariant.saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday + if (this.saSuperShortDayNames == null) this.saSuperShortDayNames = Invariant.saSuperShortDayNames; // Super short Day of week names + if (this.saMonthNames == null) this.saMonthNames = Invariant.saMonthNames; // Month Names (13) + if (this.saAbbrevMonthNames == null) this.saAbbrevMonthNames = Invariant.saAbbrevMonthNames; // Abbrev Month Names (13) // Genitive and Leap names can follow the fallback below } - // Clean up the escaping of the formats - this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates); - this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates); - this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths); - this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay); - - if ((CalendarId)calendarId == CalendarId.TAIWAN) + if (calendarId == CalendarId.TAIWAN) { - if (CultureInfo.IsTaiwanSku) + if (SystemSupportsTaiwaneseCalendar()) { // We got the month/day names from the OS (same as gregorian), but the native name is wrong this.sNativeName = "\x4e2d\x83ef\x6c11\x570b\x66c6"; @@ -166,11 +143,11 @@ namespace System.Globalization } // Check for null genitive names (in case unmanaged side skips it for non-gregorian calendars, etc) - if (this.saMonthGenitiveNames == null || String.IsNullOrEmpty(this.saMonthGenitiveNames[0])) + if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saMonthGenitiveNames[0])) this.saMonthGenitiveNames = this.saMonthNames; // Genitive month names (same as month names for invariant) - if (this.saAbbrevMonthGenitiveNames == null || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0])) + if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0])) this.saAbbrevMonthGenitiveNames = this.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant) - if (this.saLeapYearMonthNames == null || String.IsNullOrEmpty(this.saLeapYearMonthNames[0])) + if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || String.IsNullOrEmpty(this.saLeapYearMonthNames[0])) this.saLeapYearMonthNames = this.saMonthNames; InitializeEraNames(localeName, calendarId); @@ -178,7 +155,7 @@ namespace System.Globalization InitializeAbbreviatedEraNames(localeName, calendarId); // Abbreviated English Era Names are only used for the Japanese calendar. - if (calendarId == (int)CalendarId.JAPAN) + if (calendarId == CalendarId.JAPAN) { this.saAbbrevEnglishEraNames = JapaneseCalendar.EnglishEraNames(); } @@ -193,12 +170,12 @@ namespace System.Globalization this.iCurrentEra = this.saEraNames.Length; } - private void InitializeEraNames(string localeName, int calendarId) + private void InitializeEraNames(string localeName, CalendarId calendarId) { // Note that the saEraNames only include "A.D." We don't have localized names for other calendars available from windows - switch ((CalendarId)calendarId) + switch (calendarId) { - // For Localized Gregorian we really expect the data from the OS. + // For Localized Gregorian we really expect the data from the OS. case CalendarId.GREGORIAN: // Fallback for CoreCLR < Win7 or culture.dll missing if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0])) @@ -207,7 +184,7 @@ namespace System.Globalization } break; - // The rest of the calendars have constant data, so we'll just use that + // The rest of the calendars have constant data, so we'll just use that case CalendarId.GREGORIAN_US: case CalendarId.JULIAN: this.saEraNames = new String[] { "A.D." }; @@ -237,9 +214,9 @@ namespace System.Globalization case CalendarId.GREGORIAN_ME_FRENCH: this.saEraNames = new String[] { "ap. J.-C." }; break; - + case CalendarId.TAIWAN: - if (CultureInfo.IsTaiwanSku) + if (SystemSupportsTaiwaneseCalendar()) { this.saEraNames = new String[] { "\x4e2d\x83ef\x6c11\x570b" }; } @@ -252,11 +229,11 @@ namespace System.Globalization case CalendarId.KOREA: this.saEraNames = new String[] { "\xb2e8\xae30" }; break; - + case CalendarId.THAI: this.saEraNames = new String[] { "\x0e1e\x002e\x0e28\x002e" }; break; - + case CalendarId.JAPAN: case CalendarId.JAPANESELUNISOLAR: this.saEraNames = JapaneseCalendar.EraNames(); @@ -276,25 +253,25 @@ namespace System.Globalization } } - private void InitializeAbbreviatedEraNames(string localeName, int calendarId) + private void InitializeAbbreviatedEraNames(string localeName, CalendarId calendarId) { // Note that the saAbbrevEraNames only include "AD" We don't have localized names for other calendars available from windows - switch ((CalendarId)calendarId) + switch (calendarId) { - // For Localized Gregorian we really expect the data from the OS. + // For Localized Gregorian we really expect the data from the OS. case CalendarId.GREGORIAN: - // Fallback for culture.dll missing + // Fallback for CoreCLR < Win7 or culture.dll missing if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0])) { this.saAbbrevEraNames = new String[] { "AD" }; } break; - // The rest of the calendars have constant data, so we'll just use that + // The rest of the calendars have constant data, so we'll just use that case CalendarId.GREGORIAN_US: - case CalendarId.JULIAN: + case CalendarId.JULIAN: this.saAbbrevEraNames = new String[] { "AD" }; - break; + break; case CalendarId.JAPAN: case CalendarId.JAPANESELUNISOLAR: this.saAbbrevEraNames = JapaneseCalendar.AbbrevEraNames(); @@ -316,12 +293,12 @@ namespace System.Globalization this.saAbbrevEraNames = new String[1]; if (this.saEraNames[0].Length == 4) { - this.saAbbrevEraNames[0] = this.saEraNames[0].Substring(2,2); + this.saAbbrevEraNames[0] = this.saEraNames[0].Substring(2, 2); } else { this.saAbbrevEraNames[0] = this.saEraNames[0]; - } + } break; case CalendarId.PERSIAN: @@ -338,7 +315,7 @@ namespace System.Globalization } } - internal static CalendarData GetCalendarData(int calendarId) + internal static CalendarData GetCalendarData(CalendarId calendarId) { // // Get a calendar. @@ -348,50 +325,47 @@ namespace System.Globalization // // Get a culture name + // TODO: Note that this doesn't handle the new calendars (lunisolar, etc) String culture = CalendarIdToCultureName(calendarId); - + // Return our calendar - return CultureInfo.GetCultureInfo(culture).m_cultureData.GetCalendar(calendarId); + return CultureInfo.GetCultureInfo(culture)._cultureData.GetCalendar(calendarId); } - // - // Helper methods - // - private static String CalendarIdToCultureName(int calendarId) + private static String CalendarIdToCultureName(CalendarId calendarId) { - // note that this doesn't handle the new calendars (lunisolar, etc) switch (calendarId) { - case Calendar.CAL_GREGORIAN_US: + case CalendarId.GREGORIAN_US: return "fa-IR"; // "fa-IR" Iran - - case Calendar.CAL_JAPAN: + + case CalendarId.JAPAN: return "ja-JP"; // "ja-JP" Japan - case Calendar.CAL_TAIWAN: // zh-TW Taiwan - return "zh-TW"; - - case Calendar.CAL_KOREA: + case CalendarId.TAIWAN: + return "zh-TW"; // zh-TW Taiwan + + case CalendarId.KOREA: return "ko-KR"; // "ko-KR" Korea - - case Calendar.CAL_HIJRI: - case Calendar.CAL_GREGORIAN_ARABIC: - case Calendar.CAL_UMALQURA: + + case CalendarId.HIJRI: + case CalendarId.GREGORIAN_ARABIC: + case CalendarId.UMALQURA: return "ar-SA"; // "ar-SA" Saudi Arabia - case Calendar.CAL_THAI: + case CalendarId.THAI: return "th-TH"; // "th-TH" Thailand - - case Calendar.CAL_HEBREW: + + case CalendarId.HEBREW: return "he-IL"; // "he-IL" Israel - - case Calendar.CAL_GREGORIAN_ME_FRENCH: + + case CalendarId.GREGORIAN_ME_FRENCH: return "ar-DZ"; // "ar-DZ" Algeria - - case Calendar.CAL_GREGORIAN_XLIT_ENGLISH: - case Calendar.CAL_GREGORIAN_XLIT_FRENCH: + + case CalendarId.GREGORIAN_XLIT_ENGLISH: + case CalendarId.GREGORIAN_XLIT_FRENCH: return "ar-IQ"; // "ar-IQ"; Iraq - + default: // Default to gregorian en-US break; @@ -399,20 +373,6 @@ namespace System.Globalization return "en-US"; } - - - // Get native two digit year max - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern int nativeGetTwoDigitYearMax(int calID); - - // Call native side to load our calendar data - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool nativeGetCalendarData(CalendarData data, String localeName, int calendar); - - // Call native side to figure out which calendars are allowed - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern int nativeGetCalendars(String localeName, bool useUserOverride, [In, Out] int[] calendars); - } - } +} |