Calendar.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / clr / src / BCL / System / Globalization / Calendar.cs / 1 / Calendar.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
namespace System.Globalization {
    using System; 
    using System.Runtime.CompilerServices; 
    using System.Globalization;
    using System.Runtime.Versioning; 

    // This abstract class represents a calendar. A calendar reckons time in
    // divisions such as weeks, months and years. The number, length and start of
    // the divisions vary in each calendar. 
    //
    // Any instant in time can be represented as an n-tuple of numeric values using 
    // a particular calendar. For example, the next vernal equinox occurs at (0.0, 0 
    // , 46, 8, 20, 3, 1999) in the Gregorian calendar. An  implementation of
    // Calendar can map any DateTime value to such an n-tuple and vice versa. The 
    // DateTimeFormat class can map between such n-tuples and a textual
    // representation such as "8:46 AM [....] 20th 1999 AD".
    //
    // Most calendars identify a year which begins the current era. There may be any 
    // number of previous eras. The Calendar class identifies the eras as enumerated
    // integers where the current era (CurrentEra) has the value zero. 
    // 
    // For consistency, the first unit in each interval, e.g. the first month, is
    // assigned the value one. 
     // The calculation of hour/minute/second is moved to Calendar from GregorianCalendar,
     // since most of the calendars (or all?) have the same way of calcuating hour/minute/second.

    [Serializable] 
    [System.Runtime.InteropServices.ComVisible(true)]
    public abstract class Calendar : ICloneable 
    { 

        // Number of 100ns (10E-7 second) ticks per time unit 
        internal const long TicksPerMillisecond   = 10000;
        internal const long TicksPerSecond        = TicksPerMillisecond * 1000;
        internal const long TicksPerMinute        = TicksPerSecond * 60;
        internal const long TicksPerHour          = TicksPerMinute * 60; 
        internal const long TicksPerDay           = TicksPerHour * 24;
 
        // Number of milliseconds per time unit 
        internal const int MillisPerSecond        = 1000;
        internal const int MillisPerMinute        = MillisPerSecond * 60; 
        internal const int MillisPerHour          = MillisPerMinute * 60;
        internal const int MillisPerDay           = MillisPerHour * 24;

        // Number of days in a non-leap year 
        internal const int DaysPerYear            = 365;
        // Number of days in 4 years 
        internal const int DaysPer4Years          = DaysPerYear * 4 + 1; 
        // Number of days in 100 years
        internal const int DaysPer100Years        = DaysPer4Years * 25 - 1; 
        // Number of days in 400 years
        internal const int DaysPer400Years        = DaysPer100Years * 4 + 1;

        // Number of days from 1/1/0001 to 1/1/10000 
        internal const int DaysTo10000            = DaysPer400Years * 25 - 366;
 
        internal const long MaxMillis             = (long)DaysTo10000 * MillisPerDay; 

        // 
        //  Calendar ID Values.  This is used to get data from calendar.nlp.
        //  The order of calendar ID means the order of data items in the table.
        //
 
        internal const int CAL_GREGORIAN                  = 1 ;     // Gregorian (localized) calendar
        internal const int CAL_GREGORIAN_US               = 2 ;     // Gregorian (U.S.) calendar 
        internal const int CAL_JAPAN                      = 3 ;     // Japanese Emperor Era calendar 
        internal const int CAL_TAIWAN                     = 4 ;     // Taiwan Era calendar
        internal const int CAL_KOREA                      = 5 ;     // Korean Tangun Era calendar 
        internal const int CAL_HIJRI                      = 6 ;     // Hijri (Arabic Lunar) calendar
        internal const int CAL_THAI                       = 7 ;     // Thai calendar
        internal const int CAL_HEBREW                     = 8 ;     // Hebrew (Lunar) calendar
        internal const int CAL_GREGORIAN_ME_FRENCH        = 9 ;     // Gregorian Middle East French calendar 
        internal const int CAL_GREGORIAN_ARABIC           = 10;     // Gregorian Arabic calendar
        internal const int CAL_GREGORIAN_XLIT_ENGLISH     = 11;     // Gregorian Transliterated English calendar 
        internal const int CAL_GREGORIAN_XLIT_FRENCH      = 12; 
        internal const int CAL_JULIAN                     = 13;
        internal const int CAL_JAPANESELUNISOLAR          = 14; 
        internal const int CAL_CHINESELUNISOLAR           = 15;
        internal const int CAL_SAKA                       = 16;     // reserved to match Office but not implemented in our code
        internal const int CAL_LUNAR_ETO_CHN              = 17;     // reserved to match Office but not implemented in our code
        internal const int CAL_LUNAR_ETO_KOR              = 18;     // reserved to match Office but not implemented in our code 
        internal const int CAL_LUNAR_ETO_ROKUYOU          = 19;     // reserved to match Office but not implemented in our code
        internal const int CAL_KOREANLUNISOLAR            = 20; 
        internal const int CAL_TAIWANLUNISOLAR            = 21; 
        internal const int CAL_PERSIAN                    = 22;
        internal const int CAL_UMALQURA                   = 23; 

        internal int m_currentEraValue = -1;

        [System.Runtime.Serialization.OptionalField(VersionAdded = 2)] 
        private bool m_isReadOnly = false;
 
        // The minimum supported DateTime range for the calendar. 

        [System.Runtime.InteropServices.ComVisible(false)] 
        public virtual DateTime MinSupportedDateTime
        {
            get
            { 
                return (DateTime.MinValue);
            } 
        } 

        // The maximum supported DateTime range for the calendar. 

        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual DateTime MaxSupportedDateTime
        { 
            get
            { 
                return (DateTime.MaxValue); 
            }
        } 



 
        protected Calendar() {
            //Do-nothing constructor. 
        } 

        /// 
        // This can not be abstract, otherwise no one can create a subclass of Calendar.
        //
        internal virtual int ID {
            get { 
                return (-1);
            } 
        } 

        /// 
        // Return the Base calendar ID for calendars that didn't have defined data in culture.nlp
        //

        internal virtual int BaseCalendarID 
        {
            get { return ID; } 
        } 

        // Returns  the type of the calendar. 
        //
        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual CalendarAlgorithmType AlgorithmType
        { 
            get
            { 
                return CalendarAlgorithmType.Unknown; 
            }
        } 

        ////////////////////////////////////////////////////////////////////////
        //
        //  IsReadOnly 
        //
        //  Detect if the object is readonly. 
        // 
        ////////////////////////////////////////////////////////////////////////
        [System.Runtime.InteropServices.ComVisible(false)] 
        public bool IsReadOnly
        {
            get { return (m_isReadOnly); }
        } 

        //////////////////////////////////////////////////////////////////////// 
        // 
        //  Clone
        // 
        //  Is the implementation of IColnable.
        //
        ////////////////////////////////////////////////////////////////////////
        [System.Runtime.InteropServices.ComVisible(false)] 
        public virtual Object Clone()
        { 
            object o = MemberwiseClone(); 
            ((Calendar) o).SetReadOnlyState(false);
            return (o); 
        }

