Click here to Skip to main content
15,891,431 members
Articles / Programming Languages / C#

Time scheduler in C#

Rate me:
Please Sign up or sign in to vote.
4.67/5 (17 votes)
16 May 2007GPL34 min read 135.8K   2.5K   82  
This library allows iterating through a sequence of events or time ranges based on a time schedule.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace Idaligo.Time
{
	public class Area : IArea
	{
		protected class Errors
		{
			protected Errors()
			{
			}

			public static ApplicationException NoRanges()
			{
				return new ApplicationException("There are no ranges in the area.");
			}
		}

		private List<IPeriod> list;

		public Area()
		{
			this.list = new List<IPeriod>();
		}

		public Area(IPeriod period)
			: this()
		{
			if (period == null) throw new ArgumentNullException("period");
			this.Add(period);
		}

		public void Add(IPeriod period)
		{
			if (period == null) throw new ArgumentNullException("period");
			this.list.Add(period);
		}

		public bool Hit(DateTime at)
		{
			bool result = false;
			foreach (IPeriod range in this.list)
			{
				if (range.Hit(at))
				{
					result = true;
					break;
				}
			}
			return result;
		}

		//public IEnumerable<TimeRange> Walk1(DateTime from)
		//{
		//    IEnumerator<IPeriod> iterator = this.list.GetEnumerator();
		//    if (iterator.MoveNext())
		//    {
		//        DateTime starts = DateTime.MaxValue;
		//        DateTime ends = DateTime.MinValue;
		//        bool found = false;
		//        TimeRange current = iterator.Current.CurrentPeriodIfAny(from);
		//        if (current != null)
		//        {
		//            found = true;
		//            starts = current.From;
		//            ends = current.Till;
		//        }

		//        while (iterator.MoveNext())
		//        {
		//            current = iterator.Current.CurrentPeriodIfAny(from);
		//            if (current != null)
		//            {
		//                if (found)
		//                {
		//                    if (current.From < starts)
		//                    {
		//                        starts = current.From;
		//                    }
		//                    if (current.Till > ends)
		//                    {
		//                        starts = current.Till;
		//                    }
		//                }
		//                else
		//                {
		//                    starts = current.From;
		//                    ends = current.Till;
		//                    found = true;
		//                }
		//            }
		//        }

		//        if (found)
		//        {
		//            yield return new TimeRange(starts, ends);
		//            from = ends;
		//        }
		//        else
		//        {
		//            // do nothing
		//        }

		//        while (true)
		//        {
		//            starts = this.StartingBoundary(from);
		//            iterator = this.list.GetEnumerator();
		//            while (iterator.MoveNext())
		//            {
		//                current = iterator.Current.CurrentPeriodIfAny(starts);
		//                if (current != null)
		//                {
		//                    if (current.Till > ends)
		//                    {
		//                        ends = current.Till;
		//                    }
		//                }
		//            }
		//            yield return new TimeRange(starts, ends);
		//            from = ends;
		//        }
		//    }
		//    else
		//    {
		//        throw Errors.NoRanges();
		//    }
		//}

		public IEnumerable<TimeRange> Walk(DateTime from)
		{
			IEnumerator<IPeriod> iterator = this.list.GetEnumerator();
			if (iterator.MoveNext())
			{
				DateTime starts = DateTime.MaxValue;
				DateTime ends = DateTime.MinValue;
				bool found = false;
				TimeRange current = iterator.Current.CurrentPeriodIfAny(from);
				if (current != null)
				{
					found = true;
					starts = current.From;
					ends = current.Till;
				}

				while (iterator.MoveNext())
				{
					current = iterator.Current.CurrentPeriodIfAny(from);
					if (current != null)
					{
						if (found)
						{
							if (current.From < starts)
							{
								starts = current.From;
							}
							if (current.Till > ends)
							{
								starts = current.Till;
							}
						}
						else
						{
							starts = current.From;
							ends = current.Till;
							found = true;
						}
					}
				}
				
				TimeRange last;
				if (found)
				{
					last = new TimeRange(starts, ends);
				}
				else
				{
					last = null;
					ends = from;
				}

				// in: last, from
				while (true)
				{
					starts = this.StartingBoundary(ends);
					ends = this.EndingBoundary(starts);
					if (last != null)
					{
						if (last.Till == starts)
						{
							last = new TimeRange(last.From, ends);
						}
						else
						{
							yield return last;
							last = new TimeRange(starts, ends);
						}
					}
					else
					{
						last = new TimeRange(starts, ends);
					}
				}
			}
			else
			{
				throw Errors.NoRanges();
			}
		}

		public DateTime EndingBoundary(DateTime starts)
		{
			DateTime result = starts;

			bool found = false;
			IEnumerator<IPeriod> iterator = this.list.GetEnumerator();
			while (iterator.MoveNext())
			{
				TimeRange current = iterator.Current.CurrentPeriodIfAny(starts);
				if (current != null)
				{
					if (current.Till > result)
					{
						found = true;
						result = current.Till;
					}
				}
			}
			if (!found)
			{
				// must be found!!!
				throw new InvalidProgramException();
			}
			return result;
		}

		public DateTime StartingBoundary(DateTime from)
		{
			DateTime result;

			IEnumerator<IPeriod> iterator = this.list.GetEnumerator();
			if (iterator.MoveNext())
			{
				TimeRange current = iterator.Current.CurrentPeriodIfAny(from);
				if (current != null && current.From == from)
				{
					result = from;
				}
				else
				{
					result = iterator.Current.Next(from).From;
					while (iterator.MoveNext())
					{
						current = iterator.Current.CurrentPeriodIfAny(from);
						if (current != null)
						{
							result = from;
						}
						else
						{
							DateTime next = iterator.Current.Next(from).From;
							if (result > next)
							{
								result = next;
							}
						}
					}
				}
			}
			else
			{
				throw Errors.NoRanges();
			}

			return result;
		}

		public bool IsEmpty
		{
			[DebuggerStepThrough]
			get
			{
				return this.list.Count < 1;
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
United States United States
C# .NET developer since 2003

Comments and Discussions