舍入 DateTime 对象

我希望将日期/时间四舍五入到图表应用程序的最近间隔。我想一个扩展方法签名如下,以便四舍五入可以实现任何水平的准确性:

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

这个想法是,如果我在10分钟的时间跨度内通过,它将四舍五入到最接近的10分钟间隔。我无法理解这个实现,我希望你们之中有人以前写过或者使用过类似的东西。

我认为无论是地板,天花板或最近的执行是好的。

有什么想法吗?

编辑: 感谢@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));
...

干杯!

42695 次浏览

只要使用刻度,用它来除,满足/天花板/周围的价值,并乘以它回来。

地板

long ticks = date.Ticks / span.Ticks;


return new DateTime( ticks * span.Ticks, date.Kind );

四舍五入(中点向上)

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


return new DateTime( ticks * span.Ticks, date.Kind );

天花板

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


return new DateTime( ticks * span.Ticks, date.Kind );

你也应该清楚,如果你想你的舍入:

  1. 在音程的开始、结束或中间
    • start is the easiest and often the expected but you should be clear in your initial spec.
  2. 如何使边界情况圆满。
    • 通常情况下,只有当你四舍五入到中间而不是结束时,才会出现问题。
    • 由于四舍五入到中间是一个无偏见的答案的尝试,你需要使用像 四舍五入这样的东西在技术上四舍五入一半,甚至是真正免于偏见。

很有可能你真的只关心第一点,但是在这些“简单”的问题中,当你在现实世界中使用它时(通常在接近于零的间隔) ,结果会产生深远的影响

tvanfosson's solution's cover all the cases listed in 1. 中点的例子是偏向上的。这是值得怀疑的问题,这将是一个与时间有关的舍入。

这样你就可以四舍五入到任意给定的时间间隔,而且比除法和乘法的速度稍微快一点。

public static class DateTimeExtensions
{
public static DateTime Floor(this DateTime dateTime, TimeSpan interval)
{
return dateTime.AddTicks(-(dateTime.Ticks % interval.Ticks));
}


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


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


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


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

如果你只是想四舍五入小时到最高价值

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