        ////////////////////////////////////////////////////////////////////////
        // 
        //  ReadOnly
        // 
        //  Create a cloned readonly instance or return the input one if it is 
        //  readonly.
        // 
        ////////////////////////////////////////////////////////////////////////
        [System.Runtime.InteropServices.ComVisible(false)]
        public static Calendar ReadOnly(Calendar calendar)
        { 
            if (calendar == null)       { throw new ArgumentNullException("calendar"); }
            if (calendar.IsReadOnly)    { return (calendar); } 
 
            Calendar clonedCalendar = (Calendar)(calendar.MemberwiseClone());
            clonedCalendar.SetReadOnlyState(true); 

            return (clonedCalendar);
        }
 
        internal void VerifyWritable()
        { 
            if (m_isReadOnly) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); 
            }
        }

        internal void SetReadOnlyState(bool readOnly) 
        {
            m_isReadOnly = readOnly; 
        } 

 
        /*=================================CurrentEraValue==========================
        **Action: This is used to convert CurretEra(0) to an appropriate era value.
        **Returns:
        **Arguments: 
        **Exceptions:
        **Notes: 
        ** The value is from calendar.nlp. 
        ============================================================================*/
 
        internal virtual int CurrentEraValue {
            get {
                // The following code assumes that the current era value can not be -1.
                if (m_currentEraValue == -1) { 
                    BCLDebug.Assert(BaseCalendarID > 0, "[Calendar.CurrentEraValue] Expected ID > 0");
                    m_currentEraValue = CalendarTable.Default.ICURRENTERA(BaseCalendarID); 
                } 
                return (m_currentEraValue);
            } 
        }

        // The current era for a calendar.
 
        public const int CurrentEra = 0;
 
        internal int twoDigitYearMax = -1; 

        internal static void CheckAddResult(long ticks, DateTime minValue, DateTime maxValue) { 
            if (ticks < minValue.Ticks || ticks > maxValue.Ticks) {
                throw new ArgumentException(
                    String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Argument_ResultCalendarRange"),
                        minValue, maxValue)); 
            }
        } 
 
        internal DateTime Add(DateTime time, double value, int scale) {
            long millis = (long)(value * scale + (value >= 0? 0.5: -0.5)); 
            if (millis <= -MaxMillis || millis >= MaxMillis) {
                throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue"));
            }
            long ticks = time.Ticks + millis * TicksPerMillisecond; 
            CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
            return (new DateTime(ticks)); 
        } 

        // Returns the DateTime resulting from adding the given number of 
        // milliseconds to the specified DateTime. The result is computed by rounding
        // the number of milliseconds given by value to the nearest integer,
        // and adding that interval to the specified DateTime. The value
        // argument is permitted to be negative. 
        //
 
        public virtual DateTime AddMilliseconds(DateTime time, double milliseconds) { 
            return (Add(time, milliseconds, 1));
        } 


        // Returns the DateTime resulting from adding a fractional number of
        // days to the specified DateTime. The result is computed by rounding the 
        // fractional number of days given by value to the nearest
        // millisecond, and adding that interval to the specified DateTime. The 
        // value argument is permitted to be negative. 
        //
 
        public virtual DateTime AddDays(DateTime time, int days) {
            return (Add(time, days, MillisPerDay));
        }
 
        // Returns the DateTime resulting from adding a fractional number of
        // hours to the specified DateTime. The result is computed by rounding the 
        // fractional number of hours given by value to the nearest 
        // millisecond, and adding that interval to the specified DateTime. The
        // value argument is permitted to be negative. 
        //

        public virtual DateTime AddHours(DateTime time, int hours) {
            return (Add(time, hours, MillisPerHour)); 
        }
 
 
        // Returns the DateTime resulting from adding a fractional number of
        // minutes to the specified DateTime. The result is computed by rounding the 
        // fractional number of minutes given by value to the nearest
        // millisecond, and adding that interval to the specified DateTime. The
        // value argument is permitted to be negative.
        // 

        public virtual DateTime AddMinutes(DateTime time, int minutes) { 
            return (Add(time, minutes, MillisPerMinute)); 
        }
 

        // Returns the DateTime resulting from adding the given number of
        // months to the specified DateTime. The result is computed by incrementing
        // (or decrementing) the year and month parts of the specified DateTime by 
        // value months, and, if required, adjusting the day part of the
        // resulting date downwards to the last day of the resulting month in the 
        // resulting year. The time-of-day part of the result is the same as the 
        // time-of-day part of the specified DateTime.
        // 
        // In more precise terms, considering the specified DateTime to be of the
        // form y / m / d + t, where y is the
        // year, m is the month, d is the day, and t is the
        // time-of-day, the result is y1 / m1 / d1 + t, 
        // where y1 and m1 are computed by adding value months
        // to y and m, and d1 is the largest value less than 
        // or equal to d that denotes a valid day in month m1 of year 
        // y1.
        // 

        public abstract DateTime AddMonths(DateTime time, int months);

        // Returns the DateTime resulting from adding a number of 
        // seconds to the specified DateTime. The result is computed by rounding the
        // fractional number of seconds given by value to the nearest 
        // millisecond, and adding that interval to the specified DateTime. The 
        // value argument is permitted to be negative.
        // 

        public virtual DateTime AddSeconds(DateTime time, int seconds) {
            return Add(time, seconds, MillisPerSecond);
        } 

        // Returns the DateTime resulting from adding a number of 
        // weeks to the specified DateTime. The 
        // value argument is permitted to be negative.
        // 

        public virtual DateTime AddWeeks(DateTime time, int weeks) {
            return (AddDays(time, weeks * 7));
        } 

 
        // Returns the DateTime resulting from adding the given number of 
        // years to the specified DateTime. The result is computed by incrementing
        // (or decrementing) the year part of the specified DateTime by value 
        // years. If the month and day of the specified DateTime is 2/29, and if the
        // resulting year is not a leap year, the month and day of the resulting
        // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
        // parts of the result are the same as those of the specified DateTime. 
        //
 
        public abstract DateTime AddYears(DateTime time, int years); 

        // Returns the day-of-month part of the specified DateTime. The returned 
        // value is an integer between 1 and 31.
        //

        public abstract int GetDayOfMonth(DateTime time); 

        // Returns the day-of-week part of the specified DateTime. The returned value 
        // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates 
        // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
        // Thursday, 5 indicates Friday, and 6 indicates Saturday. 
        //

        public abstract DayOfWeek GetDayOfWeek(DateTime time);
 
        // Returns the day-of-year part of the specified DateTime. The returned value
        // is an integer between 1 and 366. 
        // 

        public abstract int GetDayOfYear(DateTime time); 

        // Returns the number of days in the month given by the year and
        // month arguments.
        // 

        public virtual int GetDaysInMonth(int year, int month) 
        { 
            return (GetDaysInMonth(year, month, CurrentEra));
        } 

        // Returns the number of days in the month given by the year and
        // month arguments for the specified era.
        // 

        public abstract int GetDaysInMonth(int year, int month, int era); 
 
        // Returns the number of days in the year given by the year argument for the current era.
        // 

        public virtual int GetDaysInYear(int year)
        {
            return (GetDaysInYear(year, CurrentEra)); 
        }
 
        // Returns the number of days in the year given by the year argument for the current era. 
        //
 
        public abstract int GetDaysInYear(int year, int era);

        // Returns the era for the specified DateTime value.
 
        public abstract int GetEra(DateTime time);
 
        /*=================================Eras========================== 
        **Action: Get the list of era values.
        **Returns: The int array of the era names supported in this calendar. 
        **      null if era is not used.
        **Arguments: None.
        **Exceptions: None.
        ============================================================================*/ 

 
        public abstract int[] Eras { 
            get;
        } 


        // Returns the hour part of the specified DateTime. The returned value is an
        // integer between 0 and 23. 
        //
 
        public virtual int GetHour(DateTime time) { 
            return ((int)((time.Ticks / TicksPerHour) % 24));
        } 

        // Returns the millisecond part of the specified DateTime. The returned value
        // is an integer between 0 and 999.
        // 

        public virtual double GetMilliseconds(DateTime time) { 
            return (double)((time.Ticks / TicksPerMillisecond) % 1000); 
        }
 
        // Returns the minute part of the specified DateTime. The returned value is
        // an integer between 0 and 59.
        //
 
        public virtual int GetMinute(DateTime time) {
            return ((int)((time.Ticks / TicksPerMinute) % 60)); 
        } 

        // Returns the month part of the specified DateTime. The returned value is an 
        // integer between 1 and 12.
        //

        public abstract int GetMonth(DateTime time); 

        // Returns the number of months in the specified year in the current era. 
 
        public virtual int GetMonthsInYear(int year)
        { 
            return (GetMonthsInYear(year, CurrentEra));
        }

        // Returns the number of months in the specified year and era. 

        public abstract int GetMonthsInYear(int year, int era); 
 
        // Returns the second part of the specified DateTime. The returned value is
        // an integer between 0 and 59. 
        //

        public virtual int GetSecond(DateTime time) {
            return ((int)((time.Ticks / TicksPerSecond) % 60)); 
        }
 
        /*=================================GetFirstDayWeekOfYear========================== 
        **Action: Get the week of year using the FirstDay rule.
        **Returns:  the week of year. 
        **Arguments:
        **  time
        **  firstDayOfWeek  the first day of week (0=Sunday, 1=Monday, ... 6=Saturday)
        **Notes: 
        **  The CalendarWeekRule.FirstDay rule: Week 1 begins on the first day of the year.
        **  Assume f is the specifed firstDayOfWeek, 
        **  and n is the day of week for January 1 of the specified year. 
        **  Assign offset = n - f;
        **  Case 1: offset = 0 
        **      E.g.
        **                     f=1
        **          weekday 0  1  2  3  4  5  6  0  1
        **          date       1/1 
        **          week#      1                    2
        **      then week of year = (GetDayOfYear(time) - 1) / 7 + 1 
        ** 
        **  Case 2: offset < 0
        **      e.g. 
        **                     n=1   f=3
        **          weekday 0  1  2  3  4  5  6  0
        **          date       1/1
        **          week#      1     2 
        **      This means that the first week actually starts 5 days before 1/1.
        **      So week of year = (GetDayOfYear(time) + (7 + offset) - 1) / 7 + 1 
        **  Case 3: offset > 0 
        **      e.g.
        **                  f=0   n=2 
        **          weekday 0  1  2  3  4  5  6  0  1  2
        **          date          1/1
        **          week#         1                    2
        **      This means that the first week actually starts 2 days before 1/1. 
        **      So Week of year = (GetDayOfYear(time) + offset - 1) / 7 + 1
        ============================================================================*/ 
 
        internal int GetFirstDayWeekOfYear(DateTime time, int firstDayOfWeek) {
            int dayOfYear = GetDayOfYear(time) - 1;   // Make the day of year to be 0-based, so that 1/1 is day 0. 
            // Calculate the day of week for the first day of the year.
            // dayOfWeek - (dayOfYear % 7) is the day of week for the first day of this year.  Note that
            // this value can be less than 0.  It's fine since we are making it positive again in calculating offset.
            int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7); 
            int offset = (dayForJan1 - firstDayOfWeek + 14) % 7;
            BCLDebug.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0"); 
            return ((dayOfYear + offset) / 7 + 1); 
        }
 
        internal int GetWeekOfYearFullDays(DateTime time, CalendarWeekRule rule, int firstDayOfWeek, int fullDays) {
            int dayForJan1;
            int offset;
            int day; 

            int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0. 
            // 
            // Calculate the number of days between the first day of year (1/1) and the first day of the week.
            // This value will be a positive value from 0 ~ 6.  We call this value as "offset". 
            //
            // If offset is 0, it means that the 1/1 is the start of the first week.
            //     Assume the first day of the week is Monday, it will look like this:
            //     Sun      Mon     Tue     Wed     Thu     Fri     Sat 
            //     12/31    1/1     1/2     1/3     1/4     1/5     1/6
            //              +--> First week starts here. 
            // 
            // If offset is 1, it means that the first day of the week is 1 day ahead of 1/1.
            //     Assume the first day of the week is Monday, it will look like this: 
            //     Sun      Mon     Tue     Wed     Thu     Fri     Sat
            //     1/1      1/2     1/3     1/4     1/5     1/6     1/7
            //              +--> First week starts here.
            // 
            // If offset is 2, it means that the first day of the week is 2 days ahead of 1/1.
            //     Assume the first day of the week is Monday, it will look like this: 
            //     Sat      Sun     Mon     Tue     Wed     Thu     Fri     Sat 
            //     1/1      1/2     1/3     1/4     1/5     1/6     1/7     1/8
            //                      +--> First week starts here. 



            // Day of week is 0-based. 
            // Get the day of week for 1/1.  This can be derived from the day of week of the target day.
            // Note that we can get a negative value.  It's ok since we are going to make it a positive value when calculating the offset. 
            dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7); 

            // Now, calucalte the offset.  Substract the first day of week from the dayForJan1.  And make it a positive value. 
            offset = (firstDayOfWeek - dayForJan1 + 14) % 7;
            if (offset != 0 && offset >= fullDays)
            {
                // 
                // If the offset is greater than the value of fullDays, it means that
                // the first week of the year starts on the week where Jan/1 falls on. 
                // 
                offset -= 7;
            } 
            //
            // Calculate the day of year for specified time by taking offset into account.
            //
            day = dayOfYear - offset; 
            if (day >= 0) {
                // 
                // If the day of year value is greater than zero, get the week of year. 
                //
                return (day/7 + 1); 
            }
            //
            // Otherwise, the specified time falls on the week of previous year.
            // Call this method again by passing the last day of previous year. 
            //
            return (GetWeekOfYearFullDays(time.AddDays(-(dayOfYear+1)), rule, firstDayOfWeek, fullDays)); 
        } 

        // Returns the week of year for the specified DateTime. The returned value is an 
        // integer between 1 and 53.
        //

        public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) 
        {
            if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6) { 
                throw new ArgumentOutOfRangeException( 
                    "firstDayOfWeek", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"),
                    DayOfWeek.Sunday, DayOfWeek.Saturday)); 
            }
            switch (rule) {
                case CalendarWeekRule.FirstDay:
                    return (GetFirstDayWeekOfYear(time, (int)firstDayOfWeek)); 
                case CalendarWeekRule.FirstFullWeek:
                    return (GetWeekOfYearFullDays(time, rule, (int)firstDayOfWeek, 7)); 
                case CalendarWeekRule.FirstFourDayWeek: 
                    return (GetWeekOfYearFullDays(time, rule, (int)firstDayOfWeek, 4));
            } 
            throw new ArgumentOutOfRangeException(
                "rule", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"),
                CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek));
 
        }
 
        // Returns the year part of the specified DateTime. The returned value is an 
        // integer between 1 and 9999.
        // 

        public abstract int GetYear(DateTime time);

        // Checks whether a given day in the current era is a leap day. This method returns true if 
        // the date is a leap day, or false if not.
        // 
 
        public virtual bool IsLeapDay(int year, int month, int day)
        { 
            return (IsLeapDay(year, month, day, CurrentEra));
        }

        // Checks whether a given day in the specified era is a leap day. This method returns true if 
        // the date is a leap day, or false if not.
        // 
 
        public abstract bool IsLeapDay(int year, int month, int day, int era);
 
        // Checks whether a given month in the current era is a leap month. This method returns true if
        // month is a leap month, or false if not.
        //
 
        public virtual bool IsLeapMonth(int year, int month) {
            return (IsLeapMonth(year, month, CurrentEra)); 
        } 

        // Checks whether a given month in the specified era is a leap month. This method returns true if 
        // month is a leap month, or false if not.
        //

        public abstract bool IsLeapMonth(int year, int month, int era); 

        // Returns  the leap month in a calendar year of the current era. This method returns 0 
        // if this calendar does not have leap month, or this year is not a leap year. 
        //
 
        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual int GetLeapMonth(int year)
        {
            return (GetLeapMonth(year, CurrentEra)); 
        }
 
        // Returns  the leap month in a calendar year of the specified era. This method returns 0 
        // if this calendar does not have leap month, or this year is not a leap year.
        // 

        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual int GetLeapMonth(int year, int era)
        { 
            if (!IsLeapYear(year, era))
                return 0; 
 
            int monthsCount = GetMonthsInYear(year, era);
            for (int month=1; month<=monthsCount; month++) 
            {
                if (IsLeapMonth(year, month, era))
                    return month;
            } 

            return 0; 
        } 

        // Checks whether a given year in the current era is a leap year. This method returns true if 
        // year is a leap year, or false if not.
        //

        public virtual bool IsLeapYear(int year) 
        {
            return (IsLeapYear(year, CurrentEra)); 
        } 

        // Checks whether a given year in the specified era is a leap year. This method returns true if 
        // year is a leap year, or false if not.
        //

        public abstract bool IsLeapYear(int year, int era); 

        // Returns the date and time converted to a DateTime value.  Throws an exception if the n-tuple is invalid. 
        // 

        public virtual DateTime ToDateTime(int year, int month,  int day, int hour, int minute, int second, int millisecond) 
        {
            return (ToDateTime(year, month, day, hour, minute, second, millisecond, CurrentEra));
        }
 
        // Returns the date and time converted to a DateTime value.  Throws an exception if the n-tuple is invalid.
        // 
 
        public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
 
        internal virtual Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) {
            result = DateTime.MinValue;
            try {
                result = ToDateTime(year, month, day, hour, minute, second, millisecond, era); 
                return true;
            } 
            catch (ArgumentException) { 
                return false;
            } 
        }

        internal virtual bool IsValidYear(int year, int era) {
            return (year >= GetYear(MinSupportedDateTime) && year <= GetYear(MaxSupportedDateTime)); 
        }
 
        internal virtual bool IsValidMonth(int year, int month, int era) { 
            return (IsValidYear(year, era) && month >= 1 && month <= GetMonthsInYear(year, era));
        } 

        internal virtual bool IsValidDay(int year, int month, int day, int era)
        {
            return (IsValidMonth(year, month, era) && day >= 1 && day <= GetDaysInMonth(year, month, era)); 
        }
 
 

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern int nativeGetTwoDigitYearMax(int calID);

        // Returns and assigns the maximum value to represent a two digit year.  This
        // value is the upper boundary of a 100 year range that allows a two digit year 
        // to be properly translated to a four digit year.  For example, if 2029 is the
        // upper boundary, then a two digit value of 30 should be interpreted as 1930 
        // while a two digit value of 29 should be interpreted as 2029.  In this example 
        // , the 100 year range would be from 1930-2029.  See ToFourDigitYear().
 
        public virtual int TwoDigitYearMax
        {
            get
            { 
                return (twoDigitYearMax);
            } 
 
            set
            { 
                VerifyWritable();
                twoDigitYearMax = value;
            }
        } 

        // Converts the year value to the appropriate century by using the 
        // TwoDigitYearMax property.  For example, if the TwoDigitYearMax value is 2029, 
        // then a two digit value of 30 will get converted to 1930 while a two digit
        // value of 29 will get converted to 2029. 

        public virtual int ToFourDigitYear(int year) {
            if (year < 0) {
                throw new ArgumentOutOfRangeException("year", 
                    Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            } 
            if (year < 100) { 
                return ((TwoDigitYearMax/100 - ( year > TwoDigitYearMax % 100 ? 1 : 0))*100 + year);
            } 
            // If the year value is above 100, just return the year value.  Don't have to do
            // the TwoDigitYearMax comparison.
            return (year);
        } 

        // Return the tick count corresponding to the given hour, minute, second. 
        // Will check the if the parameters are valid. 
        internal static long TimeToTicks(int hour, int minute, int second, int millisecond)
        { 
            if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >=0 && second < 60)
            {
                if (millisecond < 0 || millisecond >= MillisPerSecond) {
                    throw new ArgumentOutOfRangeException( 
                                "millisecond",
                                String.Format( 
                                    CultureInfo.InvariantCulture, 
                                    Environment.GetResourceString("ArgumentOutOfRange_Range"), 0, MillisPerSecond - 1));
                } 
                return TimeSpan.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond;
            }
            throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"));
        } 

