【问题标题】:Roundoff Timespan to 15 min interval舍入时间跨度到 15 分钟间隔
【发布时间】:2014-06-03 02:33:33
【问题描述】:

我的代码中有一个属性,用户可以在其中输入 HH:mm 中的时间跨度,例如

10:32
10:44
15:45

我想在我的财产中四舍五入到最近的 15 分钟,但我这里没有日期时间。我只需要使用 Timespan 来完成

10:32 to 10:30
10:44 to 10:45
15:45 to 15:45
01:02 to 01:00
02:11 to 02:15
03:22 to 03:15
23:52 to 00:00

尝试了所有这些解决方案,但其中涉及日期时间

How can I round up the time to the nearest X minutes?
Is there a simple function for rounding a DateTime down to the nearest 30 minutes, in C#?
DotNet Roundoff datetime to last 15 minutes

【问题讨论】:

  • TimeSpan 是一个不可变结构,因此您无法更改已创建的实例,但您可以通过提取其部分从现有的TimeSpan 创建一个新的TimeSpanTimeSpan 公开 Minutes 属性 - 提取此值,四舍五入到最接近的一刻钟(确保如果四舍五入到第 60 分钟,则增加 Hours,如果四舍五入到第 24 小时,则增加 @ 987654331@),并创建TimeSpan 的新实例。

标签: c#


【解决方案1】:

我想你想要这样的东西:

public static class TimeSpanExtensions
{
    public static TimeSpan RoundToNearestMinutes(this TimeSpan input, int minutes)
    {
        var totalMinutes = (int)(input + new TimeSpan(0, minutes/2, 0)).TotalMinutes;

        return new TimeSpan(0, totalMinutes - totalMinutes % minutes, 0);
    }
}

如果您传入 15 作为您选择的舍入间隔,该函数将首先添加 7 分钟,然后向下舍入到最接近的 15 分钟。这应该会给你你想要的。

因为上面写的是扩展方法,所以可以这样使用:

var span1 = new TimeSpan(0, 10, 37, 00).RoundToNearestMinutes(15);
var span2 = new TimeSpan(0, 10, 38, 00).RoundToNearestMinutes(15);

第一个变为 10:30,第二个变为 10:45(根据需要)。

【讨论】:

  • 不应该返回 new Timespan(input.Hours, minutes - minutes % 15, input.Seconds)??
  • @softwaregeek:不,因为我之前已经转换为TotalMinutes
  • @softwaregeek:不用担心!感谢审核! :)
  • 更简单的算法是:return new TimeSpan(0, Math.Round(input.TotalMinutes / minutes) * minutes, 0);
  • @s-a-n:这里的规则是什么? 52 距离 45 距离 7 分钟,但距离 00 距离 8 分钟。那你为什么要四舍五入呢?另外,在您的要求中,您能解释一下为什么将 03:22 舍入到 03:25 吗? 03:25 不是 15 分钟的倍数。我认为您可能需要更新您的问题以澄清这些要点。
【解决方案2】:

我喜欢 Baldrick 的回答,但我发现它在使用负 TimeSpan 值时不起作用(例如在时区偏移的情况下)。

我将他的原始代码修改如下,这似乎适用于正负 TimeSpan 值。

public static class TimeSpanExtensions
{
    public static TimeSpan RoundToNearestMinutes(this TimeSpan input, int minutes)
    {
        var halfRange = new TimeSpan(0, minutes/2, 0);
        if (input.Ticks < 0)
            halfRange = halfRange.Negate();
        var totalMinutes = (int)(input + halfRange).TotalMinutes;
        return new TimeSpan(0, totalMinutes - totalMinutes % minutes, 0);
    }
}

