The Labs \ Source Viewer \ SSCLI \ System.Globalization \ HijriCalendar

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Globalization
  16. {
  17.    
  18.     using System;
  19.     using System.Runtime.Versioning;
  20.     using System.Text;
  21.     using Microsoft.Win32;
  22.    
  23.     ////////////////////////////////////////////////////////////////////////////
  24.     //
  25.     // Rules for the Hijri calendar:
  26.     // - The Hijri calendar is a strictly Lunar calendar.
  27.     // - Days begin at sunset.
  28.     // - Islamic Year 1 (Muharram 1, 1 A.H.) is equivalent to absolute date
  29.     // 227015 (Friday, July 16, 622 C.E. - Julian).
  30.     // - Leap Years occur in the 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, & 29th
  31.     // years of a 30-year cycle. Year = leap iff ((11y+14) mod 30 < 11).
  32.     // - There are 12 months which contain alternately 30 and 29 days.
  33.     // - The 12th month, Dhu al-Hijjah, contains 30 days instead of 29 days
  34.     // in a leap year.
  35.     // - Common years have 354 days. Leap years have 355 days.
  36.     // - There are 10,631 days in a 30-year cycle.
  37.     // - The Islamic months are:
  38.     // 1. Muharram (30 days) 7. Rajab (30 days)
  39.     // 2. Safar (29 days) 8. Sha'ban (29 days)
  40.     // 3. Rabi I (30 days) 9. Ramadan (30 days)
  41.     // 4. Rabi II (29 days) 10. Shawwal (29 days)
  42.     // 5. Jumada I (30 days) 11. Dhu al-Qada (30 days)
  43.     // 6. Jumada II (29 days) 12. Dhu al-Hijjah (29 days) {30}
  44.     //
  45.     // NOTENOTE
  46.     // The calculation of the HijriCalendar is based on the absolute date. And the
  47.     // absolute date means the number of days from January 1st, 1 A.D.
  48.     // Therefore, we do not support the days before the January 1st, 1 A.D.
  49.     //
  50.     //////////////////////////////////////////////////////////////////////////// </STRIP>
  51. /*
  52.     **  Calendar support range:
  53.     **      Calendar    Minimum    Maximum
  54.     **      ==========  ==========  ==========
  55.     **      Gregorian  0622/07/18  9999/12/31
  56.     **      Hijri      0001/01/01  9666/04/03
  57.     */   
  58.    
  59.     [Serializable()]
  60.     [System.Runtime.InteropServices.ComVisible(true)]
  61.     public class HijriCalendar : Calendar
  62.     {
  63.        
  64.        
  65.         public static readonly int HijriEra = 1;
  66.        
  67.         internal const int DatePartYear = 0;
  68.         internal const int DatePartDayOfYear = 1;
  69.         internal const int DatePartMonth = 2;
  70.         internal const int DatePartDay = 3;
  71.        
  72.         internal const int MinAdvancedHijri = -2;
  73.         internal const int MaxAdvancedHijri = 2;
  74.        
  75.         static internal readonly int[] HijriMonthDays = {0, 30, 59, 89, 118, 148, 177, 207, 236, 266,
  76.         295, 325, 355};
  77.        
  78.         //internal static Calendar m_defaultInstance;
  79.        
  80.         private static string m_HijriAdvanceRegKeyEntry = "AddHijriDate";
  81.        
  82.         private int m_HijriAdvance = Int32.MinValue;
  83.        
  84.         // DateTime.MaxValue = Hijri calendar (year:9666, month: 4, day: 3).
  85.         internal const int MaxCalendarYear = 9666;
  86.         internal const int MaxCalendarMonth = 4;
  87.         internal const int MaxCalendarDay = 3;
  88.         // Hijri calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 7, day: 18)
  89.         // This is the minimal Gregorian date that we support in the HijriCalendar.
  90.         static internal readonly DateTime calendarMinValue = new DateTime(622, 7, 18);
  91.         static internal readonly DateTime calendarMaxValue = DateTime.MaxValue;
  92.        
  93.        
  94.         [System.Runtime.InteropServices.ComVisible(false)]
  95.         public override DateTime MinSupportedDateTime {
  96.             get { return (calendarMinValue); }
  97.         }
  98.        
  99.        
  100.         [System.Runtime.InteropServices.ComVisible(false)]
  101.         public override DateTime MaxSupportedDateTime {
  102.             get { return (calendarMaxValue); }
  103.         }
  104.        
  105.         // Return the type of the Hijri calendar.
  106.         //
  107.        
  108.         [System.Runtime.InteropServices.ComVisible(false)]
  109.         public override CalendarAlgorithmType AlgorithmType {
  110.             get { return CalendarAlgorithmType.LunarCalendar; }
  111.         }
  112.        
  113. /*=================================GetDefaultInstance==========================
  114.         **Action: Internal method to provide a default intance of HijriCalendar.  Used by NLS+ implementation
  115.         **      and other calendars.
  116.         **Returns:
  117.         **Arguments:
  118.         **Exceptions:
  119.         ============================================================================*/       
  120. /*
  121.         internal static Calendar GetDefaultInstance() {
  122.             if (m_defaultInstance == null) {
  123.                 m_defaultInstance = new HijriCalendar();
  124.             }
  125.             return (m_defaultInstance);
  126.         }
  127.         */       
  128.        
  129.         // Construct an instance of Hijri calendar.
  130.        
  131.         public HijriCalendar()
  132.         {
  133.         }
  134.        
  135.         internal override int ID {
  136.             get { return (CAL_HIJRI); }
  137.         }
  138.        
  139. /*=================================GetAbsoluteDateHijri==========================
  140.         **Action: Gets the Absolute date for the given Hijri date.  The absolute date means
  141.         **      the number of days from January 1st, 1 A.D.
  142.         **Returns:
  143.         **Arguments:
  144.         **Exceptions:
  145.         ============================================================================*/       
  146.        
  147.         long GetAbsoluteDateHijri(int y, int m, int d)
  148.         {
  149.             return (long)(DaysUpToHijriYear(y) + HijriMonthDays[m - 1] + d - 1 - HijriAdjustment);
  150.         }
  151.        
  152. /*=================================DaysUpToHijriYear==========================
  153.         **Action: Gets the total number of days (absolute date) up to the given Hijri Year.
  154.         **      The absolute date means the number of days from January 1st, 1 A.D.
  155.         **Returns: Gets the total number of days (absolute date) up to the given Hijri Year.
  156.         **Arguments: HijriYear year value in Hijri calendar.
  157.         **Exceptions: None
  158.         **Notes:
  159.         ============================================================================*/       
  160.        
  161.         long DaysUpToHijriYear(int HijriYear)
  162.         {
  163.             long NumDays;
  164.             // number of absolute days
  165.             int NumYear30;
  166.             // number of years up to current 30 year cycle
  167.             int NumYearsLeft;
  168.             // number of years into 30 year cycle
  169.             //
  170.             // Compute the number of years up to the current 30 year cycle.
  171.             //
  172.             NumYear30 = ((HijriYear - 1) / 30) * 30;
  173.            
  174.             //
  175.             // Compute the number of years left. This is the number of years
  176.             // into the 30 year cycle for the given year.
  177.             //
  178.             NumYearsLeft = HijriYear - NumYear30 - 1;
  179.            
  180.             //
  181.             // Compute the number of absolute days up to the given year.
  182.             //
  183.             NumDays = ((NumYear30 * 10631l) / 30l) + 227013l;
  184.             while (NumYearsLeft > 0) {
  185.                 // Common year is 354 days, and leap year is 355 days.
  186.                 NumDays += 354 + (IsLeapYear(NumYearsLeft, CurrentEra) ? 1 : 0);
  187.                 NumYearsLeft--;
  188.             }
  189.            
  190.             //
  191.             // Return the number of absolute days.
  192.             //
  193.             return (NumDays);
  194.         }
  195.        
  196.        
  197.         public int HijriAdjustment {
  198.             get {
  199.                 if (m_HijriAdvance == Int32.MinValue) {
  200.                     // Never been set before. Use the system value from registry.
  201.                     m_HijriAdvance = GetAdvanceHijriDate();
  202.                 }
  203.                 return (m_HijriAdvance);
  204.             }
  205.            
  206.             set {
  207.                 VerifyWritable();
  208.                
  209.                 // NOTE: Check the value of Min/MaxAdavncedHijri with Arabic speakers to see if the assumption is good.
  210.                 if (value < MinAdvancedHijri || value > MaxAdvancedHijri) {
  211.                     throw new ArgumentOutOfRangeException("HijriAdjustment", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"), MinAdvancedHijri, MaxAdvancedHijri));
  212.                 }
  213.                 m_HijriAdvance = value;
  214.             }
  215.         }
  216.        
  217. /*=================================GetAdvanceHijriDate==========================
  218.         **Action: Gets the AddHijriDate value from the registry.
  219.         **Returns:
  220.         **Arguments:    None.
  221.         **Exceptions:
  222.         **Note:
  223.         **  The HijriCalendar has a user-overidable calculation.  That is, use can set a value from the control
  224.         **  panel, so that the calculation of the Hijri Calendar can move ahead or backwards from -2 to +2 days.
  225.         **
  226.         **  The valid string values in the registry are:
  227.         **      "AddHijriDate-2"  =>  Add -2 days to the current calculated Hijri date.
  228.         **      "AddHijriDate"    =>  Add -1 day to the current calculated Hijri date.
  229.         **      ""              =>  Add 0 day to the current calculated Hijri date.
  230.         **      "AddHijriDate+1"  =>  Add +1 days to the current calculated Hijri date.
  231.         **      "AddHijriDate+2"  =>  Add +2 days to the current calculated Hijri date.
  232.         ============================================================================*/       
  233.         [ResourceExposure(ResourceScope.None)]
  234.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  235.         int GetAdvanceHijriDate()
  236.         {
  237.            
  238.             int hijriAdvance = 0;
  239.            
  240.             const int parameterValueLength = 255;
  241.             StringBuilder parameterValue = new StringBuilder(parameterValueLength);
  242.             bool rc = Win32Native.FetchConfigurationString(true, m_HijriAdvanceRegKeyEntry, parameterValue, parameterValueLength);
  243.             if (rc) {
  244.                 string str = parameterValue.ToString();
  245.                 if (String.Compare(str, 0, m_HijriAdvanceRegKeyEntry, 0, m_HijriAdvanceRegKeyEntry.Length, true, CultureInfo.InvariantCulture) == 0) {
  246.                     if (str.Length == m_HijriAdvanceRegKeyEntry.Length)
  247.                         hijriAdvance = -1;
  248.                     else {
  249.                         str = str.Substring(m_HijriAdvanceRegKeyEntry.Length);
  250.                         try {
  251.                             int advance = Int32.Parse(str.ToString(), CultureInfo.InvariantCulture);
  252.                             if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri)) {
  253.                                 hijriAdvance = advance;
  254.                             }
  255.                         }
  256.                         // If we got garbage from registry just ignore it.
  257.                         // hijriAdvance = 0 because of declaraction assignment up above.
  258.                         catch (ArgumentException) {
  259.                         }
  260.                         catch (FormatException) {
  261.                         }
  262.                         catch (OverflowException) {
  263.                         }
  264.                     }
  265.                 }
  266.             }
  267.            
  268.             return (hijriAdvance);
  269.         }
  270.        
  271.         internal void CheckTicksRange(long ticks)
  272.         {
  273.             if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks) {
  274.                 throw new ArgumentOutOfRangeException("time", String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"), calendarMinValue, calendarMaxValue));
  275.             }
  276.         }
  277.        
  278.         internal void CheckEraRange(int era)
  279.         {
  280.             if (era != CurrentEra && era != HijriEra) {
  281.                 throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
  282.             }
  283.         }
  284.        
  285.         internal void CheckYearRange(int year, int era)
  286.         {
  287.             CheckEraRange(era);
  288.             if (year < 1 || year > MaxCalendarYear) {
  289.                 throw new ArgumentOutOfRangeException("year", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxCalendarYear));
  290.             }
  291.         }
  292.        
  293.         internal void CheckYearMonthRange(int year, int month, int era)
  294.         {
  295.             CheckYearRange(year, era);
  296.             if (year == MaxCalendarYear) {
  297.                 if (month > MaxCalendarMonth) {
  298.                     throw new ArgumentOutOfRangeException("month", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxCalendarMonth));
  299.                 }
  300.             }
  301.            
  302.             if (month < 1 || month > 12) {
  303.                 throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
  304.             }
  305.         }
  306.        
  307. /*=================================GetDatePart==========================
  308.         **Action: Returns a given date part of this <i>DateTime</i>. This method is used
  309.         **      to compute the year, day-of-year, month, or day part.
  310.         **Returns:
  311.         **Arguments:
  312.         **Exceptions:  ArgumentException if part is incorrect.
  313.         **Notes:
  314.         **      First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
  315.         **      Use the formula (((AbsoluteDate - 227013) * 30) / 10631) + 1, we can a rough value for the Hijri year.
  316.         **      In order to get the exact Hijri year, we compare the exact absolute date for HijriYear and (HijriYear + 1).
  317.         **      From here, we can get the correct Hijri year.
  318.         ============================================================================*/       
  319.        
  320.         internal virtual int GetDatePart(long ticks, int part)
  321.         {
  322.             int HijriYear;
  323.             // Hijri year
  324.             int HijriMonth;
  325.             // Hijri month
  326.             int HijriDay;
  327.             // Hijri day
  328.             long NumDays;
  329.             // The calculation buffer in number of days.
  330.             CheckTicksRange(ticks);
  331.            
  332.             //
  333.             // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
  334.             // 1/1/0001 is absolute date 1.
  335.             //
  336.             NumDays = ticks / GregorianCalendar.TicksPerDay + 1;
  337.            
  338.             //
  339.             // See how much we need to backup or advance
  340.             //
  341.             NumDays += HijriAdjustment;
  342.            
  343.             //
  344.             // Calculate the appromixate Hijri Year from this magic formula.
  345.             //
  346.             HijriYear = (int)(((NumDays - 227013) * 30) / 10631) + 1;
  347.            
  348.             long daysToHijriYear = DaysUpToHijriYear(HijriYear);
  349.             // The absoulte date for HijriYear
  350.             long daysOfHijriYear = GetDaysInYear(HijriYear, CurrentEra);
  351.             // The number of days for (HijriYear+1) year.
  352.             if (NumDays < daysToHijriYear) {
  353.                 daysToHijriYear -= daysOfHijriYear;
  354.                 HijriYear--;
  355.             }
  356.             else if (NumDays == daysToHijriYear) {
  357.                 HijriYear--;
  358.                 daysToHijriYear -= GetDaysInYear(HijriYear, CurrentEra);
  359.             }
  360.             else {
  361.                 if (NumDays > daysToHijriYear + daysOfHijriYear) {
  362.                     daysToHijriYear += daysOfHijriYear;
  363.                     HijriYear++;
  364.                 }
  365.             }
  366.             if (part == DatePartYear) {
  367.                 return (HijriYear);
  368.             }
  369.            
  370.             //
  371.             // Calculate the Hijri Month.
  372.             //
  373.            
  374.             HijriMonth = 1;
  375.             NumDays -= daysToHijriYear;
  376.            
  377.             if (part == DatePartDayOfYear) {
  378.                 return ((int)NumDays);
  379.             }
  380.            
  381.             while ((HijriMonth <= 12) && (NumDays > HijriMonthDays[HijriMonth - 1])) {
  382.                 HijriMonth++;
  383.             }
  384.             HijriMonth--;
  385.            
  386.             if (part == DatePartMonth) {
  387.                 return (HijriMonth);
  388.             }
  389.            
  390.             //
  391.             // Calculate the Hijri Day.
  392.             //
  393.             HijriDay = (int)(NumDays - HijriMonthDays[HijriMonth - 1]);
  394.            
  395.             if (part == DatePartDay) {
  396.                 return (HijriDay);
  397.             }
  398.             // Incorrect part value.
  399.             throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing"));
  400.         }
  401.        
  402.         // Returns the DateTime resulting from adding the given number of
  403.         // months to the specified DateTime. The result is computed by incrementing
  404.         // (or decrementing) the year and month parts of the specified DateTime by
  405.         // value months, and, if required, adjusting the day part of the
  406.         // resulting date downwards to the last day of the resulting month in the
  407.         // resulting year. The time-of-day part of the result is the same as the
  408.         // time-of-day part of the specified DateTime.
  409.         //
  410.         // In more precise terms, considering the specified DateTime to be of the
  411.         // form y / m / d + t, where y is the
  412.         // year, m is the month, d is the day, and t is the
  413.         // time-of-day, the result is y1 / m1 / d1 + t,
  414.         // where y1 and m1 are computed by adding value months
  415.         // to y and m, and d1 is the largest value less than
  416.         // or equal to d that denotes a valid day in month m1 of year
  417.         // y1.
  418.         //
  419.        
  420.         public override DateTime AddMonths(DateTime time, int months)
  421.         {
  422.             if (months < -120000 || months > 120000) {
  423.                 throw new ArgumentOutOfRangeException("months", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), -120000, 120000));
  424.             }
  425.             // Get the date in Hijri calendar.
  426.             int y = GetDatePart(time.Ticks, DatePartYear);
  427.             int m = GetDatePart(time.Ticks, DatePartMonth);
  428.             int d = GetDatePart(time.Ticks, DatePartDay);
  429.             int i = m - 1 + months;
  430.             if (i >= 0) {
  431.                 m = i % 12 + 1;
  432.                 y = y + i / 12;
  433.             }
  434.             else {
  435.                 m = 12 + (i + 1) % 12;
  436.                 y = y + (i - 11) / 12;
  437.             }
  438.             int days = GetDaysInMonth(y, m);
  439.             if (d > days) {
  440.                 d = days;
  441.             }
  442.             long ticks = GetAbsoluteDateHijri(y, m, d) * TicksPerDay + (time.Ticks % TicksPerDay);
  443.             Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
  444.             return (new DateTime(ticks));
  445.         }
  446.        
  447.         // Returns the DateTime resulting from adding the given number of
  448.         // years to the specified DateTime. The result is computed by incrementing
  449.         // (or decrementing) the year part of the specified DateTime by value
  450.         // years. If the month and day of the specified DateTime is 2/29, and if the
  451.         // resulting year is not a leap year, the month and day of the resulting
  452.         // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
  453.         // parts of the result are the same as those of the specified DateTime.
  454.         //
  455.        
  456.         public override DateTime AddYears(DateTime time, int years)
  457.         {
  458.             return (AddMonths(time, years * 12));
  459.         }
  460.        
  461.         // Returns the day-of-month part of the specified DateTime. The returned
  462.         // value is an integer between 1 and 31.
  463.         //
  464.        
  465.         public override int GetDayOfMonth(DateTime time)
  466.         {
  467.             return (GetDatePart(time.Ticks, DatePartDay));
  468.         }
  469.        
  470.         // Returns the day-of-week part of the specified DateTime. The returned value
  471.         // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
  472.         // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
  473.         // Thursday, 5 indicates Friday, and 6 indicates Saturday.
  474.         //
  475.        
  476.         public override DayOfWeek GetDayOfWeek(DateTime time)
  477.         {
  478.             return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
  479.         }
  480.        
  481.         // Returns the day-of-year part of the specified DateTime. The returned value
  482.         // is an integer between 1 and 366.
  483.         //
  484.        
  485.         public override int GetDayOfYear(DateTime time)
  486.         {
  487.             return (GetDatePart(time.Ticks, DatePartDayOfYear));
  488.         }
  489.        
  490.         // Returns the number of days in the month given by the year and
  491.         // month arguments.
  492.         //
  493.        
  494.         public override int GetDaysInMonth(int year, int month, int era)
  495.         {
  496.             CheckYearMonthRange(year, month, era);
  497.             if (month == 12) {
  498.                 // For the 12th month, leap year has 30 days, and common year has 29 days.
  499.                 return (IsLeapYear(year, CurrentEra) ? 30 : 29);
  500.             }
  501.             // Other months contain 30 and 29 days alternatively. The 1st month has 30 days.
  502.             return (((month % 2) == 1) ? 30 : 29);
  503.         }
  504.        
  505.         // Returns the number of days in the year given by the year argument for the current era.
  506.         //
  507.        
  508.         public override int GetDaysInYear(int year, int era)
  509.         {
  510.             CheckYearRange(year, era);
  511.             // Common years have 354 days. Leap years have 355 days.
  512.             return (IsLeapYear(year, CurrentEra) ? 355 : 354);
  513.         }
  514.        
  515.         // Returns the era for the specified DateTime value.
  516.        
  517.         public override int GetEra(DateTime time)
  518.         {
  519.             CheckTicksRange(time.Ticks);
  520.             return (HijriEra);
  521.         }
  522.        
  523.        
  524.         public override int[] Eras {
  525.             get { return (new int[] {HijriEra}); }
  526.         }
  527.        
  528.         // Returns the month part of the specified DateTime. The returned value is an
  529.         // integer between 1 and 12.
  530.         //
  531.        
  532.         public override int GetMonth(DateTime time)
  533.         {
  534.             return (GetDatePart(time.Ticks, DatePartMonth));
  535.         }
  536.        
  537.         // Returns the number of months in the specified year and era.
  538.        
  539.         public override int GetMonthsInYear(int year, int era)
  540.         {
  541.             CheckYearRange(year, era);
  542.             return (12);
  543.         }
  544.        
  545.         // Returns the year part of the specified DateTime. The returned value is an
  546.         // integer between 1 and MaxCalendarYear.
  547.         //
  548.        
  549.         public override int GetYear(DateTime time)
  550.         {
  551.             return (GetDatePart(time.Ticks, DatePartYear));
  552.         }
  553.        
  554.         // Checks whether a given day in the specified era is a leap day. This method returns true if
  555.         // the date is a leap day, or false if not.
  556.         //
  557.        
  558.         public override bool IsLeapDay(int year, int month, int day, int era)
  559.         {
  560.             // The year/month/era value checking is done in GetDaysInMonth().
  561.             int daysInMonth = GetDaysInMonth(year, month, era);
  562.             if (day < 1 || day > daysInMonth) {
  563.                 throw new ArgumentOutOfRangeException("day", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Day"), daysInMonth, month));
  564.             }
  565.             return (IsLeapYear(year, era) && month == 12 && day == 30);
  566.         }
  567.        
  568.         // Returns the leap month in a calendar year of the specified era. This method returns 0
  569.         // if this calendar does not have leap month, or this year is not a leap year.
  570.         //
  571.        
  572.         [System.Runtime.InteropServices.ComVisible(false)]
  573.         public override int GetLeapMonth(int year, int era)
  574.         {
  575.             CheckYearRange(year, era);
  576.             return (0);
  577.         }
  578.        
  579.         // Checks whether a given month in the specified era is a leap month. This method returns true if
  580.         // month is a leap month, or false if not.
  581.         //
  582.        
  583.         public override bool IsLeapMonth(int year, int month, int era)
  584.         {
  585.             CheckYearMonthRange(year, month, era);
  586.             return (false);
  587.         }
  588.        
  589.         // Checks whether a given year in the specified era is a leap year. This method returns true if
  590.         // year is a leap year, or false if not.
  591.         //
  592.        
  593.         public override bool IsLeapYear(int year, int era)
  594.         {
  595.             CheckYearRange(year, era);
  596.             return ((((year * 11) + 14) % 30) < 11);
  597.         }
  598.        
  599.         // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
  600.         //
  601.        
  602.         public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
  603.         {
  604.             // The year/month/era checking is done in GetDaysInMonth().
  605.             int daysInMonth = GetDaysInMonth(year, month, era);
  606.             if (day < 1 || day > daysInMonth) {
  607.                 BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day);
  608.                 throw new ArgumentOutOfRangeException("day", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Day"), daysInMonth, month));
  609.             }
  610.            
  611.             long lDate = GetAbsoluteDateHijri(year, month, day);
  612.            
  613.             if (lDate >= 0) {
  614.                 return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)));
  615.             }
  616.             else {
  617.                 throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
  618.             }
  619.         }
  620.        
  621.         private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1451;
  622.        
  623.        
  624.         public override int TwoDigitYearMax {
  625.             get {
  626.                 if (twoDigitYearMax == -1) {
  627.                     twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
  628.                 }
  629.                 return (twoDigitYearMax);
  630.             }
  631.            
  632.             set {
  633.                 VerifyWritable();
  634.                 if (value < 99 || value > MaxCalendarYear) {
  635.                     throw new ArgumentOutOfRangeException("value", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 99, MaxCalendarYear));
  636.                    
  637.                 }
  638.                 twoDigitYearMax = value;
  639.             }
  640.         }
  641.        
  642.        
  643.         public override int ToFourDigitYear(int year)
  644.         {
  645.             if (year < 100) {
  646.                 return (base.ToFourDigitYear(year));
  647.             }
  648.            
  649.             if (year > MaxCalendarYear) {
  650.                 throw new ArgumentOutOfRangeException("year", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxCalendarYear));
  651.             }
  652.             return (year);
  653.         }
  654.        
  655.     }
  656. }

Developer Fusion