#if !FEATURE_PAL 
        private const String TwoDigitYearMaxSubKey = "Control Panel\\International\\Calendars\\TwoDigitYearMax"; 
#endif
 

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        internal static int GetSystemTwoDigitYearSetting(int CalID, int defaultYearValue) 
        {
 
            // 
            // Call Win32 ::GetCalendarInfo() to retrieve CAL_ITWODIGITYEARMAX value.
            // This function only exists after Windows 98 and Windows 2000. 
            //

            int twoDigitYearMax = nativeGetTwoDigitYearMax(CalID);
            if (twoDigitYearMax < 0) 
            {
#if !FEATURE_PAL 
                // 
                // The Win32 call fails, use the registry setting instead.
                // 
                Microsoft.Win32.RegistryKey key = null;

                try
                { 
                    key = Microsoft.Win32.Registry.CurrentUser.InternalOpenSubKey(TwoDigitYearMaxSubKey, false);
                } 
                // If we can't read the key, we'll just keep going anyway. 
                catch (ObjectDisposedException)
                { 
                }
                catch (ArgumentException)
                {
                } 

                if (key != null) 
                { 
                    try {
                        Object value = key.InternalGetValue(CalID.ToString(CultureInfo.InvariantCulture), null, false, false); 
                        if (value != null)
                        {
                            try
                            { 
                                twoDigitYearMax = Int32.Parse(value.ToString(), CultureInfo.InvariantCulture);
                            } 
                            // 
                            // If error happens in parsing the string. Leave as it is. We will
                            // set twoDigitYearMax to the default value later. 
                            //
                            catch (ArgumentException)
                            {
                            } 
                            catch (FormatException)
                            { 
                            } 
                            catch (OverflowException)
                            { 
                            }
                        }
                    }
                    finally { 
                        key.Close();
                    } 
                } 

                if (twoDigitYearMax < 0) 
                {
#endif // !FEATURE_PAL
                    twoDigitYearMax = defaultYearValue;
#if !FEATURE_PAL 
                }
#endif //!FEATURE_PAL 
            } 
            return (twoDigitYearMax);
        } 

    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
