Background
I was working on a data search program the other week. It allows the user to specify start and end DateTime
values and searches for data within that range. However, each day's data is stored separately, so the program has to search each day in the range one at a time. It seemed logical to use a foreach
to get a DateTime
for each day within the range. So I wrote this class to allow me to do that.
The files
The included files are:
TimeRanger.cs
TimeIntervalEnumerators.cs
DateTruncate.cs
(which has its own article here)
TimeRangerDemo.cs
Extract them from the zip and add them to your project. (Well, not the demo file unless you want to build the demo.)
Using the code
You can use the TimeRanger class like so:
PIEBALD.Types.TimeRanger tr = new PIEBALD.Types.TimeRanger
(
System.DateTime.Now.AddDays ( -400 )
,
System.DateTime.Now.AddDays ( +30 )
) ;
foreach ( System.DateTime dt in tr.Months )
{
System.Console.WriteLine ( dt ) ;
}
Often you won't need to use TimeRanger; it's convenient for passing a time range to a method and in cases where you want to enumerate the same range multiple times, perhaps with various granularities. In many cases the iterators in TimeIntervalEnumerators.cs
will suffice:
foreach
(
System.DateTime dt in
PIEBALD.Lib.LibTim.MonthEnumerator
(
System.DateTime.Now.AddDays ( -400 )
,
System.DateTime.Now.AddDays ( +30 )
)
)
{
System.Console.WriteLine ( dt ) ;
}
Points of Interest
The first version of this used an additional class that implemented IEnumerator
, but Russell Morris pointed out iterators (yield
methods) that are new in .net 2.0, so I rewrote the code to use them.
For any who want to see how I implemented the iterators (at Russell Morris' suggestion) (note that the iteration will be "backward" if the StartPoint is greater than the EndPoint):
public static System.Collections.Generic.IEnumerable<System.DateTime>
MonthEnumerator
(
System.DateTime StartPoint
,
System.DateTime EndPoint
)
{
System.DateTime current = PIEBALD.Lib.LibTim.DateTruncate
(
StartPoint
,
PIEBALD.Lib.LibTim.TimeGranularity.Month
) ;
if ( StartPoint <= EndPoint )
{
if ( current < StartPoint )
{
current = current.AddMonths ( 1 ) ;
}
while ( current <= EndPoint )
{
yield return ( current ) ;
current = current.AddMonths ( 1 ) ;
}
}
else
{
while ( current >= EndPoint )
{
yield return ( current ) ;
current = current.AddMonths ( -1 ) ;
}
}
yield break ;
}
History
First submitted 2007-02-02