Monday, August 30, 2010

Trimming/rounding a date time. Floors and ceilings.

Well, first, credit where credit is due. I found this on StackOverflow and only slightly modified it. But it's too good not to share.

This code will let you "round" a date time to any given interval. You can get the floor or ceiling, or do a traditional round.

Here's the code:

public static class Extensions
{
    public static DateTime Floor(this DateTime date, TimeSpan span)
    {
        if (span == TimeSpan.FromMinutes(0))
            return date;
        long ticks = date.Ticks / span.Ticks;
        return new DateTime(ticks * span.Ticks);
    }

    public static DateTime Ceil(this DateTime date, TimeSpan span)
    {
        if (span == TimeSpan.FromMinutes(0))
            return date;
        long ticks = (date.Ticks + span.Ticks - 1) / span.Ticks;
        return new DateTime(ticks * span.Ticks);
    }

    public static DateTime Round(this DateTime date, TimeSpan span)
    {
        if (span == TimeSpan.FromMinutes(0))
            return date;
        long ticks = (date.Ticks + (span.Ticks / 2)) / span.Ticks;
        return new DateTime(ticks * span.Ticks);
    }
}


Here's a simple example using Floor:
DateTime dt = new DateTime(2010, 8, 29, 15, 26, 23);
Console.WriteLine("Floor:");
Console.WriteLine(dt.Floor(TimeSpan.FromSeconds(0)));
Console.WriteLine(dt.Floor(TimeSpan.FromMinutes(1)));
Console.WriteLine(dt.Floor(TimeSpan.FromMinutes(5)));
Console.WriteLine(dt.Floor(TimeSpan.FromMinutes(10)));
Console.WriteLine(dt.Floor(TimeSpan.FromMinutes(60)));
Console.WriteLine();

Console.WriteLine("Ceil:");
Console.WriteLine(dt.Ceil(TimeSpan.FromSeconds(0)));
Console.WriteLine(dt.Ceil(TimeSpan.FromMinutes(1)));
Console.WriteLine(dt.Ceil(TimeSpan.FromMinutes(5)));
Console.WriteLine(dt.Ceil(TimeSpan.FromMinutes(10)));
Console.WriteLine(dt.Ceil(TimeSpan.FromMinutes(60)));
Console.WriteLine();

Console.WriteLine("Round:");
Console.WriteLine(dt.Round(TimeSpan.FromSeconds(0)));
Console.WriteLine(dt.Round(TimeSpan.FromMinutes(1)));
Console.WriteLine(dt.Round(TimeSpan.FromMinutes(5)));
Console.WriteLine(dt.Round(TimeSpan.FromMinutes(10)));
Console.WriteLine(dt.Round(TimeSpan.FromMinutes(60)));
Console.ReadKey();

And here's the output:

Floor:
8/29/2010 3:26:23 PM
8/29/2010 3:26:00 PM
8/29/2010 3:25:00 PM
8/29/2010 3:20:00 PM
8/29/2010 3:00:00 PM

Ceil:
8/29/2010 3:26:23 PM
8/29/2010 3:27:00 PM
8/29/2010 3:30:00 PM
8/29/2010 3:30:00 PM
8/29/2010 4:00:00 PM

Round:
8/29/2010 3:26:23 PM
8/29/2010 3:26:00 PM
8/29/2010 3:25:00 PM
8/29/2010 3:30:00 PM
8/29/2010 3:00:00 PM

No comments:

Post a Comment

Speak your mind.