2 // System.Globalization.CultureInfo.cs
5 // Miguel de Icaza (miguel@ximian.com)
6 // Dick Porter (dick@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
9 // (C) 2001, 2002, 2003 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 // Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
34 using System.Threading;
35 using System.Runtime.CompilerServices;
36 using System.Runtime.InteropServices;
38 namespace System.Globalization
40 [System.Runtime.InteropServices.ComVisible (true)]
42 [StructLayout (LayoutKind.Sequential)]
43 public class CultureInfo : ICloneable, IFormatProvider
45 static volatile CultureInfo invariant_culture_info = new CultureInfo (InvariantCultureId, false, true);
46 static object shared_table_lock = new object ();
47 internal static int BootstrapCultureID;
49 #pragma warning disable 169, 649
59 int default_calendar_type;
60 bool m_useUserOverride;
62 volatile NumberFormatInfo numInfo;
63 volatile DateTimeFormatInfo dateTimeInfo;
64 volatile TextInfo textInfo;
65 private string m_name;
68 private string englishname;
70 private string nativename;
72 private string iso3lang;
74 private string iso2lang;
76 private string win3lang;
78 private string territory;
80 string[] native_calendar_names;
82 volatile CompareInfo compareInfo;
84 private unsafe readonly void *textinfo_data;
86 int m_dataItem; // MS.NET serializes this.
87 #pragma warning restore 169, 649
92 CultureInfo parent_culture;
94 // Deserialized instances will set this to false
99 // Used by Thread.set_CurrentCulture
100 internal byte[] cached_serialized_form;
102 const int InvariantCultureId = 0x7F;
103 const int CalendarTypeBits = 8;
105 const string MSG_READONLY = "This instance is read only";
107 public static CultureInfo InvariantCulture {
109 return invariant_culture_info;
113 public static CultureInfo CurrentCulture {
115 return Thread.CurrentThread.CurrentCulture;
119 public static CultureInfo CurrentUICulture {
121 return Thread.CurrentThread.CurrentUICulture;
125 internal static CultureInfo ConstructCurrentCulture ()
127 CultureInfo ci = new CultureInfo ();
128 if (!ConstructInternalLocaleFromCurrentLocale (ci))
129 ci = InvariantCulture;
130 BootstrapCultureID = ci.cultureID;
134 internal static CultureInfo ConstructCurrentUICulture ()
136 return ConstructCurrentCulture ();
139 // it is used for RegionInfo.
140 internal string Territory {
141 get { return territory; }
145 // FIXME: It is implemented, but would be hell slow.
147 public CultureTypes CultureTypes {
149 CultureTypes ret = (CultureTypes) 0;
150 foreach (CultureTypes v in Enum.GetValues (typeof (CultureTypes)))
151 if (Array.IndexOf (GetCultures (v), this) >= 0)
158 public CultureInfo GetConsoleFallbackUICulture ()
160 // as documented in MSDN ...
162 case "ar": case "ar-BH": case "ar-EG": case "ar-IQ":
163 case "ar-JO": case "ar-KW": case "ar-LB": case "ar-LY":
164 case "ar-QA": case "ar-SA": case "ar-SY": case "ar-AE":
166 case "dv": case "dv-MV":
167 case "fa": case "fa-IR":
168 case "gu": case "gu-IN":
169 case "he": case "he-IL":
170 case "hi": case "hi-IN":
171 case "kn": case "kn-IN":
172 case "kok": case "kok-IN":
173 case "mr": case "mr-IN":
174 case "pa": case "pa-IN":
175 case "sa": case "sa-IN":
176 case "syr": case "syr-SY":
177 case "ta": case "ta-IN":
178 case "te": case "te-IN":
179 case "th": case "th-TH":
180 case "ur": case "ur-PK":
181 case "vi": case "vi-VN":
182 return GetCultureInfo ("en");
183 case "ar-DZ": case "ar-MA": case "ar-TN":
184 return GetCultureInfo ("fr");
186 return (CultureTypes & CultureTypes.WindowsOnlyCultures) != 0 ? CultureInfo.InvariantCulture : this;
190 public string IetfLanguageTag {
191 // There could be more consistent way to implement
192 // it, but right now it works just fine with this...
205 // For specific cultures it basically returns LCID.
206 // For neutral cultures it is mapped to the default(?) specific
207 // culture, where the LCID of the specific culture seems to be
208 // n + 1024 by default. zh-CHS is the only exception which is
209 // mapped to 2052, not 1028 (zh-CHT is mapped to 1028 instead).
210 // There are very few exceptions, here I simply list them here.
211 // It is Windows-specific property anyways, so no worthy of
212 // trying to do some complex things with locale-builder.
214 public virtual int KeyboardLayoutId {
217 case 4: // zh-CHS (neutral)
219 case 1034: // es-ES Spanish 2
221 case 31748: // zh-CHT (neutral)
223 case 31770: // sr (neutral)
226 return LCID < 1024 ? LCID + 1024 : LCID;
232 public virtual int LCID {
238 public virtual string Name {
241 if (m_name == "zh-CHS")
243 if (m_name == "zh-CHT")
250 public virtual string NativeName {
252 if (!constructed) Construct ();
257 internal string NativeCalendarName {
259 if (!constructed) Construct ();
260 return native_calendar_names[(default_calendar_type >> CalendarTypeBits) - 1];
264 public virtual Calendar Calendar {
266 if (calendar == null) {
267 if (!constructed) Construct ();
268 calendar = CreateCalendar (default_calendar_type);
275 [MonoLimitation ("Optional calendars are not supported only default calendar is returned")]
276 public virtual Calendar[] OptionalCalendars {
278 return new[] { Calendar };
282 public virtual CultureInfo Parent
285 if (parent_culture == null) {
288 if (parent_lcid == cultureID)
291 if (parent_lcid == InvariantCultureId)
292 parent_culture = InvariantCulture;
293 else if (cultureID == InvariantCultureId)
294 parent_culture = this;
296 parent_culture = new CultureInfo (parent_lcid);
298 return parent_culture;
302 public virtual TextInfo TextInfo
305 if (textInfo == null) {
306 if (!constructed) Construct ();
308 if(textInfo == null) {
309 textInfo = CreateTextInfo (m_isReadOnly);
318 public virtual string ThreeLetterISOLanguageName {
320 if (!constructed) Construct ();
325 public virtual string ThreeLetterWindowsLanguageName
328 if (!constructed) Construct ();
333 public virtual string TwoLetterISOLanguageName {
335 if (!constructed) Construct ();
340 public bool UseUserOverride
343 return m_useUserOverride;
347 public void ClearCachedData()
349 Thread.CurrentThread.CurrentCulture = null;
350 Thread.CurrentThread.CurrentUICulture = null;
353 public virtual object Clone()
355 if (!constructed) Construct ();
356 CultureInfo ci=(CultureInfo)MemberwiseClone ();
357 ci.m_isReadOnly=false;
358 ci.cached_serialized_form=null;
359 if (!IsNeutralCulture) {
360 ci.NumberFormat = (NumberFormatInfo)NumberFormat.Clone ();
361 ci.DateTimeFormat = (DateTimeFormatInfo)DateTimeFormat.Clone ();
366 public override bool Equals (object value)
368 CultureInfo b = value as CultureInfo;
371 return b.cultureID == cultureID;
376 public static CultureInfo[] GetCultures(CultureTypes types)
378 bool neutral=((types & CultureTypes.NeutralCultures)!=0);
379 bool specific=((types & CultureTypes.SpecificCultures)!=0);
380 bool installed=((types & CultureTypes.InstalledWin32Cultures)!=0); // TODO
382 CultureInfo [] infos = internal_get_cultures (neutral, specific, installed);
383 // The runtime returns a NULL in the first position of the array when
384 // 'neutral' is true. We fill it in with a clone of InvariantCulture
385 // since it must not be read-only
386 if (neutral && infos.Length > 0 && infos [0] == null) {
387 infos [0] = (CultureInfo) InvariantCulture.Clone ();
394 public override int GetHashCode ()
396 return cultureID.GetHashCode ();
399 public static CultureInfo ReadOnly(CultureInfo ci)
402 throw new ArgumentNullException("ci");
405 if(ci.m_isReadOnly) {
408 CultureInfo new_ci=(CultureInfo)ci.Clone ();
409 new_ci.m_isReadOnly=true;
410 if (new_ci.numInfo != null)
411 new_ci.numInfo = NumberFormatInfo.ReadOnly (new_ci.numInfo);
412 if (new_ci.dateTimeInfo != null)
413 new_ci.dateTimeInfo = DateTimeFormatInfo.ReadOnly (new_ci.dateTimeInfo);
414 if (new_ci.textInfo != null)
415 new_ci.textInfo = TextInfo.ReadOnly (new_ci.textInfo);
420 public override string ToString()
425 public virtual CompareInfo CompareInfo
428 if(compareInfo==null) {
433 if(compareInfo==null) {
434 compareInfo=new CompareInfo (this);
443 public virtual bool IsNeutralCulture {
445 if (cultureID == InvariantCultureId)
448 if (!constructed) Construct ();
449 return territory == null;
453 internal void CheckNeutral ()
455 #if !MOONLIGHT && !NET_4_0
456 if (IsNeutralCulture) {
457 throw new NotSupportedException ("Culture \"" + m_name + "\" is " +
458 "a neutral culture. It can not be used in formatting " +
459 "and parsing and therefore cannot be set as the thread's " +
465 public virtual NumberFormatInfo NumberFormat {
467 if (!constructed) Construct ();
469 if (numInfo == null){
471 if (numInfo == null) {
472 numInfo = new NumberFormatInfo (m_isReadOnly);
473 construct_number_format ();
482 if (!constructed) Construct ();
483 if (m_isReadOnly) throw new InvalidOperationException(MSG_READONLY);
486 throw new ArgumentNullException ("NumberFormat");
492 public virtual DateTimeFormatInfo DateTimeFormat {
494 if (dateTimeInfo != null)
497 if (!constructed) Construct ();
500 // TODO: Have to lock because construct_datetime_format is not atomic
502 if (cultureID == InvariantCultureId && m_isReadOnly)
503 dateTimeInfo = DateTimeFormatInfo.InvariantInfo;
504 else if (dateTimeInfo == null) {
505 dateTimeInfo = new DateTimeFormatInfo (this, m_isReadOnly);
506 if (cultureID != InvariantCultureId)
507 construct_datetime_format ();
515 if (!constructed) Construct ();
516 if (m_isReadOnly) throw new InvalidOperationException(MSG_READONLY);
519 throw new ArgumentNullException ("DateTimeFormat");
521 dateTimeInfo = value;
525 public virtual string DisplayName {
527 // Mono is not localized and will always return english name regardless of OS locale
532 public virtual string EnglishName {
534 if (!constructed) Construct ();
539 public static CultureInfo InstalledUICulture
541 get { return GetCultureInfo (BootstrapCultureID); }
544 public bool IsReadOnly {
552 // IFormatProvider implementation
554 public virtual object GetFormat( Type formatType )
556 object format = null;
558 if ( formatType == typeof(NumberFormatInfo) )
559 format = NumberFormat;
560 else if ( formatType == typeof(DateTimeFormatInfo) )
561 format = DateTimeFormat;
568 construct_internal_locale_from_lcid (cultureID);
572 static bool ConstructInternalLocaleFromCurrentLocale (CultureInfo ci)
574 if (!construct_internal_locale_from_current_locale (ci))
579 [MethodImplAttribute (MethodImplOptions.InternalCall)]
580 private extern bool construct_internal_locale_from_lcid (int lcid);
582 [MethodImplAttribute (MethodImplOptions.InternalCall)]
583 private extern bool construct_internal_locale_from_name (string name);
585 // [MethodImplAttribute (MethodImplOptions.InternalCall)]
586 // private extern static bool construct_internal_locale_from_specific_name (CultureInfo ci, string name);
588 [MethodImplAttribute (MethodImplOptions.InternalCall)]
589 private extern static bool construct_internal_locale_from_current_locale (CultureInfo ci);
591 [MethodImplAttribute (MethodImplOptions.InternalCall)]
592 private extern static CultureInfo [] internal_get_cultures (bool neutral, bool specific, bool installed);
594 [MethodImplAttribute (MethodImplOptions.InternalCall)]
595 private extern void construct_datetime_format ();
597 [MethodImplAttribute (MethodImplOptions.InternalCall)]
598 private extern void construct_number_format ();
600 private void ConstructInvariant (bool read_only)
602 cultureID = InvariantCultureId;
604 /* NumberFormatInfo defaults to the invariant data */
605 numInfo=NumberFormatInfo.InvariantInfo;
608 numInfo = (NumberFormatInfo) numInfo.Clone ();
611 textInfo = CreateTextInfo (read_only);
615 nativename="Invariant Language (Invariant Country)";
619 default_calendar_type = 1 << CalendarTypeBits;
622 private unsafe TextInfo CreateTextInfo (bool readOnly)
624 return new TextInfo (this, cultureID, this.textinfo_data, readOnly);
627 public CultureInfo (int culture) : this (culture, true) {}
629 public CultureInfo (int culture, bool useUserOverride) :
630 this (culture, useUserOverride, false) {}
632 private CultureInfo (int culture, bool useUserOverride, bool read_only)
635 throw new ArgumentOutOfRangeException ("culture", "Positive "
636 + "number required.");
639 m_isReadOnly = read_only;
640 m_useUserOverride = useUserOverride;
642 if (culture == InvariantCultureId) {
643 /* Short circuit the invariant culture */
644 ConstructInvariant (read_only);
648 if (!construct_internal_locale_from_lcid (culture)) {
650 throw new CultureNotFoundException ("culture",
651 String.Format ("Culture ID {0} (0x{0:X4}) is not a " +
652 "supported culture.", culture));
654 throw new ArgumentException (
655 String.Format ("Culture ID {0} (0x{0:X4}) is not a " +
656 "supported culture.", culture), "culture");
661 public CultureInfo (string name) : this (name, true) {}
663 public CultureInfo (string name, bool useUserOverride) :
664 this (name, useUserOverride, false) {}
666 private CultureInfo (string name, bool useUserOverride, bool read_only)
669 throw new ArgumentNullException ("name");
672 m_isReadOnly = read_only;
673 m_useUserOverride = useUserOverride;
675 if (name.Length == 0) {
676 /* Short circuit the invariant culture */
677 ConstructInvariant (read_only);
681 if (!construct_internal_locale_from_name (name.ToLowerInvariant ())) {
683 throw new CultureNotFoundException ("name",
684 "Culture name " + name + " is not supported.");
686 throw new ArgumentException ("Culture name " + name +
687 " is not supported.", "name");
692 // This is used when creating by specific name and creating by
693 // current locale so we can initialize the object without
694 // doing any member initialization
695 private CultureInfo () { constructed = true; }
696 static Hashtable shared_by_number, shared_by_name;
698 static void insert_into_shared_tables (CultureInfo c)
700 if (shared_by_number == null){
701 shared_by_number = new Hashtable ();
702 shared_by_name = new Hashtable ();
704 shared_by_number [c.cultureID] = c;
705 shared_by_name [c.m_name] = c;
708 public static CultureInfo GetCultureInfo (int culture)
712 lock (shared_table_lock){
713 if (shared_by_number != null){
714 c = shared_by_number [culture] as CultureInfo;
717 return (CultureInfo) c;
719 c = new CultureInfo (culture, false, true);
720 insert_into_shared_tables (c);
725 public static CultureInfo GetCultureInfo (string name)
728 throw new ArgumentNullException ("name");
731 lock (shared_table_lock){
732 if (shared_by_name != null){
733 c = shared_by_name [name] as CultureInfo;
736 return (CultureInfo) c;
738 c = new CultureInfo (name, false, true);
739 insert_into_shared_tables (c);
744 [MonoTODO ("Currently it ignores the altName parameter")]
745 public static CultureInfo GetCultureInfo (string name, string altName) {
747 throw new ArgumentNullException ("null");
749 throw new ArgumentNullException ("null");
751 return GetCultureInfo (name);
754 public static CultureInfo GetCultureInfoByIetfLanguageTag (string name)
756 // There could be more consistent way to implement
757 // it, but right now it works just fine with this...
760 return GetCultureInfo ("zh-CHS");
762 return GetCultureInfo ("zh-CHT");
764 return GetCultureInfo (name);
768 // used in runtime (icall.c) to construct CultureInfo for
769 // AssemblyName of assemblies
770 internal static CultureInfo CreateCulture (string name, bool reference)
773 bool use_user_override;
775 bool invariant = name.Length == 0;
777 use_user_override = invariant ? false : true;
781 use_user_override = invariant ? false : true;
784 return new CultureInfo (name, use_user_override, read_only);
787 public static CultureInfo CreateSpecificCulture (string name)
790 throw new ArgumentNullException ("name");
792 if (name.Length == 0)
793 return InvariantCulture;
795 CultureInfo ci = null;
797 ci = new CultureInfo (name);
798 } catch (Exception) {
799 // TODO: Use construct_internal_locale_from_name when it's not bound to constructor instead
801 int idx = name.IndexOf ('-');
804 ci = new CultureInfo (name.Substring (0, idx));
813 if (!ci.IsNeutralCulture)
816 return CreateSpecificCultureFromNeutral (ci.Name);
820 // Creates specific culture from neutral culture. Used by CreateSpecificCulture
821 // only but using separate method we can delay switch underlying Dictionary
824 static CultureInfo CreateSpecificCultureFromNeutral (string name)
829 // For neutral cultures find predefined default specific culture
831 // Use managed switch because we need this for only some cultures
832 // and the method is not used frequently
834 // TODO: We could optimize for cultures with single specific culture
836 switch (name.ToLowerInvariant ()) {
837 case "af": id = 1078; break;
838 case "am": id = 1118; break;
839 case "ar": id = 1025; break;
840 case "arn": id = 1146; break;
841 case "as": id = 1101; break;
842 case "az": id = 1068; break;
843 case "az-Cyrl": id = 2092; break;
844 case "az-Latn": id = 1068; break;
845 case "ba": id = 1133; break;
846 case "be": id = 1059; break;
847 case "bg": id = 1026; break;
848 case "bn": id = 1093; break;
849 case "bo": id = 1105; break;
850 case "br": id = 1150; break;
851 case "bs": id = 5146; break;
852 case "bs-Cyrl": id = 8218; break;
853 case "bs-Latn": id = 5146; break;
854 case "ca": id = 1027; break;
855 case "co": id = 1155; break;
856 case "cs": id = 1029; break;
857 case "cy": id = 1106; break;
858 case "da": id = 1030; break;
859 case "de": id = 1031; break;
860 case "dsb": id = 2094; break;
861 case "dv": id = 1125; break;
862 case "el": id = 1032; break;
863 case "en": id = 1033; break;
864 case "es": id = 3082; break;
865 case "et": id = 1061; break;
866 case "eu": id = 1069; break;
867 case "fa": id = 1065; break;
868 case "fi": id = 1035; break;
869 case "fil": id = 1124; break;
870 case "fo": id = 1080; break;
871 case "fr": id = 1036; break;
872 case "fy": id = 1122; break;
873 case "ga": id = 2108; break;
874 case "gd": id = 1169; break;
875 case "gl": id = 1110; break;
876 case "gsw": id = 1156; break;
877 case "gu": id = 1095; break;
878 case "ha": id = 1128; break;
879 case "ha-Latn": id = 1128; break;
880 case "he": id = 1037; break;
881 case "hi": id = 1081; break;
882 case "hr": id = 1050; break;
883 case "hsb": id = 1070; break;
884 case "hu": id = 1038; break;
885 case "hy": id = 1067; break;
886 case "id": id = 1057; break;
887 case "ig": id = 1136; break;
888 case "ii": id = 1144; break;
889 case "is": id = 1039; break;
890 case "it": id = 1040; break;
891 case "iu": id = 2141; break;
892 case "iu-Cans": id = 1117; break;
893 case "iu-Latn": id = 2141; break;
894 case "ja": id = 1041; break;
895 case "ka": id = 1079; break;
896 case "kk": id = 1087; break;
897 case "kl": id = 1135; break;
898 case "km": id = 1107; break;
899 case "kn": id = 1099; break;
900 case "ko": id = 1042; break;
901 case "kok": id = 1111; break;
902 case "ky": id = 1088; break;
903 case "lb": id = 1134; break;
904 case "lo": id = 1108; break;
905 case "lt": id = 1063; break;
906 case "lv": id = 1062; break;
907 case "mi": id = 1153; break;
908 case "mk": id = 1071; break;
909 case "ml": id = 1100; break;
910 case "mn": id = 1104; break;
911 case "mn-Cyrl": id = 1104; break;
912 case "mn-Mong": id = 2128; break;
913 case "moh": id = 1148; break;
914 case "mr": id = 1102; break;
915 case "ms": id = 1086; break;
916 case "mt": id = 1082; break;
917 case "nb": id = 1044; break;
918 case "ne": id = 1121; break;
919 case "nl": id = 1043; break;
920 case "nn": id = 2068; break;
921 case "no": id = 1044; break;
922 case "nso": id = 1132; break;
923 case "oc": id = 1154; break;
924 case "or": id = 1096; break;
925 case "pa": id = 1094; break;
926 case "pl": id = 1045; break;
927 case "prs": id = 1164; break;
928 case "ps": id = 1123; break;
929 case "pt": id = 1046; break;
930 case "qut": id = 1158; break;
931 case "quz": id = 1131; break;
932 case "rm": id = 1047; break;
933 case "ro": id = 1048; break;
934 case "ru": id = 1049; break;
935 case "rw": id = 1159; break;
936 case "sa": id = 1103; break;
937 case "sah": id = 1157; break;
938 case "se": id = 1083; break;
939 case "si": id = 1115; break;
940 case "sk": id = 1051; break;
941 case "sl": id = 1060; break;
942 case "sma": id = 7227; break;
943 case "smj": id = 5179; break;
944 case "smn": id = 9275; break;
945 case "sms": id = 8251; break;
946 case "sq": id = 1052; break;
947 case "sr": id = 9242; break;
948 case "sr-Cyrl": id = 10266; break;
949 case "sr-Latn": id = 9242; break;
950 case "sv": id = 1053; break;
951 case "sw": id = 1089; break;
952 case "syr": id = 1114; break;
953 case "ta": id = 1097; break;
954 case "te": id = 1098; break;
955 case "tg": id = 1064; break;
956 case "tg-Cyrl": id = 1064; break;
957 case "th": id = 1054; break;
958 case "tk": id = 1090; break;
959 case "tn": id = 1074; break;
960 case "tr": id = 1055; break;
961 case "tt": id = 1092; break;
962 case "tzm": id = 2143; break;
963 case "tzm-Latn": id = 2143; break;
964 case "ug": id = 1152; break;
965 case "uk": id = 1058; break;
966 case "ur": id = 1056; break;
967 case "uz": id = 1091; break;
968 case "uz-Cyrl": id = 2115; break;
969 case "uz-Latn": id = 1091; break;
970 case "vi": id = 1066; break;
971 case "wo": id = 1160; break;
972 case "xh": id = 1076; break;
973 case "yo": id = 1130; break;
974 case "zh": id = 2052; break;
975 case "zh-CHS": case "zh-Hans":
977 case "zh-CHT": case "zh-Hant":
979 case "zu": id = 1077; break;
981 throw new NotImplementedException ("Mapping for neutral culture " + name);
984 return new CultureInfo (id);
987 static Calendar CreateCalendar (int calendarType)
989 switch (calendarType >> CalendarTypeBits) {
991 GregorianCalendarTypes greg_type;
992 greg_type = (GregorianCalendarTypes) (calendarType & 0xFF);
993 return new GregorianCalendar (greg_type);
995 return new ThaiBuddhistCalendar ();
997 return new UmAlQuraCalendar ();
999 return new HijriCalendar ();
1001 throw new NotImplementedException ("Unknown calendar type: " + calendarType);