Wednesday, September 12, 2007

How to get a random date in C#

I looked everywhere for a sample on generating random dates in C# but could find any so I wrote mine.


private static DateTime getRandomDate(Random rand,
DateTime minDate, DateTime maxDate)
{
int totalDays = (int)DateTimeUtil.DateDiff(
DateInterval.Day , minDate, maxDate);
int randomDays = rand.Next(0,totalDays);
return minDate.AddDays(randomDays);

}


This function uses the DateTime utility class below which I found somewhere on the web.

public enum DateInterval
{
Day,
DayOfYear,
Hour,
Minute,
Month,
Quarter,
Second,
Weekday,
WeekOfYear,
Year
}

///

public sealed class DateTimeUtil
{

#region DateDiff Methods

public static long DateDiff(DateInterval interval,
DateTime dt1, DateTime dt2)
{

return DateDiff(interval, dt1, dt2, System.Globalization
.DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek);

}

private static int GetQuarter(int nMonth)
{
if (nMonth <= 3)
return 1;
if (nMonth <= 6)
return 2;
if (nMonth <= 9)
return 3;
return 4;
}

public static long DateDiff(DateInterval interval,
DateTime dt1, DateTime dt2, DayOfWeek eFirstDayOfWeek)
{

if (interval == DateInterval.Year)

return dt2.Year - dt1.Year;

if (interval == DateInterval.Month)

return (dt2.Month - dt1.Month) +
(12 * (dt2.Year - dt1.Year));

TimeSpan ts = dt2 - dt1;

if (interval == DateInterval.Day ||
interval == DateInterval.DayOfYear)
return Round(ts.TotalDays);

if (interval == DateInterval.Hour)
return Round(ts.TotalHours);

if (interval == DateInterval.Minute)
return Round(ts.TotalMinutes);

if (interval == DateInterval.Second)

return Round(ts.TotalSeconds);

if (interval == DateInterval.Weekday)
{
return Round(ts.TotalDays / 7.0);
}

if (interval == DateInterval.WeekOfYear)
{
while (dt2.DayOfWeek != eFirstDayOfWeek)
dt2 = dt2.AddDays(-1);
while (dt1.DayOfWeek != eFirstDayOfWeek)
dt1 = dt1.AddDays(-1);
ts = dt2 - dt1;
return Round(ts.TotalDays / 7.0);
}

if (interval == DateInterval.Quarter)
{
double d1Quarter = GetQuarter(dt1.Month);
double d2Quarter = GetQuarter(dt2.Month);
double d1 = d2Quarter - d1Quarter;
double d2 = (4 * (dt2.Year - dt1.Year));
return Round(d1 + d2);
}
return 0;
}

private static long Round(double dVal)
{
if (dVal >= 0)
return (long)Math.Floor(dVal);
return (long)Math.Ceiling(dVal);
}
#endregion
}

2 comments:

Unknown said...

I used your random date generator to test my list sorting by date string.

You saved me a few minutes, so thanks!

I made an overload for it to, so I could just use it for general testing where the date didn't matter too much.

I encapsulated the 'getRandomDate' into the class too, so you don't have to bother with creating an instance of 'Random'

like this:


public sealed class DateTimeUtil
{
static Random rand = new Random();
public static DateTime GetRandomDate()
{
DateTime minDate = new DateTime(1968, 9, 5);
DateTime maxDate = new DateTime(2008, 6, 1);
return (GetRandomDate(minDate, maxDate));
}

public static DateTime GetRandomDate(DateTime minDate, DateTime maxDate)
{
int totalDays = (int)DateTimeUtil.DateDiff(DateInterval.Day, minDate, maxDate);
int randomDays = rand.Next(0, totalDays);
return minDate.AddDays(randomDays);
}
etc..



Happy programming!

James

Unknown said...

what about using TimeSpan instead?

int totalDays = ((TimeSpan)(maxDate - minDate)).Days;