By TimS


2011-08-11 16:17:44 8 Comments

Is there a simple function for rounding UP a DateTime to the nearest 15 minutes?

E.g.

2011-08-11 16:59 becomes 2011-08-11 17:00

2011-08-11 17:00 stays as 2011-08-11 17:00

2011-08-11 17:01 becomes 2011-08-11 17:15

11 comments

@soulflyman 2018-09-18 13:27:27

My version

DateTime newDateTimeObject = oldDateTimeObject.AddMinutes(15 - oldDateTimeObject.Minute % 15);

As a method it would lock like this

public static DateTime GetNextQuarterHour(DateTime oldDateTimeObject)
{
    return oldDateTimeObject.AddMinutes(15 - oldDateTimeObject.Minute % 15);
}

and is called like that

DateTime thisIsNow = DateTime.Now;
DateTime nextQuarterHour = GetNextQuarterHour(thisIsNow);

@Du D. 2018-04-25 16:27:51

You can use this method, it uses the specified date to ensure it maintains any of the globalization and datetime kind previously specified in the datetime object.

const long LNG_OneMinuteInTicks = 600000000;
/// <summary>
/// Round the datetime to the nearest minute
/// </summary>
/// <param name = "dateTime"></param>
/// <param name = "numberMinutes">The number minute use to round the time to</param>
/// <returns></returns>        
public static DateTime Round(DateTime dateTime, int numberMinutes = 1)
{
    long roundedMinutesInTicks = LNG_OneMinuteInTicks * numberMinutes;
    long remainderTicks = dateTime.Ticks % roundedMinutesInTicks;
    if (remainderTicks < roundedMinutesInTicks / 2)
    {
        // round down
        return dateTime.AddTicks(-remainderTicks);
    }

    // round up
    return dateTime.AddTicks(roundedMinutesInTicks - remainderTicks);
}

.Net Fiddle Test

If you want to use the TimeSpan to round, you can use this.

/// <summary>
/// Round the datetime
/// </summary>
/// <example>Round(dt, TimeSpan.FromMinutes(5)); => round the time to the nearest 5 minutes.</example>
/// <param name = "dateTime"></param>
/// <param name = "roundBy">The time use to round the time to</param>
/// <returns></returns>        
public static DateTime Round(DateTime dateTime, TimeSpan roundBy)
{            
    long remainderTicks = dateTime.Ticks % roundBy.Ticks;
    if (remainderTicks < roundBy.Ticks / 2)
    {
        // round down
        return dateTime.AddTicks(-remainderTicks);
    }

    // round up
    return dateTime.AddTicks(roundBy.Ticks - remainderTicks);
}

TimeSpan Fiddle

@DotnetShadow 2019-04-14 23:46:23

What happens if you want to round to the nearest 7th minute var d = new DateTime(2019, 04, 15, 9, 40, 0, 0); // should be 9:42 but none of these methods work like that?

@DotnetShadow 2019-04-14 23:52:10

Edit looks like @soulflyman answer would produce the right result

@dtb 2011-08-11 16:25:08

DateTime RoundUp(DateTime dt, TimeSpan d)
{
    return new DateTime((dt.Ticks + d.Ticks - 1) / d.Ticks * d.Ticks, dt.Kind);
}

Example:

var dt1 = RoundUp(DateTime.Parse("2011-08-11 16:59"), TimeSpan.FromMinutes(15));
// dt1 == {11/08/2011 17:00:00}

var dt2 = RoundUp(DateTime.Parse("2011-08-11 17:00"), TimeSpan.FromMinutes(15));
// dt2 == {11/08/2011 17:00:00}

var dt3 = RoundUp(DateTime.Parse("2011-08-11 17:01"), TimeSpan.FromMinutes(15));
// dt3 == {11/08/2011 17:15:00}

@JYelton 2011-08-11 16:42:55

This solution just made it into my utility library as an extension method.

@Theo 2013-06-14 20:21:29

I'm bad at math. What would the RoundDown() equivalent look like? ...Found that... I'll leave an answer.

@dtb 2013-06-14 20:23:16

@Paul Raff 2014-04-03 17:28:22

Watch out for rounding times that are near the upper extreme. This can cause an exception to be thrown if the Ticks you calculate is greater than DateTime.MaxValue.Ticks. Be safe and take the minimum of your calculated value and DateTime.MaxValue.Ticks.

