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

  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.     using System;
  18.     using System.Runtime.CompilerServices;
  19.     using System.Globalization;
  20.     using System.Runtime.Versioning;
  21.    
  22.     // This abstract class represents a calendar. A calendar reckons time in
  23.     // divisions such as weeks, months and years. The number, length and start of
  24.     // the divisions vary in each calendar.
  25.     //
  26.     // Any instant in time can be represented as an n-tuple of numeric values using
  27.     // a particular calendar. For example, the next vernal equinox occurs at (0.0, 0
  28.     // , 46, 8, 20, 3, 1999) in the Gregorian calendar. An implementation of
  29.     // Calendar can map any DateTime value to such an n-tuple and vice versa. The
  30.     // DateTimeFormat class can map between such n-tuples and a textual
  31.     // representation such as "8:46 AM March 20th 1999 AD".
  32.     //
  33.     // Most calendars identify a year which begins the current era. There may be any
  34.     // number of previous eras. The Calendar class identifies the eras as enumerated
  35.     // integers where the current era (CurrentEra) has the value zero.
  36.     //
  37.     // For consistency, the first unit in each interval, e.g. the first month, is
  38.     // assigned the value one.
  39.     // The calculation of hour/minute/second is moved to Calendar from GregorianCalendar,
  40.     // since most of the calendars (or all?) have the same way of calcuating hour/minute/second.
  41.    
  42.     [Serializable()]
  43.     [System.Runtime.InteropServices.ComVisible(true)]
  44.     public abstract class Calendar : ICloneable
  45.     {
  46.        
  47.         // Number of 100ns (10E-7 second) ticks per time unit
  48.         internal const long TicksPerMillisecond = 10000;
  49.         internal const long TicksPerSecond = TicksPerMillisecond * 1000;
  50.         internal const long TicksPerMinute = TicksPerSecond * 60;
  51.         internal const long TicksPerHour = TicksPerMinute * 60;
  52.         internal const long TicksPerDay = TicksPerHour * 24;
  53.        
  54.         // Number of milliseconds per time unit
  55.         internal const int MillisPerSecond = 1000;
  56.         internal const int MillisPerMinute = MillisPerSecond * 60;
  57.         internal const int MillisPerHour = MillisPerMinute * 60;
  58.         internal const int MillisPerDay = MillisPerHour * 24;
  59.        
  60.         // Number of days in a non-leap year
  61.         internal const int DaysPerYear = 365;
  62.         // Number of days in 4 years
  63.         internal const int DaysPer4Years = DaysPerYear * 4 + 1;
  64.         // Number of days in 100 years
  65.         internal const int DaysPer100Years = DaysPer4Years * 25 - 1;
  66.         // Number of days in 400 years
  67.         internal const int DaysPer400Years = DaysPer100Years * 4 + 1;
  68.        
  69.         // Number of days from 1/1/0001 to 1/1/10000
  70.         internal const int DaysTo10000 = DaysPer400Years * 25 - 366;
  71.        
  72.         internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
  73.        
  74.         //
  75.         // Calendar ID Values. This is used to get data from calendar.nlp.
  76.         // The order of calendar ID means the order of data items in the table.
  77.         //
  78.        
  79.         internal const int CAL_GREGORIAN = 1;
  80.         // Gregorian (localized) calendar
  81.         internal const int CAL_GREGORIAN_US = 2;
  82.         // Gregorian (U.S.) calendar
  83.         internal const int CAL_JAPAN = 3;
  84.         // Japanese Emperor Era calendar
  85.         internal const int CAL_TAIWAN = 4;
  86.         // Taiwan Era calendar
  87.         internal const int CAL_KOREA = 5;
  88.         // Korean Tangun Era calendar
  89.         internal const int CAL_HIJRI = 6;
  90.         // Hijri (Arabic Lunar) calendar
  91.         internal const int CAL_THAI = 7;
  92.         // Thai calendar
  93.         internal const int CAL_HEBREW = 8;
  94.         // Hebrew (Lunar) calendar
  95.         internal const int CAL_GREGORIAN_ME_FRENCH = 9;
  96.         // Gregorian Middle East French calendar
  97.         internal const int CAL_GREGORIAN_ARABIC = 10;
  98.         // Gregorian Arabic calendar
  99.         internal const int CAL_GREGORIAN_XLIT_ENGLISH = 11;
  100.         // Gregorian Transliterated English calendar
  101.         internal const int CAL_GREGORIAN_XLIT_FRENCH = 12;
  102.         internal const int CAL_JULIAN = 13;
  103.         internal const int CAL_JAPANESELUNISOLAR = 14;
  104.         internal const int CAL_CHINESELUNISOLAR = 15;
  105.         internal const int CAL_SAKA = 16;
  106.         // reserved to match Office but not implemented in our code
  107.         internal const int CAL_LUNAR_ETO_CHN = 17;
  108.         // reserved to match Office but not implemented in our code
  109.         internal const int CAL_LUNAR_ETO_KOR = 18;
  110.         // reserved to match Office but not implemented in our code
  111.         internal const int CAL_LUNAR_ETO_ROKUYOU = 19;
  112.         // reserved to match Office but not implemented in our code
  113.         internal const int CAL_KOREANLUNISOLAR = 20;
  114.         internal const int CAL_TAIWANLUNISOLAR = 21;
  115.         internal const int CAL_PERSIAN = 22;
  116.         internal const int CAL_UMALQURA = 23;
  117.        
  118.         internal int m_currentEraValue = -1;
  119.        
  120.         [System.Runtime.Serialization.OptionalField(VersionAdded = 2)]
  121.         private bool m_isReadOnly = false;
  122.        
  123.         // The minimum supported DateTime range for the calendar.
  124.        
  125.         [System.Runtime.InteropServices.ComVisible(false)]
  126.         public virtual DateTime MinSupportedDateTime {
  127.             get { return (DateTime.MinValue); }
  128.         }
  129.        
  130.         // The maximum supported DateTime range for the calendar.
  131.        
  132.         [System.Runtime.InteropServices.ComVisible(false)]
  133.         public virtual DateTime MaxSupportedDateTime {
  134.             get { return (DateTime.MaxValue); }
  135.         }
  136.        
  137.        
  138.        
  139.        
  140.         protected Calendar()
  141.         {
  142.             //Do-nothing constructor.
  143.         }
  144.        
  145.         ///
  146.         // This can not be abstract, otherwise no one can create a subclass of Calendar.
  147.         //
  148.         internal virtual int ID {
  149.             get { return (-1); }
  150.         }
  151.        
  152.         ///
  153.         // Return the Base calendar ID for calendars that didn't have defined data in culture.nlp
  154.         //
  155.        
  156.         internal virtual int BaseCalendarID {
  157.             get { return ID; }
  158.         }
  159.        
  160.         // Returns the type of the calendar.
  161.         //
  162.         [System.Runtime.InteropServices.ComVisible(false)]
  163.         public virtual CalendarAlgorithmType AlgorithmType {
  164.             get { return CalendarAlgorithmType.Unknown; }
  165.         }
  166.        
  167.         ////////////////////////////////////////////////////////////////////////
  168.         //
  169.         // IsReadOnly
  170.         //
  171.         // Detect if the object is readonly.
  172.         //
  173.         ////////////////////////////////////////////////////////////////////////
  174.         [System.Runtime.InteropServices.ComVisible(false)]
  175.         public bool IsReadOnly {
  176.             get { return (m_isReadOnly); }
  177.         }
  178.        
  179.         ////////////////////////////////////////////////////////////////////////
  180.         //
  181.         // Clone
  182.         //
  183.         // Is the implementation of IColnable.
  184.         //
  185.         ////////////////////////////////////////////////////////////////////////
  186.         [System.Runtime.InteropServices.ComVisible(false)]
  187.         public virtual object Clone()
  188.         {
  189.             object o = MemberwiseClone();
  190.             ((Calendar)o).SetReadOnlyState(false);
  191.             return (o);
  192.         }
  193.        
  194.         ////////////////////////////////////////////////////////////////////////
  195.         //
  196.         // ReadOnly
  197.         //
  198.         // Create a cloned readonly instance or return the input one if it is
  199.         // readonly.
  200.         //
  201.         ////////////////////////////////////////////////////////////////////////
  202.         [System.Runtime.InteropServices.ComVisible(false)]
  203.         public static Calendar ReadOnly(Calendar calendar)
  204.         {
  205.             if (calendar == null) {
  206.                 throw new ArgumentNullException("calendar");
  207.             }
  208.             if (calendar.IsReadOnly) {
  209.                 return (calendar);
  210.             }
  211.            
  212.             Calendar clonedCalendar = (Calendar)(calendar.MemberwiseClone());
  213.             clonedCalendar.SetReadOnlyState(true);
  214.            
  215.             return (clonedCalendar);
  216.         }
  217.        
  218.         internal void VerifyWritable()
  219.         {
  220.             if (m_isReadOnly) {
  221.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
  222.             }
  223.         }
  224.        
  225.         internal void SetReadOnlyState(bool readOnly)
  226.         {
  227.             m_isReadOnly = readOnly;
  228.         }
  229.        
  230.        
  231. /*=================================CurrentEraValue==========================
  232.         **Action: This is used to convert CurretEra(0) to an appropriate era value.
  233.         **Returns:
  234.         **Arguments:
  235.         **Exceptions:
  236.         **Notes:
  237.         ** The value is from calendar.nlp.
  238.         ============================================================================*/       
  239.        
  240.         internal virtual int CurrentEraValue {
  241.             get {
  242.                 // The following code assumes that the current era value can not be -1.
  243.                 if (m_currentEraValue == -1) {
  244.                     BCLDebug.Assert(BaseCalendarID > 0, "[Calendar.CurrentEraValue] Expected ID > 0");
  245.                     m_currentEraValue = CalendarTable.Default.ICURRENTERA(BaseCalendarID);
  246.                 }
  247.                 return (m_currentEraValue);
  248.             }
  249.         }
  250.        
  251.         // The current era for a calendar.
  252.        
  253.         public const int CurrentEra = 0;
  254.        
  255.         internal int twoDigitYearMax = -1;
  256.        
  257.         static internal void CheckAddResult(long ticks, DateTime minValue, DateTime maxValue)
  258.         {
  259.             if (ticks < minValue.Ticks || ticks > maxValue.Ticks) {
  260.                 throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Argument_ResultCalendarRange"), minValue, maxValue));
  261.             }
  262.         }
  263.        
  264.         internal DateTime Add(DateTime time, double value, int scale)
  265.         {
  266.             long millis = (long)(value * scale + (value >= 0 ? 0.5 : -0.5));
  267.             if (millis <= -MaxMillis || millis >= MaxMillis) {
  268.                 throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue"));
  269.             }
  270.             long ticks = time.Ticks + millis * TicksPerMillisecond;
  271.             CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
  272.             return (new DateTime(ticks));
  273.         }
  274.        
  275.         // Returns the DateTime resulting from adding the given number of
  276.         // milliseconds to the specified DateTime. The result is computed by rounding
  277.         // the number of milliseconds given by value to the nearest integer,
  278.         // and adding that interval to the specified DateTime. The value
  279.         // argument is permitted to be negative.
  280.         //
  281.        
  282.         public virtual DateTime AddMilliseconds(DateTime time, double milliseconds)
  283.         {
  284.             return (Add(time, milliseconds, 1));
  285.         }
  286.        
  287.        
  288.         // Returns the DateTime resulting from adding a fractional number of
  289.         // days to the specified DateTime. The result is computed by rounding the
  290.         // fractional number of days given by value to the nearest
  291.         // millisecond, and adding that interval to the specified DateTime. The
  292.         // value argument is permitted to be negative.
  293.         //
  294.        
  295.         public virtual DateTime AddDays(DateTime time, int days)
  296.         {
  297.             return (Add(time, days, MillisPerDay));
  298.         }
  299.        
  300.         // Returns the DateTime resulting from adding a fractional number of
  301.         // hours to the specified DateTime. The result is computed by rounding the
  302.         // fractional number of hours given by value to the nearest
  303.         // millisecond, and adding that interval to the specified DateTime. The
  304.         // value argument is permitted to be negative.
  305.         //
  306.        
  307.         public virtual DateTime AddHours(DateTime time, int hours)
  308.         {
  309.             return (Add(time, hours, MillisPerHour));
  310.         }
  311.        
  312.        
  313.         // Returns the DateTime resulting from adding a fractional number of
  314.         // minutes to the specified DateTime. The result is computed by rounding the
  315.         // fractional number of minutes given by value to the nearest
  316.         // millisecond, and adding that interval to the specified DateTime. The
  317.         // value argument is permitted to be negative.
  318.         //
  319.        
  320.         public virtual DateTime AddMinutes(DateTime time, int minutes)
  321.         {
  322.             return (Add(time, minutes, MillisPerMinute));
  323.         }
  324.        
  325.        
  326.         // Returns the DateTime resulting from adding the given number of
  327.         // months to the specified DateTime. The result is computed by incrementing
  328.         // (or decrementing) the year and month parts of the specified DateTime by
  329.         // value months, and, if required, adjusting the day part of the
  330.         // resulting date downwards to the last day of the resulting month in the
  331.         // resulting year. The time-of-day part of the result is the same as the
  332.         // time-of-day part of the specified DateTime.
  333.         //
  334.         // In more precise terms, considering the specified DateTime to be of the
  335.         // form y / m / d + t, where y is the
  336.         // year, m is the month, d is the day, and t is the
  337.         // time-of-day, the result is y1 / m1 / d1 + t,
  338.         // where y1 and m1 are computed by adding value months
  339.         // to y and m, and d1 is the largest value less than
  340.         // or equal to d that denotes a valid day in month m1 of year
  341.         // y1.
  342.         //
  343.        
  344.         public abstract DateTime AddMonths(DateTime time, int months);
  345.        
  346.         // Returns the DateTime resulting from adding a number of
  347.         // seconds to the specified DateTime. The result is computed by rounding the
  348.         // fractional number of seconds given by value to the nearest
  349.         // millisecond, and adding that interval to the specified DateTime. The
  350.         // value argument is permitted to be negative.
  351.         //
  352.        
  353.         public virtual DateTime AddSeconds(DateTime time, int seconds)
  354.         {
  355.             return Add(time, seconds, MillisPerSecond);
  356.         }
  357.        
  358.         // Returns the DateTime resulting from adding a number of
  359.         // weeks to the specified DateTime. The
  360.         // value argument is permitted to be negative.
  361.         //
  362.        
  363.         public virtual DateTime AddWeeks(DateTime time, int weeks)
  364.         {
  365.             return (AddDays(time, weeks * 7));
  366.         }
  367.        
  368.        
  369.         // Returns the DateTime resulting from adding the given number of
  370.         // years to the specified DateTime. The result is computed by incrementing
  371.         // (or decrementing) the year part of the specified DateTime by value
  372.         // years. If the month and day of the specified DateTime is 2/29, and if the
  373.         // resulting year is not a leap year, the month and day of the resulting
  374.         // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
  375.         // parts of the result are the same as those of the specified DateTime.
  376.         //
  377.        
  378.         public abstract DateTime AddYears(DateTime time, int years);
  379.        
  380.         // Returns the day-of-month part of the specified DateTime. The returned
  381.         // value is an integer between 1 and 31.
  382.         //
  383.        
  384.         public abstract int GetDayOfMonth(DateTime time);
  385.        
  386.         // Returns the day-of-week part of the specified DateTime. The returned value
  387.         // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
  388.         // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
  389.         // Thursday, 5 indicates Friday, and 6 indicates Saturday.
  390.         //
  391.        
  392.         public abstract DayOfWeek GetDayOfWeek(DateTime time);
  393.        
  394.         // Returns the day-of-year part of the specified DateTime. The returned value
  395.         // is an integer between 1 and 366.
  396.         //
  397.        
  398.         public abstract int GetDayOfYear(DateTime time);
  399.        
  400.         // Returns the number of days in the month given by the year and
  401.         // month arguments.
  402.         //
  403.        
  404.         public virtual int GetDaysInMonth(int year, int month)
  405.         {
  406.             return (GetDaysInMonth(year, month, CurrentEra));
  407.         }
  408.        
  409.         // Returns the number of days in the month given by the year and
  410.         // month arguments for the specified era.
  411.         //
  412.        
  413.         public abstract int GetDaysInMonth(int year, int month, int era);
  414.        
  415.         // Returns the number of days in the year given by the year argument for the current era.
  416.         //
  417.        
  418.         public virtual int GetDaysInYear(int year)
  419.         {
  420.             return (GetDaysInYear(year, CurrentEra));
  421.         }
  422.        
  423.         // Returns the number of days in the year given by the year argument for the current era.
  424.         //
  425.        
  426.         public abstract int GetDaysInYear(int year, int era);
  427.        
  428.         // Returns the era for the specified DateTime value.
  429.        
  430.         public abstract int GetEra(DateTime time);
  431.        
  432. /*=================================Eras==========================
  433.         **Action: Get the list of era values.
  434.         **Returns: The int array of the era names supported in this calendar.
  435.         **      null if era is not used.
  436.         **Arguments: None.
  437.         **Exceptions: None.
  438.         ============================================================================*/       
  439.        
  440.        
  441.         public abstract int[] Eras {
  442.             get;
  443.         }
  444.        
  445.        
  446.         // Returns the hour part of the specified DateTime. The returned value is an
  447.         // integer between 0 and 23.
  448.         //
  449.        
  450.         public virtual int GetHour(DateTime time)
  451.         {
  452.             return ((int)((time.Ticks / TicksPerHour) % 24));
  453.         }
  454.        
  455.         // Returns the millisecond part of the specified DateTime. The returned value
  456.         // is an integer between 0 and 999.
  457.         //
  458.        
  459.         public virtual double GetMilliseconds(DateTime time)
  460.         {
  461.             return (double)((time.Ticks / TicksPerMillisecond) % 1000);
  462.         }
  463.        
  464.         // Returns the minute part of the specified DateTime. The returned value is
  465.         // an integer between 0 and 59.
  466.         //
  467.        
  468.         public virtual int GetMinute(DateTime time)
  469.         {
  470.             return ((int)((time.Ticks / TicksPerMinute) % 60));
  471.         }
  472.        
  473.         // Returns the month part of the specified DateTime. The returned value is an
  474.         // integer between 1 and 12.
  475.         //
  476.        
  477.         public abstract int GetMonth(DateTime time);
  478.        
  479.         // Returns the number of months in the specified year in the current era.
  480.        
  481.         public virtual int GetMonthsInYear(int year)
  482.         {
  483.             return (GetMonthsInYear(year, CurrentEra));
  484.         }
  485.        
  486.         // Returns the number of months in the specified year and era.
  487.        
  488.         public abstract int GetMonthsInYear(int year, int era);
  489.        
  490.         // Returns the second part of the specified DateTime. The returned value is
  491.         // an integer between 0 and 59.
  492.         //
  493.        
  494.         public virtual int GetSecond(DateTime time)
  495.         {
  496.             return ((int)((time.Ticks / TicksPerSecond) % 60));
  497.         }
  498.        
  499. /*=================================GetFirstDayWeekOfYear==========================
  500.         **Action: Get the week of year using the FirstDay rule.
  501.         **Returns:  the week of year.
  502.         **Arguments:
  503.         **  time
  504.         **  firstDayOfWeek  the first day of week (0=Sunday, 1=Monday, ... 6=Saturday)
  505.         **Notes:
  506.         **  The CalendarWeekRule.FirstDay rule: Week 1 begins on the first day of the year.
  507.         **  Assume f is the specifed firstDayOfWeek,
  508.         **  and n is the day of week for January 1 of the specified year.
  509.         **  Assign offset = n - f;
  510.         **  Case 1: offset = 0
  511.         **      E.g.
  512.         **                    f=1
  513.         **          weekday 0  1  2  3  4  5  6  0  1
  514.         **          date      1/1
  515.         **          week#      1                    2
  516.         **      then week of year = (GetDayOfYear(time) - 1) / 7 + 1
  517.         **
  518.         **  Case 2: offset < 0
  519.         **      e.g.
  520.         **                    n=1  f=3
  521.         **          weekday 0  1  2  3  4  5  6  0
  522.         **          date      1/1
  523.         **          week#      1    2
  524.         **      This means that the first week actually starts 5 days before 1/1.
  525.         **      So week of year = (GetDayOfYear(time) + (7 + offset) - 1) / 7 + 1
  526.         **  Case 3: offset > 0
  527.         **      e.g.
  528.         **                  f=0  n=2
  529.         **          weekday 0  1  2  3  4  5  6  0  1  2
  530.         **          date          1/1
  531.         **          week#        1                    2
  532.         **      This means that the first week actually starts 2 days before 1/1.
  533.         **      So Week of year = (GetDayOfYear(time) + offset - 1) / 7 + 1
  534.         ============================================================================*/       
  535.        
  536.         internal int GetFirstDayWeekOfYear(DateTime time, int firstDayOfWeek)
  537.         {
  538.             int dayOfYear = GetDayOfYear(time) - 1;
  539.             // Make the day of year to be 0-based, so that 1/1 is day 0.
  540.             // Calculate the day of week for the first day of the year.
  541.             // dayOfWeek - (dayOfYear % 7) is the day of week for the first day of this year. Note that
  542.             // this value can be less than 0. It's fine since we are making it positive again in calculating offset.
  543.             int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7);
  544.             int offset = (dayForJan1 - firstDayOfWeek + 14) % 7;
  545.             BCLDebug.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0");
  546.             return ((dayOfYear + offset) / 7 + 1);
  547.         }
  548.        
  549.         internal int GetWeekOfYearFullDays(DateTime time, CalendarWeekRule rule, int firstDayOfWeek, int fullDays)
  550.         {
  551.             int dayForJan1;
  552.             int offset;
  553.             int day;
  554.            
  555.             int dayOfYear = GetDayOfYear(time) - 1;
  556.             // Make the day of year to be 0-based, so that 1/1 is day 0.
  557.             //
  558.             // Calculate the number of days between the first day of year (1/1) and the first day of the week.
  559.             // This value will be a positive value from 0 ~ 6. We call this value as "offset".
  560.             //
  561.             // If offset is 0, it means that the 1/1 is the start of the first week.
  562.             // Assume the first day of the week is Monday, it will look like this:
  563.             // Sun Mon Tue Wed Thu Fri Sat
  564.             // 12/31 1/1 1/2 1/3 1/4 1/5 1/6
  565.             // +--> First week starts here.
  566.             //
  567.             // If offset is 1, it means that the first day of the week is 1 day ahead of 1/1.
  568.             // Assume the first day of the week is Monday, it will look like this:
  569.             // Sun Mon Tue Wed Thu Fri Sat
  570.             // 1/1 1/2 1/3 1/4 1/5 1/6 1/7
  571.             // +--> First week starts here.
  572.             //
  573.             // If offset is 2, it means that the first day of the week is 2 days ahead of 1/1.
  574.             // Assume the first day of the week is Monday, it will look like this:
  575.             // Sat Sun Mon Tue Wed Thu Fri Sat
  576.             // 1/1 1/2 1/3 1/4 1/5 1/6 1/7 1/8
  577.             // +--> First week starts here.
  578.            
  579.            
  580.             // Day of week is 0-based.
  581.             // Get the day of week for 1/1. This can be derived from the day of week of the target day.
  582.             // 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.
  583.             dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7);
  584.            
  585.             // Now, calucalte the offset. Substract the first day of week from the dayForJan1. And make it a positive value.
  586.             offset = (firstDayOfWeek - dayForJan1 + 14) % 7;
  587.             if (offset != 0 && offset >= fullDays) {
  588.                 //
  589.                 // If the offset is greater than the value of fullDays, it means that
  590.                 // the first week of the year starts on the week where Jan/1 falls on.
  591.                 //
  592.                 offset -= 7;
  593.             }
  594.             //
  595.             // Calculate the day of year for specified time by taking offset into account.
  596.             //
  597.             day = dayOfYear - offset;
  598.             if (day >= 0) {
  599.                 //
  600.                 // If the day of year value is greater than zero, get the week of year.
  601.                 //
  602.                 return (day / 7 + 1);
  603.             }
  604.             //
  605.             // Otherwise, the specified time falls on the week of previous year.
  606.             // Call this method again by passing the last day of previous year.
  607.             //
  608.             return (GetWeekOfYearFullDays(time.AddDays(-(dayOfYear + 1)), rule, firstDayOfWeek, fullDays));
  609.         }
  610.        
  611.         // Returns the week of year for the specified DateTime. The returned value is an
  612.         // integer between 1 and 53.
  613.         //
  614.        
  615.         public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
  616.         {
  617.             if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6) {
  618.                 throw new ArgumentOutOfRangeException("firstDayOfWeek", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), DayOfWeek.Sunday, DayOfWeek.Saturday));
  619.             }
  620.             switch (rule) {
  621.                 case CalendarWeekRule.FirstDay:
  622.                     return (GetFirstDayWeekOfYear(time, (int)firstDayOfWeek));
  623.                 case CalendarWeekRule.FirstFullWeek:
  624.                     return (GetWeekOfYearFullDays(time, rule, (int)firstDayOfWeek, 7));
  625.                 case CalendarWeekRule.FirstFourDayWeek:
  626.                     return (GetWeekOfYearFullDays(time, rule, (int)firstDayOfWeek, 4));
  627.             }
  628.             throw new ArgumentOutOfRangeException("rule", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek));
  629.            
  630.         }
  631.        
  632.         // Returns the year part of the specified DateTime. The returned value is an
  633.         // integer between 1 and 9999.
  634.         //
  635.        
  636.         public abstract int GetYear(DateTime time);
  637.        
  638.         // Checks whether a given day in the current era is a leap day. This method returns true if
  639.         // the date is a leap day, or false if not.
  640.         //
  641.        
  642.         public virtual bool IsLeapDay(int year, int month, int day)
  643.         {
  644.             return (IsLeapDay(year, month, day, CurrentEra));
  645.         }
  646.        
  647.         // Checks whether a given day in the specified era is a leap day. This method returns true if
  648.         // the date is a leap day, or false if not.
  649.         //
  650.        
  651.         public abstract bool IsLeapDay(int year, int month, int day, int era);
  652.        
  653.         // Checks whether a given month in the current era is a leap month. This method returns true if
  654.         // month is a leap month, or false if not.
  655.         //
  656.        
  657.         public virtual bool IsLeapMonth(int year, int month)
  658.         {
  659.             return (IsLeapMonth(year, month, CurrentEra));
  660.         }
  661.        
  662.         // Checks whether a given month in the specified era is a leap month. This method returns true if
  663.         // month is a leap month, or false if not.
  664.         //
  665.        
  666.         public abstract bool IsLeapMonth(int year, int month, int era);
  667.        
  668.         // Returns the leap month in a calendar year of the current era. This method returns 0
  669.         // if this calendar does not have leap month, or this year is not a leap year.
  670.         //
  671.        
  672.         [System.Runtime.InteropServices.ComVisible(false)]
  673.         public virtual int GetLeapMonth(int year)
  674.         {
  675.             return (GetLeapMonth(year, CurrentEra));
  676.         }
  677.        
  678.         // Returns the leap month in a calendar year of the specified era. This method returns 0
  679.         // if this calendar does not have leap month, or this year is not a leap year.
  680.         //
  681.        
  682.         [System.Runtime.InteropServices.ComVisible(false)]
  683.         public virtual int GetLeapMonth(int year, int era)
  684.         {
  685.             if (!IsLeapYear(year, era))
  686.                 return 0;
  687.            
  688.             int monthsCount = GetMonthsInYear(year, era);
  689.             for (int month = 1; month <= monthsCount; month++) {
  690.                 if (IsLeapMonth(year, month, era))
  691.                     return month;
  692.             }
  693.            
  694.             return 0;
  695.         }
  696.        
  697.         // Checks whether a given year in the current era is a leap year. This method returns true if
  698.         // year is a leap year, or false if not.
  699.         //
  700.        
  701.         public virtual bool IsLeapYear(int year)
  702.         {
  703.             return (IsLeapYear(year, CurrentEra));
  704.         }
  705.        
  706.         // Checks whether a given year in the specified era is a leap year. This method returns true if
  707.         // year is a leap year, or false if not.
  708.         //
  709.        
  710.         public abstract bool IsLeapYear(int year, int era);
  711.        
  712.         // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
  713.         //
  714.        
  715.         public virtual DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond)
  716.         {
  717.             return (ToDateTime(year, month, day, hour, minute, second, millisecond, CurrentEra));
  718.         }
  719.        
  720.         // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
  721.         //
  722.        
  723.         public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
  724.        
  725.         internal virtual bool TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
  726.         {
  727.             result = DateTime.MinValue;
  728.             try {
  729.                 result = ToDateTime(year, month, day, hour, minute, second, millisecond, era);
  730.                 return true;
  731.             }
  732.             catch (ArgumentException) {
  733.                 return false;
  734.             }
  735.         }
  736.        
  737.         internal virtual bool IsValidYear(int year, int era)
  738.         {
  739.             return (year >= GetYear(MinSupportedDateTime) && year <= GetYear(MaxSupportedDateTime));
  740.         }
  741.        
  742.         internal virtual bool IsValidMonth(int year, int month, int era)
  743.         {
  744.             return (IsValidYear(year, era) && month >= 1 && month <= GetMonthsInYear(year, era));
  745.         }
  746.        
  747.         internal virtual bool IsValidDay(int year, int month, int day, int era)
  748.         {
  749.             return (IsValidMonth(year, month, era) && day >= 1 && day <= GetDaysInMonth(year, month, era));
  750.         }
  751.        
  752.        
  753.        
  754.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  755.         static internal extern int nativeGetTwoDigitYearMax(int calID);
  756.        
  757.         // Returns and assigns the maximum value to represent a two digit year. This
  758.         // value is the upper boundary of a 100 year range that allows a two digit year
  759.         // to be properly translated to a four digit year. For example, if 2029 is the
  760.         // upper boundary, then a two digit value of 30 should be interpreted as 1930
  761.         // while a two digit value of 29 should be interpreted as 2029. In this example
  762.         // , the 100 year range would be from 1930-2029. See ToFourDigitYear().
  763.        
  764.         public virtual int TwoDigitYearMax {
  765.             get { return (twoDigitYearMax); }
  766.            
  767.             set {
  768.                 VerifyWritable();
  769.                 twoDigitYearMax = value;
  770.             }
  771.         }
  772.        
  773.         // Converts the year value to the appropriate century by using the
  774.         // TwoDigitYearMax property. For example, if the TwoDigitYearMax value is 2029,
  775.         // then a two digit value of 30 will get converted to 1930 while a two digit
  776.         // value of 29 will get converted to 2029.
  777.        
  778.         public virtual int ToFourDigitYear(int year)
  779.         {
  780.             if (year < 0) {
  781.                 throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  782.             }
  783.             if (year < 100) {
  784.                 return ((TwoDigitYearMax / 100 - (year > TwoDigitYearMax % 100 ? 1 : 0)) * 100 + year);
  785.             }
  786.             // If the year value is above 100, just return the year value. Don't have to do
  787.             // the TwoDigitYearMax comparison.
  788.             return (year);
  789.         }
  790.        
  791.         // Return the tick count corresponding to the given hour, minute, second.
  792.         // Will check the if the parameters are valid.
  793.         static internal long TimeToTicks(int hour, int minute, int second, int millisecond)
  794.         {
  795.             if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60) {
  796.                 if (millisecond < 0 || millisecond >= MillisPerSecond) {
  797.                     throw new ArgumentOutOfRangeException("millisecond", String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 0, MillisPerSecond - 1));
  798.                 }
  799.                 return TimeSpan.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond;
  800.             }
  801.             throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"));
  802.         }
  803.        
  804.        
  805.        
  806.         [ResourceExposure(ResourceScope.None)]
  807.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  808.         static internal int GetSystemTwoDigitYearSetting(int CalID, int defaultYearValue)
  809.         {
  810.            
  811.             //
  812.             // Call Win32 ::GetCalendarInfo() to retrieve CAL_ITWODIGITYEARMAX value.
  813.             // This function only exists after Windows 98 and Windows 2000.
  814.             //
  815.            
  816.             int twoDigitYearMax = nativeGetTwoDigitYearMax(CalID);
  817.             if (twoDigitYearMax < 0) {
  818.                 twoDigitYearMax = defaultYearValue;
  819.             }
  820.             return (twoDigitYearMax);
  821.         }
  822.        
  823.     }
  824. }

Developer Fusion