舍入DateTime对象

gre*_*ade 100 c# algorithm

我想将日期/时间舍入到图表应用程序的最近区间.我想要一个像下面这样的扩展方法签名,以便可以在任何精度级别上实现舍入:

static DateTime Round(this DateTime date, TimeSpan span);
Run Code Online (Sandbox Code Playgroud)

我的想法是,如果我通过十分钟的时间跨度,它将四舍五入到最接近的十分钟间隔.我不能理解我的实施,并希望你们中的一个人之前会写过或使用类似的东西.

我认为楼层,天花板或最近的实施都可以.

有任何想法吗?

编辑:感谢@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

被称为如此:

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));
...
Run Code Online (Sandbox Code Playgroud)

干杯!

tva*_*son 123

地板

long ticks = date.Ticks / span.Ticks;

return new DateTime( ticks * span.Ticks );
Run Code Online (Sandbox Code Playgroud)

回合(中点)

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

return new DateTime( ticks * span.Ticks );
Run Code Online (Sandbox Code Playgroud)

天花板

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

return new DateTime( ticks * span.Ticks );
Run Code Online (Sandbox Code Playgroud)

  • 我最近遇到了一个没有保留 DateTimeKind 的问题。以下对每个方法中最后一行的调整对我的情况有所帮助:`return new DateTime(ticks * span.Ticks, date.Kind);` (6认同)

aj.*_*lan 35

这将让你四舍五入到给定的任何间隔.它也比分割然后乘以刻度稍快.

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));
  }
}
Run Code Online (Sandbox Code Playgroud)


Shu*_*oUk 10

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

  1. 间隔的开始,结束或中间
    • 开始是最简单的,往往是预期的,但你应该在你的初始规范中明确.
  2. 您希望边界情况如何变圆.
    • 通常只是一个问题,如果你四舍五入到中间而不是结束.
    • 由于四舍五入到中间是尝试一个无偏见的答案,你需要使用像银行家舍入这样的东西技术上圆半,甚至真正摆脱偏见.

很可能你真的只关心第一点,但在这些"简单"的问题中,当你在现实世界中使用它时,产生的行为会产生深远的影响(通常在零点附近)

tvanfosson的解决方案涵盖了1中列出的所有案例.中点示例偏向上.令人怀疑的是,这将成为与时间相关的四舍五入的问题.