【讨论】:

    【解决方案3】:

    我知道这已经很晚了,但我认为它可能对任何寻找答案的人有用,就像我发现这个问题时一样。请注意,这可用于四舍五入到任何时间长度的单位,并且可以轻松修改为向下舍入或四舍五入到最近的时间块(通过将 Math.Ceiling 更改为 Math.Floor 或 Math.Round)

    public TimeSpan RoundTimeSpanUp(TimeSpan span, TimeSpan roundingTimeSpan)
    {
        long originalTicks = roundingTimeSpan.Ticks;
        long roundedTicks = (long)(Math.Ceiling((double)span.Ticks / originalTicks) * originalTicks);
        TimeSpan result = new TimeSpan(roundedTicks);
        return result;
    }
    

    可以这样使用:

    TimeSpan roundedMinutes = RoundTimeSpanUp(span, TimeSpan.FromMinutes(15));

    或按任何时间单位进行四舍五入,如下所示:

    TimeSpan roundedHours = RoundTimeSpanUp(span, TimeSpan.FromHours(1));

    【讨论】:

    • 这是更通用和更清洁的解决方案。 +1,让它成为公认的答案。
    【解决方案4】:

    我意识到这已经很晚了,但是@Baldrick 提供的答案启发了我自己的解决方案:

    public static class TimeSpanExtensions
    {
        /// <summary>
        /// Rounds a TimeSpan based on the provided values.
        /// </summary>
        /// <param name="ts">The extension target.</param>
        /// <param name="Direction">The direction in which to round.</param>
        /// <param name="MinutePrecision">The precision to round to.</param>
        /// <returns>A new TimeSpan based on the provided values.</returns>
        public static System.TimeSpan Round(this System.TimeSpan ts, 
            RoundingDirection Direction, 
            int MinutePrecision)
        {
            if(Direction == RoundingDirection.Up)
            {
                return System.TimeSpan.FromMinutes(
                    MinutePrecision * Math.Ceiling(ts.TotalMinutes / MinutePrecision)); 
            }
    
            if(Direction == RoundingDirection.Down)
            {
                return System.TimeSpan.FromMinutes(
                    MinutePrecision * Math.Floor(ts.TotalMinutes / MinutePrecision)); 
            }
    
            // Really shouldn't be able to get here...
            return ts; 
        }
    }
    
    /// <summary>
    /// Rounding direction used in rounding operations. 
    /// </summary>
    public enum RoundingDirection
    {
        /// <summary>
        /// Round up.
        /// </summary>
        Up, 
        /// <summary>
        /// Round down.
        /// </summary>
        Down
    }
    

    【讨论】:

      【解决方案5】:

      我在一个旧的 asp 表单应用程序的代码隐藏中组合了以下逻辑,以从 UI 中的隐藏字段中获取 dateTime 字符串并计算客户端和服务器之间的差异。

       private TimeSpan calculateVariance(string dateString)
              {
                  DateTime clientHour = Convert.ToDateTime(dateString);
                  DateTime serverHour = DateTime.Now.ToLocalTime();
                  TimeSpan timeVariance = clientHour - serverHour;
      
                  TimeSpan roundedTimeVariance;
      
                  //ROUND VARIANCE TO THE NEAREST 15 minutes AND RETURN AS EITHER A POSITIVE OR NEGATIVE TimeSpan Object
                  if (timeVariance.Minutes > 52)
                  {
                      roundedTimeVariance = new TimeSpan(timeVariance.Hours + 1, 0, 0);
                  }
                  else if (timeVariance.Minutes > 37)
                  {
                      roundedTimeVariance = new TimeSpan(timeVariance.Hours, 45, 0);
                  }
                  else if (timeVariance.Minutes > 22)
                  {
                      roundedTimeVariance = new TimeSpan(timeVariance.Hours, 30, 0 );
                  }
                  else if (timeVariance.Minutes > 7)
                  {
                      roundedTimeVariance = new TimeSpan(timeVariance.Hours, 15, 0);
                  }
                  else
                  {
                      roundedTimeVariance = new TimeSpan(timeVariance.Hours, 0, 0);
                  }
      
                  return roundedTimeVariance;
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-24
        • 1970-01-01
        • 2023-03-16
        • 2013-10-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多