namespace System.Globalization {
    using System; 
    using System.Runtime.CompilerServices; 
    using System.Globalization;
    using System.Runtime.Versioning; 

    // This abstract class represents a calendar. A calendar reckons time in
    // divisions such as weeks, months and years. The number, length and start of
    // the divisions vary in each calendar. 
    //
    // Any instant in time can be represented as an n-tuple of numeric values using 
    // a particular calendar. For example, the next vernal equinox occurs at (0.0, 0 
    // , 46, 8, 20, 3, 1999) in the Gregorian calendar. An  implementation of
    // Calendar can map any DateTime value to such an n-tuple and vice versa. The 
    // DateTimeFormat class can map between such n-tuples and a textual
    // representation such as "8:46 AM [....] 20th 1999 AD".
    //
    // Most calendars identify a year which begins the current era. There may be any 
    // number of previous eras. The Calendar class identifies the eras as enumerated
    // integers where the current era (CurrentEra) has the value zero. 
    // 
    // For consistency, the first unit in each interval, e.g. the first month, is
    // assigned the value one. 
     // The calculation of hour/minute/second is moved to Calendar from GregorianCalendar,
     // since most of the calendars (or all?) have the same way of calcuating hour/minute/second.

    [Serializable] 
    [System.Runtime.InteropServices.ComVisible(true)]
    public abstract class Calendar : ICloneable 
    { 

