2009-09-08 74 views
94

我想将日期/时间舍入到图表应用程序的最近间隔。我想扩展方法签名一样遵循,这样的舍入可来达到的精度的任何级别:舍入日期时间对象

static DateTime Round(this DateTime date, TimeSpan span); 

的想法是,如果我通过在十分钟的时间跨度,它会舍入到最接近十分钟时间间隔。我无法在实施过程中找到自己的头,并希望你们中的一个人能够写下或使用过类似的东西。

我认为楼层,天花板或最近的实施是好的。

任何想法?

编辑:感谢@tvanfosson & @ShuggyCoUk,实施看起来是这样的:

public static class DateExtensions { 
    public static DateTime Round(this DateTime date, TimeSpan span) { 
     long ticks = (date.Ticks + (span.Ticks/2) + 1)/ span.Ticks; 
     return new DateTime(ticks * span.Ticks); 
    } 
    public static DateTime Floor(this DateTime date, TimeSpan span) { 
     long ticks = (date.Ticks/span.Ticks); 
     return new DateTime(ticks * span.Ticks); 
    } 
    public static DateTime Ceil(this DateTime date, TimeSpan span) { 
     long ticks = (date.Ticks + span.Ticks - 1)/span.Ticks; 
     return new DateTime(ticks * span.Ticks); 
    } 
} 

,被称为像这样:

DateTime nearestHour = DateTime.Now.Round(new TimeSpan(1,0,0)); 
DateTime minuteCeiling = DateTime.Now.Ceil(new TimeSpan(0,1,0)); 
DateTime weekFloor = DateTime.Now.Floor(new TimeSpan(7,0,0,0)); 
... 

干杯!

+1

这里的某些实现的效果也会有所帮助:http://stackoverflow.com/questions/766626/is-there-一个更好的方式在一个C到四舍五入日期时间到最近5秒 – 2009-09-08 12:27:05

+1

可能的重复[是否有更好的方法来修剪日期时间到一个特定的精度?](http: //sackoverflow.com/questions/152774/is-there-a-better-way-to-trim-a-datetime-to-a-specific-precision) – 2010-05-25 17:18:27

+1

不要忘了将原始的DateTimeKind添加到新创建的日期前:new DateTime(ticks * span.Ticks,date.Kind); – 2013-11-14 17:29:19

回答

112

long ticks = date.Ticks/span.Ticks; 

return new DateTime(ticks * span.Ticks); 

回合(最多的中点)

long ticks = (date.Ticks + (span.Ticks/2) + 1)/ span.Ticks; 

return new DateTime(ticks * span.Ticks); 

天花板

long ticks = (date.Ticks + span.Ticks - 1)/ span.Ticks; 

return new DateTime(ticks * span.Ticks); 
2

只需使用Ticks,使用Ticks来划分floor/ceil/round的值,然后再乘以它。

10

,如果你希望你的舍入到你也应该清楚:

  1. 要到区间的开始,结束或中间
    • 开始是最简单且经常是预期的,但您应该在初始规范中明确指出。
  2. 如何让边界案例四舍五入。
    • 通常只有一个问题,如果你四舍五入到中间而不是结束。
    • 由于舍入到中间是一个无偏见的答案的尝试,你需要在技术上使用类似Bankers Rounding的东西,甚至可以真正摆脱偏见。

这是很可能,你真正关心的是第一点,但在这些“简单”的问题,你在现实世界中的时间间隔使用(通常所产生的行为有深远的影响相邻零)

tvanfosson的解决方案涵盖了所有在1中列出的案例。 中点示例偏向上。这是一个与时间有关的问题,这是值得怀疑的。

28

这会让你四舍五入到给定的间隔。它也比分割然后乘以蜱略快。

private static DateTime Floor(DateTime dateTime, TimeSpan interval) 
{ 
    return dateTime.AddTicks(-(dateTime.Ticks % interval.Ticks)); 
} 

private static DateTime Ceiling(DateTime dateTime, TimeSpan interval) 
{ 
    var overflow = dateTime.Ticks % interval.Ticks; 

    return overflow == 0 ? dateTime : dateTime.AddTicks(interval.Ticks - overflow); 
} 

private static DateTime Round(DateTime dateTime, TimeSpan interval) 
{ 
    var halfIntervalTicks = (interval.Ticks + 1) >> 1; 

    return dateTime.AddTicks(halfIntervalTicks - ((dateTime.Ticks + halfIntervalTicks) % interval.Ticks)); 
} 
-3

如果你只想小时围捕到峰顶值

Console.WriteLine(DateTime.Now.ToString("M/d/yyyy hh:00:00")); 
+0

OP请求DateTime作为返回对象。 – 2017-10-17 01:04:33