【问题标题】:Rounding DateTime objects舍入 DateTime 对象
【发布时间】:2010-11-26 11:50:57
【问题描述】:

我想将日期/时间四舍五入到图表应用程序的最近间隔。我想要一个如下的扩展方法签名,以便可以实现任何精度级别的舍入:

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));
...

干杯!

【问题讨论】:

标签: c# algorithm


【解决方案1】:

只需使用刻度,用它来划分、下限/舍入/舍入值,然后将其乘回。

【讨论】:

    【解决方案2】:

    楼层

    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 );
    

    【讨论】:

    • 我最近遇到了一个未保留 DateTimeKind 的问题。在我的情况下,对每种方法的最后一行进行以下调整:return new DateTime(ticks * span.Ticks, date.Kind);
    【解决方案3】:

    如果您希望四舍五入,您也应该清楚:

    1. 位于区间的开始、结束或中间
      • start 是最简单的并且通常是预期的,但您应该在初始规范中明确。
    2. 您希望边界情况如何舍入。
      • 通常只有在舍入到中间而不是末尾时才会出现问题。
      • 由于四舍五入是一种尝试无偏见的答案,因此您需要使用类似 Bankers Rounding 之类的东西,从技术上讲,四舍五入甚至是真正没有偏见。

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

    tvanfosson 的解决方案涵盖了 1 中列出的所有情况。 中点示例偏向上。值得怀疑的是,这是否会成为时间相关舍入的问题。

    【讨论】:

      【解决方案4】:

      这将使您可以四舍五入到给定的任何间隔。它也比除法然后乘以刻度稍快。

      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));
        }
      }
      

      【讨论】:

        【解决方案5】:

        如果您只想将小时数四舍五入到上限值

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

        【讨论】:

        • OP 请求一个 DateTime 作为返回对象。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-27
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        • 2011-05-17
        • 1970-01-01
        相关资源
        最近更新 更多