        // Number of 100ns (10E-7 second) ticks per time unit 
        internal const long TicksPerMillisecond   = 10000;
        internal const long TicksPerSecond        = TicksPerMillisecond * 1000;
        internal const long TicksPerMinute        = TicksPerSecond * 60;
        internal const long TicksPerHour          = TicksPerMinute * 60; 
        internal const long TicksPerDay           = TicksPerHour * 24;
 
        // Number of milliseconds per time unit 
        internal const int MillisPerSecond        = 1000;
        internal const int MillisPerMinute        = MillisPerSecond * 60; 
        internal const int MillisPerHour          = MillisPerMinute * 60;
        internal const int MillisPerDay           = MillisPerHour * 24;

        // Number of days in a non-leap year 
        internal const int DaysPerYear            = 365;
        // Number of days in 4 years 
        internal const int DaysPer4Years          = DaysPerYear * 4 + 1; 
        // Number of days in 100 years
        internal const int DaysPer100Years        = DaysPer4Years * 25 - 1; 
        // Number of days in 400 years
        internal const int DaysPer400Years        = DaysPer100Years * 4 + 1;

        // Number of days from 1/1/0001 to 1/1/10000 
        internal const int DaysTo10000            = DaysPer400Years * 25 - 366;
 
        internal const long MaxMillis             = (long)DaysTo10000 * MillisPerDay; 

        // 
        //  Calendar ID Values.  This is used to get data from calendar.nlp.
        //  The order of calendar ID means the order of data items in the table.
        //
 
        internal const int CAL_GREGORIAN                  = 1 ;     // Gregorian (localized) calendar
        internal const int CAL_GREGORIAN_US               = 2 ;     // Gregorian (U.S.) calendar 
        internal const int CAL_JAPAN                      = 3 ;     // Japanese Emperor Era calendar 
        internal const int CAL_TAIWAN                     = 4 ;     // Taiwan Era calendar
        internal const int CAL_KOREA                      = 5 ;     // Korean Tangun Era calendar 
        internal const int CAL_HIJRI                      = 6 ;     // Hijri (Arabic Lunar) calendar
        internal const int CAL_THAI                       = 7 ;     // Thai calendar
        internal const int CAL_HEBREW                     = 8 ;     // Hebrew (Lunar) calendar
        internal const int CAL_GREGORIAN_ME_FRENCH        = 9 ;     // Gregorian Middle East French calendar 
        internal const int CAL_GREGORIAN_ARABIC           = 10;     // Gregorian Arabic calendar
        internal const int CAL_GREGORIAN_XLIT_ENGLISH     = 11;     // Gregorian Transliterated English calendar 
        internal const int CAL_GREGORIAN_XLIT_FRENCH      = 12; 
        internal const int CAL_JULIAN                     = 13;
        internal const int CAL_JAPANESELUNISOLAR          = 14; 
        internal const int CAL_CHINESELUNISOLAR           = 15;
        internal const int CAL_SAKA                       = 16;     // reserved to match Office but not implemented in our code
        internal const int CAL_LUNAR_ETO_CHN              = 17;     // reserved to match Office but not implemented in our code
        internal const int CAL_LUNAR_ETO_KOR              = 18;     // reserved to match Office but not implemented in our code 
        internal const int CAL_LUNAR_ETO_ROKUYOU          = 19;     // reserved to match Office but not implemented in our code
        internal const int CAL_KOREANLUNISOLAR            = 20; 
        internal const int CAL_TAIWANLUNISOLAR            = 21; 
        internal const int CAL_PERSIAN                    = 22;
        internal const int CAL_UMALQURA                   = 23; 

        internal int m_currentEraValue = -1;

        [System.Runtime.Serialization.OptionalField(VersionAdded = 2)] 
        private bool m_isReadOnly = false;
 
        // The minimum supported DateTime range for the calendar. 

        [System.Runtime.InteropServices.ComVisible(false)] 
        public virtual DateTime MinSupportedDateTime
        {
            get
            { 
                return (DateTime.MinValue);
            } 
        } 

        // The maximum supported DateTime range for the calendar. 

        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual DateTime MaxSupportedDateTime
        { 
            get
            { 
                return (DateTime.MaxValue); 
            }
        } 



 
        protected Calendar() {
            //Do-nothing constructor. 
        } 

        /// 
        // This can not be abstract, otherwise no one can create a subclass of Calendar.
        //
        internal virtual int ID {
            get { 
                return (-1);
            } 
        } 

        /// 
        // Return the Base calendar ID for calendars that didn't have defined data in culture.nlp
        //

        internal virtual int BaseCalendarID 
        {
            get { return ID; } 
        } 

        // Returns  the type of the calendar. 
        //
        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual CalendarAlgorithmType AlgorithmType
        { 
            get
            { 
                return CalendarAlgorithmType.Unknown; 
            }
        } 

        ////////////////////////////////////////////////////////////////////////
        //
        //  IsReadOnly 
        //
        //  Detect if the object is readonly. 
        // 
        ////////////////////////////////////////////////////////////////////////
        [System.Runtime.InteropServices.ComVisible(false)] 
        public bool IsReadOnly
        {
            get { return (m_isReadOnly); }
        } 

        //////////////////////////////////////////////////////////////////////// 
        // 
        //  Clone
        // 
        //  Is the implementation of IColnable.
        //
        ////////////////////////////////////////////////////////////////////////
        [System.Runtime.InteropServices.ComVisible(false)] 
        public virtual Object Clone()
        { 
            object o = MemberwiseClone(); 
            ((Calendar) o).SetReadOnlyState(false);
            return (o); 
        }

        ////////////////////////////////////////////////////////////////////////
        // 
        //  ReadOnly
        // 
        //  Create a cloned readonly instance or return the input one if it is 
        //  readonly.
        // 
        ////////////////////////////////////////////////////////////////////////
        [System.Runtime.InteropServices.ComVisible(false)]
        public static Calendar ReadOnly(Calendar calendar)
        { 
            if (calendar == null)       { throw new ArgumentNullException("calendar"); }
            if (calendar.IsReadOnly)    { return (calendar); } 
 
            Calendar clonedCalendar = (Calendar)(calendar.MemberwiseClone());
            clonedCalendar.SetReadOnlyState(true); 

            return (clonedCalendar);
        }
 