@user1454265 2014-05-16 19:51:50

Why does this work? I'm having a hard time visualizing this.

@Evren Kuzucuoglu 2014-07-14 12:37:57

Are you not losing information from the DateTime object with this method? Like the kind and the time zone, if there are set?

@Diego Frehner 2014-08-09 10:13:30

@user14.. The ( + d.Ticks - 1) makes sure it will round up if necessary. The / and * are rounding. Example round 12 to the next 5: (12 + 5 - 1) = 16, 16 / 5 = 3 (because it is an integer datatype), 3 * 5 = 15. tada :)

@LuckyLikey 2015-05-27 05:30:04

@DiegoFrehner Thanks for beeing my captain

@njy 2016-04-08 13:17:36

@dtb one small addition, otherwise it is probably a little bugged: you need to keep the datetime kind ;-) DateTime RoundUp(DateTime dt, TimeSpan d) { return new DateTime(((dt.Ticks + d.Ticks - 1) / d.Ticks) * d.Ticks, dt.Kind); }

@DotnetShadow 2019-04-14 23:46:08

What happens if you want to round to the nearest 7th minute var d = new DateTime(2019, 04, 15, 9, 40, 0, 0); // should be 9:42 but none of these methods work like that?

@DotnetShadow 2019-04-14 23:53:02

Edit looks like @soulflyman answer would produce the right result

@redent84 2013-11-18 11:08:18

Came up with a solution that doesn't involve multiplying and dividing long numbers.

public static DateTime RoundUp(this DateTime dt, TimeSpan d)
{
    var modTicks = dt.Ticks % d.Ticks;
    var delta = modTicks != 0 ? d.Ticks - modTicks : 0;
    return new DateTime(dt.Ticks + delta, dt.Kind);
}

public static DateTime RoundDown(this DateTime dt, TimeSpan d)
{
    var delta = dt.Ticks % d.Ticks;
    return new DateTime(dt.Ticks - delta, dt.Kind);
}

public static DateTime RoundToNearest(this DateTime dt, TimeSpan d)
{
    var delta = dt.Ticks % d.Ticks;
    bool roundUp = delta > d.Ticks / 2;
    var offset = roundUp ? d.Ticks : 0;

    return new DateTime(dt.Ticks + offset - delta, dt.Kind);
}

Usage:

var date = new DateTime(2010, 02, 05, 10, 35, 25, 450); // 2010/02/05 10:35:25
var roundedUp = date.RoundUp(TimeSpan.FromMinutes(15)); // 2010/02/05 10:45:00
var roundedDown = date.RoundDown(TimeSpan.FromMinutes(15)); // 2010/02/05 10:30:00
var roundedToNearest = date.RoundToNearest(TimeSpan.FromMinutes(15)); // 2010/02/05 10:30:00

@viggity 2014-01-07 16:45:59

I thought for sure that this would be faster than using multiplication and division, but my testing shows that it isn't. This over 10000000 iterations, the modulus method took ~610ms on my machine, while the mult/div method took ~500ms. I guess FPUs make the concerns of old a non-issue. Here is my test code: pastie.org/8610460

@TravisWhidden 2015-01-08 23:01:36

Great use of extensions. Thanks!

@Alovchin 2015-03-30 16:23:47

Thanks for the solution! I just used it in my project. And I have a small update to your solution to eliminate side effects: ... return new DateTime(dt.Ticks + delta, dt.Kind); Note the dt.Kind constructor parameter. To demonstrate side effects, I have created a small test program (can be launched in LinqPad): pastebin.com/m84Hake1

@redent84 2015-03-31 13:00:07

@Alovchin Thanks. I've updated the answer. I created this ideone with your code to show the difference: ideone.com/EVKFp5

@Nate Diamond 2016-03-03 21:25:22

This is pretty old, but is the last %d.Ticks in RoundUp necessary? d.Ticks - (dt.Ticks % d.Ticks)) will necessarily be less than d.Ticks, so the answer should be the same correct?

@redent84 2016-03-16 10:18:49

@NateDiamond it seems that you are correct. I've updated the code

@Steven 2016-04-14 20:19:20

Please note that this solution does not take DST into account.

@João Nogueira 2016-06-29 11:35:11

You have to consider that a date might already be rounded up! var date = new DateTime(2010, 02, 05, 10, 0, 0, 0) var roundedUp = date.RoundUp(TimeSpan.FromMinutes(60)); yields 2010/02/05 11:00:00 with your code (should be 10:00:00) Correction: public static DateTime RoundUp(this DateTime dt, TimeSpan d) { var modTicks = (dt.Ticks%d.Ticks); var delta = d.Ticks - (modTicks); if (modTicks == 0) { delta = 0; } return new DateTime(dt.Ticks + delta, dt.Kind); }

@redent84 2016-06-29 11:44:49

@JoãoNogueira thanks for the catch up. Updated.

@Alex 2017-02-16 15:17:29

Just pointing out, modulus is a requires a division operation on the CPU. But I agree that it is more elegant that using the rouding down property of integer divisions.

@dodgy_coder 2016-05-09 08:14:01

This is a simple solution to round up to the nearest 1 minute. It preserves the TimeZone and Kind information of the DateTime. It can be modified to suit your own needs further (if you need to round to the nearest 5 minutes, etc).

DateTime dbNowExact = DateTime.Now;
DateTime dbNowRound1 = (dbNowExact.Millisecond == 0 ? dbNowExact : dbNowExact.AddMilliseconds(1000 - dbNowExact.Millisecond));
DateTime dbNowRound2 = (dbNowRound1.Second == 0 ? dbNowRound1 : dbNowRound1.AddSeconds(60 - dbNowRound1.Second));
DateTime dbNow = dbNowRound2;

@Bo Sunesen 2015-08-31 10:43:55

A more verbose solution, that uses modulo and avoids unnecessary calculation.

public static class DateTimeExtensions
{
    public static DateTime RoundUp(this DateTime dt, TimeSpan ts)
    {
        return Round(dt, ts, true);
    }

    public static DateTime RoundDown(this DateTime dt, TimeSpan ts)
    {
        return Round(dt, ts, false);
    }

    private static DateTime Round(DateTime dt, TimeSpan ts, bool up)
    {
        var remainder = dt.Ticks % ts.Ticks;
        if (remainder == 0)
        {
            return dt;
        }

        long delta;
        if (up)
        {
            delta = ts.Ticks - remainder;
        }
        else
        {
            delta = -remainder;
        }

        return dt.AddTicks(delta);
    }
}

@user1978424 2013-01-23 22:36:26

Caution: the formula above is incorrect, i.e. the following:

DateTime RoundUp(DateTime dt, TimeSpan d)
{
    return new DateTime(((dt.Ticks + d.Ticks - 1) / d.Ticks) * d.Ticks);
}

should be rewritten as:

DateTime RoundUp(DateTime dt, TimeSpan d)
{
    return new DateTime(((dt.Ticks + d.Ticks/2) / d.Ticks) * d.Ticks);
}

@Brendan Moore 2014-01-15 08:37:35

I disagree. Since the integer division / d.Ticks rounds down to the nearest 15-min interval (let's calls these "blocks"), adding only a half block doesn't guarantee rounding up. Consider when you have 4.25 blocks. If you add 0.5 blocks, then test how many integer blocks you have, you still only have 4. Adding one tick less than a full block is the correct action. It ensures you always move up to the next block range (before rounding down), but prevents you from moving between exact blocks. (IE, if you added a full block to 4.0 blocks, 5.0 would round to 5, when you want 4. 4.99 will be 4.)

@DevSal 2012-04-12 10:55:59

if you need to round to a nearest time interval (not up) then i suggest to use the following

    static DateTime RoundToNearestInterval(DateTime dt, TimeSpan d)
    {
        int f=0;
        double m = (double)(dt.Ticks % d.Ticks) / d.Ticks;
        if (m >= 0.5)
            f=1;            
        return new DateTime(((dt.Ticks/ d.Ticks)+f) * d.Ticks);
    }

@stitty 2014-12-11 22:25:00

This answer doesn't round correctly. user1978424 has the only post that shows correctly how to round to the nearest interval below: (ironically down-voted because the question was abt rounding UP)

@Vlad Bezden 2011-08-11 16:39:52

void Main()
{
    var date1 = new DateTime(2011, 8, 11, 16, 59, 00);
    date1.Round15().Dump();

    var date2 = new DateTime(2011, 8, 11, 17, 00, 02);
    date2.Round15().Dump();

    var date3 = new DateTime(2011, 8, 11, 17, 01, 23);
    date3.Round15().Dump();

    var date4 = new DateTime(2011, 8, 11, 17, 00, 00);
    date4.Round15().Dump();
}

public static class Extentions
{
    public static DateTime Round15(this DateTime value)
    {   
        var ticksIn15Mins = TimeSpan.FromMinutes(15).Ticks;

        return (value.Ticks % ticksIn15Mins == 0) ? value : new DateTime((value.Ticks / ticksIn15Mins + 1) * ticksIn15Mins);
    }
}

Results:

8/11/2011 5:00:00 PM
8/11/2011 5:15:00 PM
8/11/2011 5:15:00 PM
8/11/2011 5:00:00 PM

@JYelton 2011-08-11 16:49:53

2011-08-11 17:00:01 gets truncated to 2011-08-11 17:00:00

@Vlad Bezden 2011-08-11 17:03:40

@JYelton: Thanks for pointing out +1. I changed my code to accommodate that.

@Adam Garner 2017-07-24 13:23:22

Providing your code Linqpad format for easy verification is a great time saver. Very easy to use.

@Nicholas Carey 2011-08-11 17:24:17

Since I hate reinventing the wheel, I'd probably follow this algorithm to round a DateTime value to a specified increment of time (Timespan):

  • Convert the DateTime value to be rounded to a decimal floating-point value representing the whole and fractional number of TimeSpan units.
  • Round that to an integer, using Math.Round().
  • Scale back to ticks by multiplying the rounded integer by the number of ticks in the TimeSpan unit.
  • Instantiate a new DateTime value from the rounded number of ticks and return it to the caller.

Here's the code:

public static class DateTimeExtensions
{

    public static DateTime Round( this DateTime value , TimeSpan unit )
    {
        return Round( value , unit , default(MidpointRounding) ) ;
    }

    public static DateTime Round( this DateTime value , TimeSpan unit , MidpointRounding style )
    {
        if ( unit <= TimeSpan.Zero ) throw new ArgumentOutOfRangeException("unit" , "value must be positive") ;

        Decimal  units        = (decimal) value.Ticks / (decimal) unit.Ticks ;
        Decimal  roundedUnits = Math.Round( units , style ) ;
        long     roundedTicks = (long) roundedUnits * unit.Ticks ;
        DateTime instance     = new DateTime( roundedTicks ) ;

        return instance ;
    }

}

@HappyNomad 2013-11-26 08:19:00

This is nice code for rounding to the nearest DateTime, but I also want the ability to round up to a multiple of unit . Passing in MidpointRounding.AwayFromZero to Round does not have the desired effect. Do you have something else in mind by accepting a MidpointRounding argument?

@Olaf 2011-08-11 16:28:07

Elegant?

dt.AddSeconds(900 - (x.Minute * 60 + x.Second) % 900)

@Olaf 2011-08-11 16:35:55

A more correct version would be: x.AddSeconds(900 - (x.AddSeconds(-1).Minute * 60 + x.AddSeconds(-1).Second) % 900).AddSeconds(-1), that takes care of the "stays" condition.

Related Questions

Sponsored Content

38 Answered Questions

[SOLVED] How do you get a timestamp in JavaScript?

30 Answered Questions

[SOLVED] Daylight saving time and time zone best practices

64 Answered Questions

[SOLVED] Round to at most 2 decimal places (only if necessary)

27 Answered Questions

[SOLVED] How do I enumerate an enum in C#?

63 Answered Questions

[SOLVED] How do I calculate someone's age in C#?

  • 2008-07-31 23:40:59
  • Jeff Atwood
  • 536228 View
  • 1742 Score
  • 63 Answer
  • Tags:   c# .net datetime

33 Answered Questions

[SOLVED] How to get the current time in Python

  • 2009-01-06 04:54:23
  • user46646
  • 2703319 View
  • 2353 Score
  • 33 Answer
  • Tags:   python datetime time

36 Answered Questions

[SOLVED] Calculate relative time in C#

7 Answered Questions

[SOLVED] How to round a Double to the nearest Int in swift?

29 Answered Questions

[SOLVED] How to round a number to n decimal places in Java

3 Answered Questions

[SOLVED] How to round a time to the nearest 15 minute segment

Sponsored Content