Compare the times needed to loop over dates by using DateTime variables and integers in C#

The example Find all of the Friday the Thirteenths between two dates in C# uses integers to loop over the dates within a range. For every year between the start and end dates, the code considers the 13th of each month in that year. It then ignores any months before the start date and ends the loop if it finds a date after the end date.

This method works and is reasonably fast but it makes sense to wonder if it would be more efficient to not need to test every date to see if it is before the start date or after the end date.

The following code shows how the program compares these two types of loops over a range of dates.

// Compare two methods for looping over the dates.
private void btnGo_Click(object sender, EventArgs e)
{
    txtDateTimeLoop.Clear();
    txtIntLoop.Clear();

    // Test variables.
    DateTime loop_start_time;
    TimeSpan elapsed;
    bool test_bool;

    // Get the start and end date components.
    DateTime start_date = dtpStart.Value.Date;
    DateTime end_date = dtpEnd.Value.Date;
    int start_year = start_date.Year;
    int end_year = end_date.Year;

    // *** Loop by using int variables. ***
    // Loop over the selected years.
    loop_start_time = DateTime.Now;
    for (int year = start_year; year <= end_year; year++)
    {
        // Loop over the months in the year.
        for (int month = 1; month <= 12; month++)
        {
            // See if this month's 13th is a Friday.
            DateTime test_date = new DateTime(year, month, 13);

            // If we haven't reached the start date, skip this one.
            if (test_date < start_date) continue;

            // If we've passed the end date, stop looping.
            if (test_date > end_date) break;

            // See if this is a Friday.
            test_bool = (test_date.DayOfWeek == DayOfWeek.Friday);
        }
    }
    elapsed = DateTime.Now - loop_start_time;
    txtIntLoop.Text = elapsed.TotalSeconds.ToString("0.0000") + " secs";

    // *** Loop by using a DateTime variable. ***
    // Find the first 13th date >= start_date.
    DateTime loop_start = new DateTime(start_year, start_date.Month, 13);
    if (loop_start < start_date) loop_start.AddMonths(1);

    // Find the last 13th date <= end_date.
    DateTime loop_end = new DateTime(end_year, end_date.Month, 13);
    if (loop_end > end_date) loop_end.AddMonths(-1);

    // Time the first loop.
    loop_start_time = DateTime.Now;
    for (DateTime loop_date = loop_start;
        loop_date < loop_end;
        loop_date = loop_date.AddMonths(1))
    {
        test_bool = (loop_date.DayOfWeek == DayOfWeek.Friday);
    }
    elapsed = DateTime.Now - loop_start_time;
    txtDateTimeLoop.Text = elapsed.TotalSeconds.ToString("0.0000") + " secs";
}

The code creates some variables to record start and elapsed times and then gets some information about the selected start and end dates. It then uses integers to represent the years and months in the date range and ignores any dates that fall outside of the range. See the previous example for more information on how that loop works.

Next the code calculates the first 13th of the month greater than or equal to the start date and the last 13th of the month before or equal to the end date. It then uses a DateTime variable to loop over the dates between the start 13th and the end 13th. After each iteration the loop's iteration section uses the DateTime variable's AddMonth method to add 1 month to the variable, making it move to the 13th of the following month.

You can see from the picture that the code that uses integers for looping variables is faster than the code that uses a DateTime looping variable. The difference presumably is because the AddMonths method takes longer than creating a new DateTime from integer parameters. (If you make a simple test program that compares a loop that uses AddMonths and another that create new integers, you'll see that this seems to be the case.)

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.