        internal void VerifyWritable()
        { 
            if (m_isReadOnly) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); 
            }
        }

        internal void SetReadOnlyState(bool readOnly) 
        {
            m_isReadOnly = readOnly; 
        } 

 
        /*=================================CurrentEraValue==========================
        **Action: This is used to convert CurretEra(0) to an appropriate era value.
        **Returns:
        **Arguments: 
        **Exceptions:
        **Notes: 
        ** The value is from calendar.nlp. 
        ============================================================================*/
 
        internal virtual int CurrentEraValue {
            get {
                // The following code assumes that the current era value can not be -1.
                if (m_currentEraValue == -1) { 
                    BCLDebug.Assert(BaseCalendarID > 0, "[Calendar.CurrentEraValue] Expected ID > 0");
                    m_currentEraValue = CalendarTable.Default.ICURRENTERA(BaseCalendarID); 
                } 
                return (m_currentEraValue);
            } 
        }

        // The current era for a calendar.
 
        public const int CurrentEra = 0;
 
        internal int twoDigitYearMax = -1; 

        internal static void CheckAddResult(long ticks, DateTime minValue, DateTime maxValue) { 
            if (ticks < minValue.Ticks || ticks > maxValue.Ticks) {
                throw new ArgumentException(
                    String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Argument_ResultCalendarRange"),
                        minValue, maxValue)); 
            }
        } 
 
        internal DateTime Add(DateTime time, double value, int scale) {
            long millis = (long)(value * scale + (value >= 0? 0.5: -0.5)); 
            if (millis <= -MaxMillis || millis >= MaxMillis) {
                throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue"));
            }
            long ticks = time.Ticks + millis * TicksPerMillisecond; 
            CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
            return (new DateTime(ticks)); 
        } 

        // Returns the DateTime resulting from adding the given number of 
        // milliseconds to the specified DateTime. The result is computed by rounding
        // the number of milliseconds given by value to the nearest integer,
        // and adding that interval to the specified DateTime. The value
        // argument is permitted to be negative. 
        //
 
        public virtual DateTime AddMilliseconds(DateTime time, double milliseconds) { 
            return (Add(time, milliseconds, 1));
        } 


        // Returns the DateTime resulting from adding a fractional number of
        // days to the specified DateTime. The result is computed by rounding the 
        // fractional number of days given by value to the nearest
        // millisecond, and adding that interval to the specified DateTime. The 
        // value argument is permitted to be negative. 
        //
 
        public virtual DateTime AddDays(DateTime time, int days) {
            return (Add(time, days, MillisPerDay));
        }
 
        // Returns the DateTime resulting from adding a fractional number of
        // hours to the specified DateTime. The result is computed by rounding the 
        // fractional number of hours given by value to the nearest 
        // millisecond, and adding that interval to the specified DateTime. The
        // value argument is permitted to be negative. 
        //

        public virtual DateTime AddHours(DateTime time, int hours) {
            return (Add(time, hours, MillisPerHour)); 
        }
 
 
        // Returns the DateTime resulting from adding a fractional number of
        // minutes to the specified DateTime. The result is computed by rounding the 
        // fractional number of minutes given by value to the nearest
        // millisecond, and adding that interval to the specified DateTime. The
        // value argument is permitted to be negative.
        // 

        public virtual DateTime AddMinutes(DateTime time, int minutes) { 
            return (Add(time, minutes, MillisPerMinute)); 
        }
 

        // Returns the DateTime resulting from adding the given number of
        // months to the specified DateTime. The result is computed by incrementing
        // (or decrementing) the year and month parts of the specified DateTime by 
        // value months, and, if required, adjusting the day part of the
        // resulting date downwards to the last day of the resulting month in the 
        // resulting year. The time-of-day part of the result is the same as the 
        // time-of-day part of the specified DateTime.
        // 
        // In more precise terms, considering the specified DateTime to be of the
        // form y / m / d + t, where y is the
        // year, m is the month, d is the day, and t is the
        // time-of-day, the result is y1 / m1 / d1 + t, 
        // where y1 and m1 are computed by adding value months
        // to y and m, and d1 is the largest value less than 
        // or equal to d that denotes a valid day in month m1 of year 
        // y1.
        // 

        public abstract DateTime AddMonths(DateTime time, int months);

        // Returns the DateTime resulting from adding a number of 
        // seconds to the specified DateTime. The result is computed by rounding the
        // fractional number of seconds given by value to the nearest 
        // millisecond, and adding that interval to the specified DateTime. The 
        // value argument is permitted to be negative.
        // 

        public virtual DateTime AddSeconds(DateTime time, int seconds) {
            return Add(time, seconds, MillisPerSecond);
        } 

        // Returns the DateTime resulting from adding a number of 
        // weeks to the specified DateTime. The 
        // value argument is permitted to be negative.
        // 

        public virtual DateTime AddWeeks(DateTime time, int weeks) {
            return (AddDays(time, weeks * 7));
        } 

 
        // Returns the DateTime resulting from adding the given number of 
        // years to the specified DateTime. The result is computed by incrementing
        // (or decrementing) the year part of the specified DateTime by value 
        // years. If the month and day of the specified DateTime is 2/29, and if the
        // resulting year is not a leap year, the month and day of the resulting
        // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
        // parts of the result are the same as those of the specified DateTime. 
        //
 
        public abstract DateTime AddYears(DateTime time, int years); 

        // Returns the day-of-month part of the specified DateTime. The returned 
        // value is an integer between 1 and 31.
        //

        public abstract int GetDayOfMonth(DateTime time); 

        // Returns the day-of-week part of the specified DateTime. The returned value 
        // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates 
        // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
        // Thursday, 5 indicates Friday, and 6 indicates Saturday. 
        //

        public abstract DayOfWeek GetDayOfWeek(DateTime time);
 
        // Returns the day-of-year part of the specified DateTime. The returned value
        // is an integer between 1 and 366. 
        // 

        public abstract int GetDayOfYear(DateTime time); 

        // Returns the number of days in the month given by the year and
        // month arguments.
        // 

        public virtual int GetDaysInMonth(int year, int month) 
        { 
            return (GetDaysInMonth(year, month, CurrentEra));
        } 

        // Returns the number of days in the month given by the year and
        // month arguments for the specified era.
        // 

        public abstract int GetDaysInMonth(int year, int month, int era); 
 
        // Returns the number of days in the year given by the year argument for the current era.
        // 

        public virtual int GetDaysInYear(int year)
        {
            return (GetDaysInYear(year, CurrentEra)); 
        }
 
        // Returns the number of days in the year given by the year argument for the current era. 
        //
 
        public abstract int GetDaysInYear(int year, int era);

        // Returns the era for the specified DateTime value.
 
        public abstract int GetEra(DateTime time);
 
        /*=================================Eras========================== 
        **Action: Get the list of era values.
        **Returns: The int array of the era names supported in this calendar. 
        **      null if era is not used.
        **Arguments: None.
        **Exceptions: None.
        ============================================================================*/ 

 
        public abstract int[] Eras { 
            get;
        } 


        // Returns the hour part of the specified DateTime. The returned value is an
        // integer between 0 and 23. 
        //
 
        public virtual int GetHour(DateTime time) { 
            return ((int)((time.Ticks / TicksPerHour) % 24));
        } 

        // Returns the millisecond part of the specified DateTime. The returned value
        // is an integer between 0 and 999.
        // 

        public virtual double GetMilliseconds(DateTime time) { 
            return (double)((time.Ticks / TicksPerMillisecond) % 1000); 
        }
 
        // Returns the minute part of the specified DateTime. The returned value is
        // an integer between 0 and 59.
        //
 
        public virtual int GetMinute(DateTime time) {
            return ((int)((time.Ticks / TicksPerMinute) % 60)); 
        } 

        // Returns the month part of the specified DateTime. The returned value is an 
        // integer between 1 and 12.
        //

        public abstract int GetMonth(DateTime time); 

        // Returns the number of months in the specified year in the current era. 
 
        public virtual int GetMonthsInYear(int year)
        { 
            return (GetMonthsInYear(year, CurrentEra));
        }

        // Returns the number of months in the specified year and era. 

        public abstract int GetMonthsInYear(int year, int era); 
 
        // Returns the second part of the specified DateTime. The returned value is
        // an integer between 0 and 59. 
        //

        public virtual int GetSecond(DateTime time) {
            return ((int)((time.Ticks / TicksPerSecond) % 60)); 
        }
 
        /*=================================GetFirstDayWeekOfYear========================== 
        **Action: Get the week of year using the FirstDay rule.
        **Returns:  the week of year. 
        **Arguments:
        **  time
        **  firstDayOfWeek  the first day of week (0=Sunday, 1=Monday, ... 6=Saturday)
        **Notes: 
        **  The CalendarWeekRule.FirstDay rule: Week 1 begins on the first day of the year.
        **  Assume f is the specifed firstDayOfWeek, 
        **  and n is the day of week for January 1 of the specified year. 
        **  Assign offset = n - f;
        **  Case 1: offset = 0 
        **      E.g.
        **                     f=1
        **          weekday 0  1  2  3  4  5  6  0  1
        **          date       1/1 
        **          week#      1                    2
        **      then week of year = (GetDayOfYear(time) - 1) / 7 + 1 
        ** 
        **  Case 2: offset < 0
        **      e.g. 
        **                     n=1   f=3
        **          weekday 0  1  2  3  4  5  6  0
        **          date       1/1
        **          week#      1     2 
        **      This means that the first week actually starts 5 days before 1/1.
        **      So week of year = (GetDayOfYear(time) + (7 + offset) - 1) / 7 + 1 
        **  Case 3: offset > 0 
        **      e.g.
        **                  f=0   n=2 
        **          weekday 0  1  2  3  4  5  6  0  1  2
        **          date          1/1
        **          week#         1                    2
        **      This means that the first week actually starts 2 days before 1/1. 
        **      So Week of year = (GetDayOfYear(time) + offset - 1) / 7 + 1
        ============================================================================*/ 
 
        internal int GetFirstDayWeekOfYear(DateTime time, int firstDayOfWeek) {
            int dayOfYear = GetDayOfYear(time) - 1;   // Make the day of year to be 0-based, so that 1/1 is day 0. 
            // Calculate the day of week for the first day of the year.
            // dayOfWeek - (dayOfYear % 7) is the day of week for the first day of this year.  Note that
            // this value can be less than 0.  It's fine since we are making it positive again in calculating offset.
            int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7); 
            int offset = (dayForJan1 - firstDayOfWeek + 14) % 7;
            BCLDebug.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0"); 
            return ((dayOfYear + offset) / 7 + 1); 
        }
 
        internal int GetWeekOfYearFullDays(DateTime time, CalendarWeekRule rule, int firstDayOfWeek, int fullDays) {
            int dayForJan1;
            int offset;
            int day; 

            int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0. 
            // 
            // Calculate the number of days between the first day of year (1/1) and the first day of the week.
            // This value will be a positive value from 0 ~ 6.  We call this value as "offset". 
            //
            // If offset is 0, it means that the 1/1 is the start of the first week.
            //     Assume the first day of the week is Monday, it will look like this:
            //     Sun      Mon     Tue     Wed     Thu     Fri     Sat 
            //     12/31    1/1     1/2     1/3     1/4     1/5     1/6
            //              +--> First week starts here. 
            // 
            // If offset is 1, it means that the first day of the week is 1 day ahead of 1/1.
            //     Assume the first day of the week is Monday, it will look like this: 
            //     Sun      Mon     Tue     Wed     Thu     Fri     Sat
            //     1/1      1/2     1/3     1/4     1/5     1/6     1/7
            //              +--> First week starts here.
            // 
            // If offset is 2, it means that the first day of the week is 2 days ahead of 1/1.
            //     Assume the first day of the week is Monday, it will look like this: 
            //     Sat      Sun     Mon     Tue     Wed     Thu     Fri     Sat 
            //     1/1      1/2     1/3     1/4     1/5     1/6     1/7     1/8
            //                      +--> First week starts here. 



            // Day of week is 0-based. 
            // Get the day of week for 1/1.  This can be derived from the day of week of the target day.
            // Note that we can get a negative value.  It's ok since we are going to make it a positive value when calculating the offset. 
            dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7); 

            // Now, calucalte the offset.  Substract the first day of week from the dayForJan1.  And make it a positive value. 
            offset = (firstDayOfWeek - dayForJan1 + 14) % 7;
            if (offset != 0 && offset >= fullDays)
            {
                // 
                // If the offset is greater than the value of fullDays, it means that
                // the first week of the year starts on the week where Jan/1 falls on. 
                // 
                offset -= 7;
            } 
            //
            // Calculate the day of year for specified time by taking offset into account.
            //
            day = dayOfYear - offset; 
            if (day >= 0) {
                // 
                // If the day of year value is greater than zero, get the week of year. 
                //
                return (day/7 + 1); 
            }
            //
            // Otherwise, the specified time falls on the week of previous year.
            // Call this method again by passing the last day of previous year. 
            //
            return (GetWeekOfYearFullDays(time.AddDays(-(dayOfYear+1)), rule, firstDayOfWeek, fullDays)); 
        } 

        // Returns the week of year for the specified DateTime. The returned value is an 
        // integer between 1 and 53.
        //

        public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) 
        {
            if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6) { 
                throw new ArgumentOutOfRangeException( 
                    "firstDayOfWeek", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"),
                    DayOfWeek.Sunday, DayOfWeek.Saturday)); 
            }
            switch (rule) {
                case CalendarWeekRule.FirstDay:
                    return (GetFirstDayWeekOfYear(time, (int)firstDayOfWeek)); 
                case CalendarWeekRule.FirstFullWeek:
                    return (GetWeekOfYearFullDays(time, rule, (int)firstDayOfWeek, 7)); 
                case CalendarWeekRule.FirstFourDayWeek: 
                    return (GetWeekOfYearFullDays(time, rule, (int)firstDayOfWeek, 4));
            } 
            throw new ArgumentOutOfRangeException(
                "rule", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"),
                CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek));
 
        }
 
        // Returns the year part of the specified DateTime. The returned value is an 
        // integer between 1 and 9999.
        // 

        public abstract int GetYear(DateTime time);

        // Checks whether a given day in the current era is a leap day. This method returns true if 
        // the date is a leap day, or false if not.
        // 
 
        public virtual bool IsLeapDay(int year, int month, int day)
        { 
            return (IsLeapDay(year, month, day, CurrentEra));
        }

        // Checks whether a given day in the specified era is a leap day. This method returns true if 
        // the date is a leap day, or false if not.
        // 
 
        public abstract bool IsLeapDay(int year, int month, int day, int era);
 
        // Checks whether a given month in the current era is a leap month. This method returns true if
        // month is a leap month, or false if not.
        //
 
        public virtual bool IsLeapMonth(int year, int month) {
            return (IsLeapMonth(year, month, CurrentEra)); 
        } 

        // Checks whether a given month in the specified era is a leap month. This method returns true if 
        // month is a leap month, or false if not.
        //

        public abstract bool IsLeapMonth(int year, int month, int era); 

        // Returns  the leap month in a calendar year of the current era. This method returns 0 
        // if this calendar does not have leap month, or this year is not a leap year. 
        //
 
        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual int GetLeapMonth(int year)
        {
            return (GetLeapMonth(year, CurrentEra)); 
        }
 
        // Returns  the leap month in a calendar year of the specified era. This method returns 0 
        // if this calendar does not have leap month, or this year is not a leap year.
        // 

        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual int GetLeapMonth(int year, int era)
        { 
            if (!IsLeapYear(year, era))
                return 0; 
 
            int monthsCount = GetMonthsInYear(year, era);
            for (int month=1; month<=monthsCount; month++) 
            {
                if (IsLeapMonth(year, month, era))
                    return month;
            } 

            return 0; 
        } 

        // Checks whether a given year in the current era is a leap year. This method returns true if 
        // year is a leap year, or false if not.
        //

        public virtual bool IsLeapYear(int year) 
        {
            return (IsLeapYear(year, CurrentEra)); 
        } 

        // Checks whether a given year in the specified era is a leap year. This method returns true if 
        // year is a leap year, or false if not.
        //

        public abstract bool IsLeapYear(int year, int era); 

        // Returns the date and time converted to a DateTime value.  Throws an exception if the n-tuple is invalid. 
        // 

        public virtual DateTime ToDateTime(int year, int month,  int day, int hour, int minute, int second, int millisecond) 
        {
            return (ToDateTime(year, month, day, hour, minute, second, millisecond, CurrentEra));
        }
 
        // Returns the date and time converted to a DateTime value.  Throws an exception if the n-tuple is invalid.
        // 
 
        public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
 
        internal virtual Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) {
            result = DateTime.MinValue;
            try {
                result = ToDateTime(year, month, day, hour, minute, second, millisecond, era); 
                return true;
            } 
            catch (ArgumentException) { 
                return false;
            } 
        }

        internal virtual bool IsValidYear(int year, int era) {
            return (year >= GetYear(MinSupportedDateTime) && year <= GetYear(MaxSupportedDateTime)); 
        }
 
        internal virtual bool IsValidMonth(int year, int month, int era) { 
            return (IsValidYear(year, era) && month >= 1 && month <= GetMonthsInYear(year, era));
        } 

        internal virtual bool IsValidDay(int year, int month, int day, int era)
        {
            return (IsValidMonth(year, month, era) && day >= 1 && day <= GetDaysInMonth(year, month, era)); 
        }
 
 

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern int nativeGetTwoDigitYearMax(int calID);

        // Returns and assigns the maximum value to represent a two digit year.  This
        // value is the upper boundary of a 100 year range that allows a two digit year 
        // to be properly translated to a four digit year.  For example, if 2029 is the
        // upper boundary, then a two digit value of 30 should be interpreted as 1930 
        // while a two digit value of 29 should be interpreted as 2029.  In this example 
        // , the 100 year range would be from 1930-2029.  See ToFourDigitYear().
 
        public virtual int TwoDigitYearMax
        {
            get
            { 
                return (twoDigitYearMax);
            } 
 
            set
            { 
                VerifyWritable();
                twoDigitYearMax = value;
            }
        } 

        // Converts the year value to the appropriate century by using the 
        // TwoDigitYearMax property.  For example, if the TwoDigitYearMax value is 2029, 
        // then a two digit value of 30 will get converted to 1930 while a two digit
        // value of 29 will get converted to 2029. 

        public virtual int ToFourDigitYear(int year) {
            if (year < 0) {
                throw new ArgumentOutOfRangeException("year", 
                    Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            } 
            if (year < 100) { 
                return ((TwoDigitYearMax/100 - ( year > TwoDigitYearMax % 100 ? 1 : 0))*100 + year);
            } 
            // If the year value is above 100, just return the year value.  Don't have to do
            // the TwoDigitYearMax comparison.
            return (year);
        } 

        // Return the tick count corresponding to the given hour, minute, second. 
        // Will check the if the parameters are valid. 
        internal static long TimeToTicks(int hour, int minute, int second, int millisecond)
        { 
            if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >=0 && second < 60)
            {
                if (millisecond < 0 || millisecond >= MillisPerSecond) {
                    throw new ArgumentOutOfRangeException( 
                                "millisecond",
                                String.Format( 
                                    CultureInfo.InvariantCulture, 
                                    Environment.GetResourceString("ArgumentOutOfRange_Range"), 0, MillisPerSecond - 1));
                } 
                return TimeSpan.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond;
            }
            throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"));
        } 

