// // System.DateTime.cs // // author: // Marcel Narings (marcel@narings.nl) // // (C) 2001 Marcel Narings using System; using System.Globalization; using System.Runtime.CompilerServices; namespace System { /// /// The DateTime structure represents dates and time ranging from /// 1-1-0001 12:00:00 AM to 31-12-9999 23:59:00 Common Era. /// /// public struct DateTime : IComparable , IFormattable , IConvertible { long ticks; private const long MaxTicks = 3155378975999999999L; private const long MinTicks = 0L; private const int dp400 = 146097; private const int dp100 = 36524; private const int dp4 = 1461; // w32 file time starts counting from 1/1/1601 00:00 GMT // which is the constant ticks from the .NET epoch private const long w32file_epoch = 504911232000000000L; public static readonly DateTime MaxValue = new DateTime (MaxTicks); public static readonly DateTime MinValue = new DateTime (MinTicks); private enum Which { Day, DayYear, Month, Year }; private static int[] daysmonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; private static long AbsoluteDays (int year, int month, int day) { int[] days; int temp = 0, m=1 ; days = (IsLeapYear(year) ? daysmonthleap : daysmonth); while (m < month) temp += days[m++]; return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400)); } private int FromTicks(Which what) { int num400, num100, num4, numyears; int M =1; int[] days = daysmonth; int totaldays = (int) (ticks / TimeSpan.TicksPerDay); num400 = (totaldays / dp400); totaldays -= num400 * dp400; num100 = (totaldays / dp100); if (num100 == 4) // leap num100 = 3; totaldays -= (num100 * dp100); num4 = totaldays / dp4; totaldays -= (num4 * dp4); numyears = totaldays / 365 ; if (numyears == 4) //leap numyears =3 ; if (what == Which.Year ) return num400*400 + num100*100 + num4*4 + numyears + 1; totaldays -= (numyears * 365) ; if (what == Which.DayYear ) return totaldays + 1; if ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear days = daysmonthleap; while (totaldays >= days[M]) totaldays -= days[M++]; if (what == Which.Month ) return M; return totaldays +1; } // Constructors /// /// Constructs a DateTime for specified ticks /// /// public DateTime (long newticks) { ticks = newticks; if ( newticks < MinValue.ticks || newticks > MaxValue.ticks) throw new ArgumentOutOfRangeException (); } public DateTime (int year, int month, int day) : this (year, month, day,0,0,0,0) {} public DateTime (int year, int month, int day, int hour, int minute, int second) : this (year, month, day, hour, minute, second, 0) {} public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond) { if ( year < 1 || year > 9999 || month < 1 || month >12 || day < 1 || day > DaysInMonth(year, month) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59 ) throw new ArgumentOutOfRangeException() ; ticks = AbsoluteDays(year,month,day) * TimeSpan.TicksPerDay + hour * TimeSpan.TicksPerHour + minute * TimeSpan.TicksPerMinute + second * TimeSpan.TicksPerSecond + millisecond * TimeSpan.TicksPerMillisecond ; if (ticks < MinValue.ticks || ticks > MaxValue.ticks ) throw new ArgumentException() ; } public DateTime (int year, int month, int day, Calendar calendar) : this (year, month, day, 0, 0, 0, 0, calendar) {} public DateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar) : this (year, month, day, hour, minute, second, 0, calendar) {} public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar) : this(year, month, day, hour, minute, second, millisecond) { if ( calendar == null) throw new ArgumentNullException(); } /* Properties */ public DateTime Date { get { return new DateTime(ticks - (ticks % TimeSpan.TicksPerDay )) ; } } public int Day { get { return FromTicks(Which.Day); } } public DayOfWeek DayOfWeek { get { return ( (DayOfWeek) (((ticks / TimeSpan.TicksPerDay)+1) % 7) ); } } public int DayOfYear { get { return FromTicks(Which.DayYear); } } public int Hour { get { return ( (int) ((ticks % TimeSpan.TicksPerDay) / TimeSpan.TicksPerHour) ); } } public int Millisecond { get { return ( (int) (ticks % TimeSpan.TicksPerSecond / TimeSpan.TicksPerMillisecond) ); } } public int Minute { get { return ( (int) (ticks % TimeSpan.TicksPerHour / TimeSpan.TicksPerMinute) ); } } public int Month { get { return FromTicks(Which.Month); } } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern long GetNow (); public static DateTime Now { get { return new DateTime (GetNow ()); } } public int Second { get { return (int) (ticks % TimeSpan.TicksPerMinute / TimeSpan.TicksPerSecond); } } public long Ticks { get { return ticks ; } } public TimeSpan TimeOfDay { get { return new TimeSpan(ticks % TimeSpan.TicksPerDay ); } } //TODO implement [MonoTODO] public static DateTime Today { get { return new DateTime (0); } } //TODO implement [MonoTODO] public static DateTime UtcNow { get { return new DateTime (0); } } public int Year { get { return FromTicks(Which.Year); } } /* methods */ public DateTime Add (TimeSpan ts) { long newticks ; newticks = ticks + ts.Ticks ; if (ts.Ticks < MinTicks || ts.Ticks > MaxTicks || newticks < MinTicks || newticks > MaxTicks) throw new ArgumentException (); return new DateTime (newticks); } public DateTime AddDays (double days) { return AddMilliseconds (days * 86400000); } public DateTime AddTicks (long t) { long newticks = ticks + t; if (tMaxTicks || newticksMaxTicks) throw new ArgumentException (); return new DateTime(newticks); } public DateTime AddHours (double hours) { return AddMilliseconds (hours * 3600000); } public DateTime AddMilliseconds (double ms) { long msticks, newticks; msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond ; newticks = ticks + msticks ; if (msticks < MinTicks || msticks > MaxTicks || newticks < MinTicks || newticks > MaxTicks) throw new ArgumentException (); return new DateTime (newticks); } public DateTime AddMinutes (double minutes) { return AddMilliseconds (minutes * 60000); } public DateTime AddMonths (int months) { int day, month, year, maxday ; DateTime temp ; day = this.Day; month = this.Month + (months % 12); year = this.Year + months/12 ; if (month < 1) { month = 12 + month ; year -- ; } else if (month>12) { month = month -12; year ++; } maxday = DaysInMonth(year, month); if (day > maxday) day = maxday; temp = new DateTime (year, month, day); return temp.Add (this.TimeOfDay); } public DateTime AddSeconds (double seconds) { return AddMilliseconds (seconds*1000); } public DateTime AddYears (int years ) { return AddMonths(years * 12); } public static int Compare (DateTime t1, DateTime t2) { if (t1.ticks < t2.ticks) return -1; else if (t1.ticks > t2.ticks) return 1; else return 0; } public int CompareTo (object v) { if ( v == null) return 1; if (!(v is System.DateTime)) throw new ArgumentException (Locale.GetText ( "Value is not a System.DateTime")); return Compare (this, (DateTime) v); } public static int DaysInMonth (int year, int month) { int[] days ; if (month < 1 || month >12) throw new ArgumentOutOfRangeException (); days = (IsLeapYear(year) ? daysmonthleap : daysmonth); return days[month]; } public override bool Equals (object o) { if (!(o is System.DateTime)) return false; return ((DateTime) o).ticks == ticks; } public static bool Equals (DateTime t1, DateTime t2 ) { return (t1.ticks == t2.ticks ); } public static DateTime FromFileTime (long fileTime) { return new DateTime (w32file_epoch + fileTime); } // TODO: Implement me. [MonoTODO] public static DateTime FromOADate (double d) { return new DateTime(0); } // TODO: Implement me. [MonoTODO] public string[] GetDateTimeFormats() { return null; } //TODO: implement me [MonoTODO] public string[] GetDateTimeFormats(char format) { return null; } // TODO: implement me [MonoTODO] public string[] GetDateTimeFormats(IFormatProvider provider) { return null; } //TODO: implement me [MonoTODO] public string[] GetDateTimeFormats(char format,IFormatProvider provider ) { return null; } public override int GetHashCode () { return (int) ticks; } public TypeCode GetTypeCode () { return TypeCode.DateTime; } public static bool IsLeapYear (int year) { return ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ; } [MonoTODO] public static DateTime Parse (string s) { // TODO: Implement me return new DateTime (0); } [MonoTODO] public static DateTime Parse (string s, IFormatProvider fp) { // TODO: Implement me return new DateTime (0); } [MonoTODO] public static DateTime Parse (string s, NumberStyles style, IFormatProvider fp) { // TODO: Implement me return new DateTime (0); } [MonoTODO] public static DateTime ParseExact(string s, string format, IFormatProvider provider ) { // TODO: Implement me return new DateTime (0); } [MonoTODO] public static DateTime ParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style ) { // TODO: Implement me return new DateTime (0); } [MonoTODO] public static DateTime ParseExact( string s, string[] formats, IFormatProvider provider, DateTimeStyles style ) { // TODO: Implement me return new DateTime (0); } public TimeSpan Subtract(DateTime dt ) { return new TimeSpan(ticks - dt.ticks ); } public DateTime Subtract(TimeSpan ts) { return new DateTime(ticks - ts.Ticks ); } public long ToFileTime() { if(ticks < w32file_epoch) { throw new ArgumentOutOfRangeException("file time is not valid"); } return(ticks - w32file_epoch); } [MonoTODO] public DateTime ToLocalTime() { // TODO Implement me return new DateTime (0); } [MonoTODO] public string ToLongDateString() { // TODO implement me throw new NotImplementedException (); } [MonoTODO] public string ToLongTimeString() { // TODO implement me throw new NotImplementedException (); } [MonoTODO] public double ToOADate() { // TODO implement me return 0; } [MonoTODO] public string ToShortDateString() { // TODO implement me throw new NotImplementedException (); } [MonoTODO] public string ToShortTimeString() { // TODO implement me throw new NotImplementedException (); } [MonoTODO] public override string ToString () { // TODO: Implement me throw new NotImplementedException (); } [MonoTODO] public string ToString (IFormatProvider fp) { // TODO: Implement me. throw new NotImplementedException (); } [MonoTODO] public string ToString (string format) { // TODO: Implement me. throw new NotImplementedException (); } [MonoTODO] public string ToString (string format, IFormatProvider fp) { // TODO: Implement me. throw new NotImplementedException (); } [MonoTODO] public DateTime ToUniversalTime() { // TODO: implement me return new DateTime(0); } /* OPERATORS */ public static DateTime operator +(DateTime d, TimeSpan t) { return new DateTime (d.ticks + t.Ticks); } public static bool operator ==(DateTime d1, DateTime d2) { return (d1.ticks == d2.ticks); } public static bool operator >(DateTime t1,DateTime t2) { return (t1.ticks > t2.ticks); } public static bool operator >=(DateTime t1,DateTime t2) { return (t1.ticks >= t2.ticks); } public static bool operator !=(DateTime d1, DateTime d2) { return (d1.ticks != d2.ticks); } public static bool operator <(DateTime t1, DateTime t2) { return (t1.ticks < t2.ticks ); } public static bool operator <=(DateTime t1,DateTime t2) { return (t1.ticks <= t2.ticks); } public static TimeSpan operator -(DateTime d1,DateTime d2) { return new TimeSpan(d1.ticks - d2.ticks); } public static DateTime operator -(DateTime d,TimeSpan t ) { return new DateTime (d.ticks - t.Ticks); } public bool ToBoolean(IFormatProvider provider) { throw new InvalidCastException(); } public byte ToByte(IFormatProvider provider) { throw new InvalidCastException(); } public char ToChar(IFormatProvider provider) { throw new InvalidCastException(); } // TODO Implement me [MonoTODO] public System.DateTime ToDateTime(IFormatProvider provider) { return new System.DateTime(this.ticks); } public decimal ToDecimal(IFormatProvider provider) { throw new InvalidCastException(); } public double ToDouble(IFormatProvider provider) { throw new InvalidCastException(); } public Int16 ToInt16(IFormatProvider provider) { throw new InvalidCastException(); } public Int32 ToInt32(IFormatProvider provider) { throw new InvalidCastException(); } public Int64 ToInt64(IFormatProvider provider) { throw new InvalidCastException(); } [CLSCompliant(false)] public SByte ToSByte(IFormatProvider provider) { throw new InvalidCastException(); } public Single ToSingle(IFormatProvider provider) { throw new InvalidCastException(); } public object ToType(Type conversionType,IFormatProvider provider) { throw new InvalidCastException(); } UInt16 System.IConvertible.ToUInt16(IFormatProvider provider) { throw new InvalidCastException(); } [CLSCompliant(false)] public UInt32 ToUInt32(IFormatProvider provider) { throw new InvalidCastException(); } [CLSCompliant(false)] public UInt64 ToUInt64(IFormatProvider provider) { throw new InvalidCastException(); } } } namespace System { public enum DayOfWeek { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } }