18

Is there any kind of mathematical way to cut DateTime down to a exact Hour, Day or so? Similiar to round of a decimal to int.

Period.Day
If the original value was 2011-01-01 13:00:00, it ends up in 2011-01-01 00:00:00

if Period.Hour
If the original value was 2011-03-11 13:32:00, it ends up in 2011-03-11 13:00:00

I think about something like below. This are of course works fine, but the range-array are iterated through anyway, later. Better if I was possible to calculate directly on that iteration, instead of it's own. But someType can't be put into that iteration (it depends on someType).

if (someType == Period.Day)
  range.ForEach(d => d.time = new DateTime(d.time.Year, d.time.Month, d.time.Day,0,0,0));
if (someType == Period.Hour)
  range.ForEach(d => d.time = new DateTime(d.time.Year, d.time.Month, d.time.Day, d.time.Hour, 0, 0));
Independent
  • 2,924
  • 7
  • 29
  • 45

7 Answers7

20

Rounding down to a day is equivalent to time.Date, rounding to nearest (up on midpoint) is simply ( time + 12hours ).Date.

For rounding down to a full hour I can't think of code that's nicer to read than yours. For rounding up to the nearest hour you can apply your code to time + 30mins.

There is probably a faster method for rounding to the nearest hour:

const Int64 HourInTicks=...;
Int64 timeInTicks=time.Ticks;
Int64 trucatedToHour=timeInTicks-timeInTicks%HourInTicks;

But I'd avoid that, unless you really need the performance, which is unlikely.

(My round to nearest might have issues on days where the local time offset changes if you're using local time)

SetFreeByTruth
  • 819
  • 8
  • 23
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • Yes, very small performance difference between those good answers here. So I finally go to the most readable and clear way (because the functionality itself is a little obscure). I keep the foreach but through a "cleardate(date,period)"-method and immedietly after the data source. Which means the whole routine are already done by this loop. – Independent Nov 10 '11 at 15:06
19

To round down to day you can use the DateTime.Date Property.
To round down to hour, I'm afraid you'll have to either use what you did in your example or something like:

d.Date.AddHours(d.Hour)
Svarog
  • 2,188
  • 15
  • 21
2

I believe the following C# code will round a DateTime value to nearest minute, and I think it will be easy to generalize it to round to other units.

//round to nearest minute; add 30 seconds for rounding to nearest minute
effectiveDateTime = effectiveDateTime.AddSeconds(30);
TimeSpan timeComponent = effectiveDateTime.TimeOfDay;
effectiveDateTime = effectiveDateTime.Date;
effectiveDateTime = effectiveDateTime.AddHours(timeComponent.Hours).
     AddMinutes(timeComponent.Minutes);
2

I'll do the following:

private static readonly DateTime Epoch = new DateTime(1970, 1, 1); 
public static DateTime Round(this DateTime d, Period p)
{
    var ts = d - Epoch;

    if (p == Period.Hour)
    {
        var hours = (long)ts.TotalHours;
        return Epoch.AddHours(hours);
    }
    else if (p == Period.Days)
    {
        var days = (long)ts.TotalDays;
        return Epoch.AddDays(days);
    }
    // ...
}
Arnaud F.
  • 8,252
  • 11
  • 53
  • 102
1

Not sure if this approach is effective, but looks quite nice using string format (in this case cutting down to hours):

var date = DateTime.UtcNow;
var cutDownDate = Convert.ToDateTime(date.ToString("yyyy-MM-dd hh"));
Grengas
  • 836
  • 12
  • 16
0

Answer Is there a better way in C# to round a DateTime to the nearest 5 seconds? contains an excellent generic DateTime rounding approach.

Edit: This answer was before the updated question title and is an algorithm for rounding to nearest not rounding down.

Community
  • 1
  • 1
larsmoa
  • 12,604
  • 8
  • 62
  • 85
  • Oh, I looked at that (and just the accepted answer). A nice feature from Matt W. It solve my question completely together with a little modification. RoundOff with TimeSpan.FromTicks(X). I get the ticks from Period.Month / Period.Days and whola, the call is generic! Though it does not provide any performance from my own sample that done double iteration. Developing are sometimes so erratic.. :) – Independent Nov 10 '11 at 14:49
-1

Best method for day:

DateTime now = DateTime.Now;
DateTime roundDay = now.Date;
NizMaS
  • 47
  • 3