#if !FEATURE_PAL 
        private const String TwoDigitYearMaxSubKey = "Control Panel\\International\\Calendars\\TwoDigitYearMax"; 
#endif
 

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        internal static int GetSystemTwoDigitYearSetting(int CalID, int defaultYearValue) 
        {
 
            // 
            // Call Win32 ::GetCalendarInfo() to retrieve CAL_ITWODIGITYEARMAX value.
            // This function only exists after Windows 98 and Windows 2000. 
            //

            int twoDigitYearMax = nativeGetTwoDigitYearMax(CalID);
            if (twoDigitYearMax < 0) 
            {
#if !FEATURE_PAL 
                // 
                // The Win32 call fails, use the registry setting instead.
                // 
                Microsoft.Win32.RegistryKey key = null;

                try
                { 
                    key = Microsoft.Win32.Registry.CurrentUser.InternalOpenSubKey(TwoDigitYearMaxSubKey, false);
                } 
                // If we can't read the key, we'll just keep going anyway. 
                catch (ObjectDisposedException)
                { 
                }
                catch (ArgumentException)
                {
                } 

                if (key != null) 
                { 
                    try {
                        Object value = key.InternalGetValue(CalID.ToString(CultureInfo.InvariantCulture), null, false, false); 
                        if (value != null)
                        {
                            try
                            { 
                                twoDigitYearMax = Int32.Parse(value.ToString(), CultureInfo.InvariantCulture);
                            } 
                            // 
                            // If error happens in parsing the string. Leave as it is. We will
                            // set twoDigitYearMax to the default value later. 
                            //
                            catch (ArgumentException)
                            {
                            } 
                            catch (FormatException)
                            { 
                            } 
                            catch (OverflowException)
                            { 
                            }
                        }
                    }
                    finally { 
                        key.Close();
                    } 
                } 

                if (twoDigitYearMax < 0) 
                {
#endif // !FEATURE_PAL
                    twoDigitYearMax = defaultYearValue;
#if !FEATURE_PAL 
                }
#endif //!FEATURE_PAL 
            } 
            return (twoDigitYearMax);
        } 

    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK