Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roundoff Timespan to 15 min interval

Tags:

c#

I have a property in my code where users can enter a timespan in HH:mm like

10:32
10:44
15:45

I want to round off in my property to the nearest 15mins but i dont have datetime here. I only need to do it with Timespan

10:32 to 10:30
10:44 to 10:45
15:45 to 15:45
01:02 to 01:00
02:11 to 02:15
03:22 to 03:15
23:52 to 00:00

Tried all these solutions but they involve Datetime in them

How can I round up the time to the nearest X minutes?
Is there a simple function for rounding a DateTime down to the nearest 30 minutes, in C#?
DotNet Roundoff datetime to last 15 minutes

like image 237
s-a-n Avatar asked Jun 03 '14 02:06

s-a-n


4 Answers

I think you want something like this:

public static class TimeSpanExtensions
{
    public static TimeSpan RoundToNearestMinutes(this TimeSpan input, int minutes)
    {
        var totalMinutes = (int)(input + new TimeSpan(0, minutes/2, 0)).TotalMinutes;

        return new TimeSpan(0, totalMinutes - totalMinutes % minutes, 0);
    }
}

If you pass in 15 as your chosen interval for rounding, the function will first add 7 mins, then round down to the nearest 15 mins. This should give you what you want.

Because the above is written an extension method, you can use it like this:

var span1 = new TimeSpan(0, 10, 37, 00).RoundToNearestMinutes(15);
var span2 = new TimeSpan(0, 10, 38, 00).RoundToNearestMinutes(15);

The first one becomes 10:30, and the second one becomes 10:45 (as desired).

like image 129
Baldrick Avatar answered Nov 18 '22 19:11

Baldrick


I liked Baldrick's answer but I discovered that it does not work when using negative TimeSpan values (as in the case of time zone offsets).

I amended his original code as follows and this seems to work for both positive and negative TimeSpan values.

public static class TimeSpanExtensions
{
    public static TimeSpan RoundToNearestMinutes(this TimeSpan input, int minutes)
    {
        var halfRange = new TimeSpan(0, minutes/2, 0);
        if (input.Ticks < 0)
            halfRange = halfRange.Negate();
        var totalMinutes = (int)(input + halfRange).TotalMinutes;
        return new TimeSpan(0, totalMinutes - totalMinutes % minutes, 0);
    }
}
like image 35
Larry C Avatar answered Nov 18 '22 20:11

Larry C


I know this is rather late, but I thought it might be useful for anyone looking for an answer, as I was when I found this question. Note that this can be used to round up to units of any length of time, and can be easily modified to round down or round to the nearest block of time (by changing Math.Ceiling to Math.Floor or Math.Round)

public TimeSpan RoundTimeSpanUp(TimeSpan span, TimeSpan roundingTimeSpan)
{
    long originalTicks = roundingTimeSpan.Ticks;
    long roundedTicks = (long)(Math.Ceiling((double)span.Ticks / originalTicks) * originalTicks);
    TimeSpan result = new TimeSpan(roundedTicks);
    return result;
}

It can be used like this:

TimeSpan roundedMinutes = RoundTimeSpanUp(span, TimeSpan.FromMinutes(15));

or to round up by any unit of time, like this:

TimeSpan roundedHours = RoundTimeSpanUp(span, TimeSpan.FromHours(1));

like image 35
Rosemarie M. Avatar answered Nov 18 '22 20:11

Rosemarie M.


I realize this is quite late, however the answer provided by @Baldrick inspired my own solution:

public static class TimeSpanExtensions
{
    /// <summary>
    /// Rounds a TimeSpan based on the provided values.
    /// </summary>
    /// <param name="ts">The extension target.</param>
    /// <param name="Direction">The direction in which to round.</param>
    /// <param name="MinutePrecision">The precision to round to.</param>
    /// <returns>A new TimeSpan based on the provided values.</returns>
    public static System.TimeSpan Round(this System.TimeSpan ts, 
        RoundingDirection Direction, 
        int MinutePrecision)
    {
        if(Direction == RoundingDirection.Up)
        {
            return System.TimeSpan.FromMinutes(
                MinutePrecision * Math.Ceiling(ts.TotalMinutes / MinutePrecision)); 
        }

        if(Direction == RoundingDirection.Down)
        {
            return System.TimeSpan.FromMinutes(
                MinutePrecision * Math.Floor(ts.TotalMinutes / MinutePrecision)); 
        }

        // Really shouldn't be able to get here...
        return ts; 
    }
}

/// <summary>
/// Rounding direction used in rounding operations. 
/// </summary>
public enum RoundingDirection
{
    /// <summary>
    /// Round up.
    /// </summary>
    Up, 
    /// <summary>
    /// Round down.
    /// </summary>
    Down
}
like image 36
SeanH Avatar answered Nov 18 '22 19:11

SeanH