summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Globalization/CalendarData.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Globalization/CalendarData.cs')
-rw-r--r--src/mscorlib/src/System/Globalization/CalendarData.cs274
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);
-
}
- }
+}