// ::MONO // // System.Globalization.Calendar.cs // // Copyright (C) Wictor Wilén 2001 (wictor@iBizkit.se) // // Contributors: Marcel Narings, Wictor Wilén // // Revisions // 2001-09-14: First draft // 2001-09-15: First release // // // TODO: testing // // using System; namespace System.Globalization { /// /// Implmentation of the System.Globalization.Calendar class /// public abstract class Calendar { /// /// The Calendar Constructor /// protected Calendar () { _MaxDateTime = DateTime.MaxValue; _MinDateTime = DateTime.MinValue; } [CLSCompliant(false)] protected int _TwoDigitYearMax; [CLSCompliant(false)] protected static int[] _DaysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; [CLSCompliant(false)] protected static int[] _DaysInMonthLeap = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // these can be overridden, for example using "new protected const int _MinYear = 1;" [CLSCompliant(false)] protected const int _MinYear = 1; [CLSCompliant(false)] protected const int _MaxYear = 9999; [CLSCompliant(false)] protected const int _MinDay = 0; [CLSCompliant(false)] protected const int _MinMonth = 1; [CLSCompliant(false)] protected const int _MaxMonth = 12; [CLSCompliant(false)] protected const int _MinHour = 0; [CLSCompliant(false)] protected const int _MaxHour = 23; [CLSCompliant(false)] protected const int _MinMinute = 0; [CLSCompliant(false)] protected const int _MaxMinute = 59; [CLSCompliant(false)] protected const int _MinSecond = 0; [CLSCompliant(false)] protected const int _MaxSecond = 59; [CLSCompliant(false)] protected const int _MinMillisecond = 0; [CLSCompliant(false)] protected const int _MaxMillisecond = 999; [CLSCompliant(false)] private const long _TicksPerMillisecond = 10000; [CLSCompliant(false)] private const long _TicksPerSecond = 10000000; [CLSCompliant(false)] private const long _TicksPerMinute = 600000000; [CLSCompliant(false)] private const long _TicksPerHour = 36000000000; [CLSCompliant(false)] private const long _TicksPerDay = 864000000000; [CLSCompliant(false)] private const long _TicksPerWeek = 6048000000000; [CLSCompliant(false)] protected DateTime _MaxDateTime; [CLSCompliant(false)] protected DateTime _MinDateTime; /// /// The Currentera constant /// public const int CurrentEra = 0; /// /// Returns an array of the available eras /// public abstract int[] Eras {get;} // DONE! /// /// The Two digit max /// public virtual int TwoDigitYearMax { get { return _TwoDigitYearMax; } set { _TwoDigitYearMax = value; } } // DONE! public virtual DateTime AddDays ( DateTime time, int days ) { return new DateTime(time.Ticks).AddTicks(_TicksPerDay*days); } // DONE! public virtual DateTime AddHours ( DateTime time, int hours ) { return new DateTime(time.Ticks).AddTicks(_TicksPerHour*hours); } // DONE! public virtual DateTime AddMilliseconds ( DateTime time, double milliseconds ) { DateTime t = new DateTime(time.Ticks); return t.AddMilliseconds(milliseconds); } // DONE! public virtual DateTime AddMinutes ( DateTime time, int minutes ) { return new DateTime(time.Ticks).AddTicks(_TicksPerMinute * minutes); } // DONE! /// /// Returns a DateTime that is the specified number of months away from the specified DateTime /// /// /// /// /// Calculates correct comapared to .NET Beta 2 public virtual DateTime AddMonths ( DateTime time, int months ) { DateTime t = new DateTime(time.Ticks); return t.AddMonths(months); } // DONE! public virtual DateTime AddSeconds ( DateTime time, int seconds ) { return new DateTime(time.Ticks).AddTicks(_TicksPerSecond * seconds); } // DONE! public virtual DateTime AddWeeks ( DateTime time, int weeks ) { return new DateTime(time.Ticks).AddTicks(_TicksPerWeek * weeks); } // DONE! public virtual DateTime AddYears ( DateTime time, int years ) { DateTime t = new DateTime(time.Ticks); return t.AddYears(years); } // DONE! public abstract int GetDayOfMonth ( DateTime time ); // DONE! public abstract DayOfWeek GetDayOfWeek ( DateTime time ); // DONE! public abstract int GetDayOfYear ( DateTime time ); // DONE! public virtual int GetDaysInMonth ( int year, int month ) { if(year < _MinYear || year > _MaxYear || month < _MinMonth || month > _MaxMonth) throw new System.ArgumentOutOfRangeException(); if(this.IsLeapYear(year)) return _DaysInMonthLeap[month]; else return _DaysInMonth[month]; } // DONE! public abstract int GetDaysInMonth ( int year, int month, int era ); // DONE! public virtual int GetDaysInYear ( int year) { if( year < _MinYear || year > _MaxYear) throw new System.ArgumentOutOfRangeException(); if(this.IsLeapYear(year)) return 366; else return 365; } // DONE! public abstract int GetDaysInYear ( int year, int era ); // DONE! public abstract int GetEra ( DateTime time ); // DONE! public virtual int GetHour ( DateTime time ) { return time.Hour; } // DONE! public virtual double GetMilliseconds ( DateTime time ) { return time.Millisecond; } // DONE! public virtual int GetMinute ( DateTime time ) { return time.Minute; } // DONE! public abstract int GetMonth ( DateTime time ); // DONE! public virtual int GetMonthsInYear ( int year ) { if( year < _MinYear || year > _MaxYear) throw new System.ArgumentException(); return _MaxMonth; } // DONE! public abstract int GetMonthsInYear ( int year, int era ); // DONE! public virtual int GetSecond ( DateTime time ) { return time.Second; } // DONE! /// /// Gets the week of the year that includes the date in the specified DateTime /// /// /// /// /// /// .NET beta 2 calculates this erroneous, but this one is ok(? I think...) public virtual int GetWeekOfYear ( DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek ) { if( firstDayOfWeek < DayOfWeek.Sunday || firstDayOfWeek > DayOfWeek.Saturday) throw new System.ArgumentOutOfRangeException(); int week; int days = 0; int[] dim; if(this.IsLeapYear(time.Year)) dim = _DaysInMonthLeap; else dim = _DaysInMonth; DateTime jan1 = new DateTime(time.Year, 1, 1); for( int i = 0; i < time.Month-1; i++) days += dim[i]; days += time.Day; switch(rule) { case CalendarWeekRule.FirstDay: while(jan1.DayOfWeek != firstDayOfWeek) { days--; jan1 = jan1.AddTicks(_TicksPerDay); } break; case CalendarWeekRule.FirstFourDayWeek: while(jan1.DayOfWeek < firstDayOfWeek) { days--; jan1 = jan1.AddTicks(_TicksPerDay); } break; case CalendarWeekRule.FirstFullWeek: if(jan1.DayOfWeek != firstDayOfWeek) { do { days--; jan1 = jan1.AddTicks(_TicksPerDay); } while(jan1.DayOfWeek != firstDayOfWeek); } break; default: throw new System.ArgumentOutOfRangeException(); } if(days <= 0) week = GetWeekOfYear(new DateTime(time.Year-1,12,31), rule, firstDayOfWeek); else week = (--days / 7) + 1; return week; } // DONE! public abstract int GetYear ( DateTime time ); // DONE! // TODO: verify this for the Calendar Class public virtual bool IsLeapDay ( int year, int month, int day ) { int dim; if(day < _MinDay || month < _MinMonth || month > _MaxMonth) throw new System.ArgumentOutOfRangeException(); if(this.IsLeapYear(year)) dim = _DaysInMonthLeap[month-1]; else dim = _DaysInMonth[month-1]; if( day > dim) throw new System.ArgumentOutOfRangeException(); if( month == 2 && day == 29) return true; return false; } // DONE! public abstract bool IsLeapDay ( int year, int month, int day, int era ); // DONE! public virtual bool IsLeapMonth ( int year, int month ) { if( year < _MinYear || year > _MaxYear || month < _MinMonth || month > _MaxMonth) throw new System.ArgumentOutOfRangeException(); if(this.IsLeapYear(year)) { return true; } else return false; } // DONE! public abstract bool IsLeapMonth ( int year, int month, int era ); public virtual bool IsLeapYear ( int year ) { if(year < _MinYear || year > _MaxYear ) throw new System.ArgumentOutOfRangeException(); if(year % 4 == 0) // TODO: verify this for the Calendar class! return true; return false; } // DONE! public abstract bool IsLeapYear ( int year, int era ); // DONE! public virtual DateTime ToDateTime ( int year, int month, int day, int hour, int minute, int second, int millisecond ) { int dim; dim = GetDaysInMonth(year,month); if( day < _MinDay || day > dim || hour < _MinHour || hour > _MaxHour || minute < _MinMinute || minute > _MaxMinute || second < _MinSecond || second > _MaxSecond || millisecond < _MinMillisecond || millisecond > _MaxMillisecond) throw new System.ArgumentOutOfRangeException(); return new DateTime(year,month,day,hour,minute,second,millisecond,this); } // DONE! public abstract DateTime ToDateTime ( int year, int month, int date, int hour, int minute, int second, int millisecond, int era ); // DONE! public virtual int ToFourDigitYear ( int year ) { int i = year - ( _TwoDigitYearMax % 100 ); if( year > 0 ) return _TwoDigitYearMax - 100 + year; else return _TwoDigitYearMax + year; } } }