【问题标题】:How to round time to the nearest quarter hour in JavaScript?如何在 JavaScript 中将时间四舍五入到最接近的一刻钟?
【发布时间】:2011-06-25 11:48:03
【问题描述】:

例如:

Given time: 08:22 => Rounded to: 08:15

Given time: 08:23 => Rounded to: 08:30

应该很简单。但是我所能产生的只是冗长的、不是很好的代码来解决这个问题。我脑子里一片空白。

问候

【问题讨论】:

标签: javascript time


【解决方案1】:

假设您在变量中有小时和分钟(如果没有,您可以使用Date 实例functionsDate 实例中获取它们):

var m = (parseInt((minutes + 7.5)/15) * 15) % 60;
var h = minutes > 52 ? (hours === 23 ? 0 : ++hours) : hours;

也可以使用Math.round()来计算分钟数:

var m = (Math.round(minutes/15) * 15) % 60;

或者在没有任何函数的情况下使用更复杂的 javascript 表达式:

var m = (((minutes + 7.5)/15 | 0) * 15) % 60;
var h = ((((minutes/105) + .5) | 0) + hours) % 24;

您可以检查 jsPerf 测试,它显示 Math.round() 是三个中最慢的,而主要是最后一个是最快的,因为它只是一个没有任何函数调用的表达式(没有函数调用开销,即堆栈操作,尽管本机函数可能在 Javascript VM 中被区别对待)。 //----

【讨论】:

  • 速度对我来说不是问题。不用担心这里。谢谢你的帮助。
  • 应该是++hours 而不是hours++?在其当前形式中,hour 在该行执行后递增,这意味着 h 变量获得未递增/不正确的值。
  • @evelyn:你是对的。我编辑了我的代码。感谢您指出如此晦涩难懂的缺陷,可能会让许多非经验丰富的开发人员感到困惑。
  • 由于你不使用几小时后,或者需要++的副作用,所以只需将小时+1,避免所有问题。
  • @MichaelRushton:谢谢迈克。我还添加了一个对许多人来说可能过于复杂的无函数计算,但它可能是三者中最快的。
【解决方案2】:

这里的代码有点冗长,但我相信您会看到如何组合这些行以使其更短。为了清楚地显示步骤,我将其保留为:

var now = new Date();
var mins = now.getMinutes();
var quarterHours = Math.round(mins/15);
if (quarterHours == 4)
{
    now.setHours(now.getHours()+1);
}
var rounded = (quarterHours*15)%60;
now.setMinutes(rounded);
document.write(now);

【讨论】:

  • 上升一个小时就要加一个小时。
  • @Robert Koritnik:是的,我发帖后才意识到这一点。
  • 这将使秒和毫秒字段不四舍五入。
  • @Lorenz03Tx 有点超出问题的范围,请随时接受我的答案并扩展您自己的答案。
  • 如果时间是晚上 11:46,它不会更改日期的问题
【解决方案3】:

此函数将时间四舍五入到最接近的一刻钟。

function roundTimeQuarterHour(time) {
    var timeToReturn = new Date(time);

    timeToReturn.setMilliseconds(Math.round(timeToReturn.getMilliseconds() / 1000) * 1000);
    timeToReturn.setSeconds(Math.round(timeToReturn.getSeconds() / 60) * 60);
    timeToReturn.setMinutes(Math.round(timeToReturn.getMinutes() / 15) * 15);
    return timeToReturn;
}

【讨论】:

  • 你是这个方法的英雄!对于像我这样需要接下来 15 分钟的人,您可以改用“Math.ceil”
  • 你不能只设置毫秒(0)和设置秒(0)吗?还是喜欢你的解决方案
【解决方案4】:

可能会帮助别人。对于任何语言。主要是使用round函数的技巧。

roundedMinutes = yourRoundFun(Minutes / interval) * interval

例如间隔可以是 5 分钟、10 分钟、15 分钟、30 分钟。 然后可以将四舍五入的分钟重置为相应的日期。

yourDateObj.setMinutes(0) 
yourDateObj.setMinutes(roundedMinutes)

如果需要的话也可以

yourDateObj.setSeconds(0) 
yourDateObj.setMilliSeconds(0) 

简单吗?

【讨论】:

    【解决方案5】:

    带时间字符串

    这是一种方法,可以像您介绍的那样对时间字符串进行四舍五入。例如“08:22”

    let roundTime = (time, minutesToRound) => {
    
        let [hours, minutes] = time.split(':');
        hours = parseInt(hours);
        minutes = parseInt(minutes);
    
        // Convert hours and minutes to time in minutes
        time = (hours * 60) + minutes; 
    
        let rounded = Math.round(time / minutesToRound) * minutesToRound;
        let rHr = ''+Math.floor(rounded / 60)
        let rMin = ''+ rounded % 60
    
        return rHr.padStart(2, '0')+':'+rMin.padStart(2, '0')
    }
    
    // USAGE //
    
    // Round time to 15 minutes
    roundTime('8:07', 15); // "08:00"
    roundTime('7:53', 15); // "08:00"
    roundTime('7:52', 15); // "07:45"
    

    小时和分钟已经分开

    如果您不需要像示例所示那样解析小时和分钟字符串,则可以使用此方法

    let roundTime = (hours, minutes, minutesToRound) => {
    
        // Convert hours and minutes to minutes
        time = (hours * 60) + minutes; 
        let rounded = Math.round(time / minutesToRound) * minutesToRound;
    
        let roundedHours = Math.floor(rounded / 60)
        let roundedMinutes = rounded % 60
    
        return { hours: roundedHours, minutes: roundedMinutes }
    }
    
    // USAGE //
    
    // Round time to 15 minutes
    roundTime(7, 52, 15); // {hours: 7, minutes: 45}
    roundTime(7, 53, 15); // {hours: 8, minutes: 0}
    roundTime(1, 10, 15); // {hours: 1, minutes: 15}
    

    使用现有的日期对象

    或者,如果您希望将已经存在的日期对象四舍五入到最接近的 x 分钟,您可以使用此方法。

    如果你不给它任何日期,它将围绕当前时间。在您的情况下,您可以四舍五入到最接近的 15 分钟。

    let getRoundedDate = (minutes, d=new Date()) => {
    
      let ms = 1000 * 60 * minutes; // convert minutes to ms
      let roundedDate = new Date(Math.round(d.getTime() / ms) * ms);
    
      return roundedDate
    }
    
    
    // USAGE //
    
    // Round existing date to 5 minutes
    getRoundedDate(15, new Date()); // 2018-01-26T00:45:00.000Z
    
    // Get current time rounded to 30 minutes
    getRoundedDate(30); // 2018-01-26T00:30:00.000Z
    

    【讨论】:

    • 很好的答案,包含详细信息、选项和示例!谢谢。
    【解决方案6】:

    有一个NPM package @qc/date-round 可以使用。假设您有一个要舍入的 Date 实例

    import { round } from '@qc/date-round'
    
    const dateIn = ...; // The date to be rounded
    const interval = 15 * 60 * 1000; // 15 minutes (aka quarter hour)
    const dateOut = round(dateIn, interval)
    

    那么你可以使用date-fns来格式化日期

    import format from 'date-fns/format';
    
    console.log(format(dateOut, 'HH:mm')) // 24-hr
    console.log(format(dateOut, 'hh:mm a')) // 12-hr
    

    【讨论】:

      【解决方案7】:

      除以 9e5 毫秒 (15 * 60 * 1000),四舍五入,再乘以 9e5:

      const roundToQuarter = date => new Date(Math.round(date / 9e5) * 9e5)
      
      console.log( roundToQuarter(new Date("1999-12-31T23:52:29.999Z")) ) // 1999-12-31T23:45:00
      
      console.log( roundToQuarter(new Date("1999-12-31T23:52:30.000Z")) ) // 2000-01-01T00:00:00
      
      console.log( roundToQuarter(new Date) )

      【讨论】:

        【解决方案8】:

        另一个带有 date-fns 的(非强制性)

        import {getMinutes, setMinutes, setSeconds, setMilliseconds} from 'date-fns'
        
        let date = new Date();
        let min = getMinutes(date);
        let interval = 3  // in minutes
        let new_min = min - min%interval + interval;
        let new_date = setMilliseconds(setSeconds(setMinutes(date,new_min),0),0)
        
        console.log('Orignal Date : ' + date);
        console.log('Original Minute : ' + min);
        console.log('New Minute : ' + new_min);
        console.log('New Date : ' + new_date);
        

        【讨论】:

          【解决方案9】:

          以毫秒为单位传递间隔以roundUp顺序获取下一个循环

          例如,如果我想从当前时间开始下一个 15 分钟周期,然后调用此方法,如 *calculateNextCycle(15 * 60 * 1000);*

          同样的一刻钟通过间隔

          function calculateNextCycle(interval) {
              const timeStampCurrentOrOldDate = Date.now();
              const timeStampStartOfDay = new Date().setHours(0, 0, 0, 0);
              const timeDiff = timeStampCurrentOrOldDate - timeStampStartOfDay;
              const mod = Math.ceil(timeDiff / interval);
              return new Date(timeStampStartOfDay + (mod * interval));
          }
          
          console.log(calculateNextCycle(15 * 60 * 1000));

          【讨论】:

            【解决方案10】:

            这个方法是专门针对 Vue.js 的,它需要一段时间,然后返回最近输入的增量,我基于上面的答案,但这是专门针对使用 echma-6 标准的 Vue 的。如果您将 06:05 输入它,它将返回 T:06:00:00。这专门与 vuetify 的 v-calendar 一起使用,以每周或每天的格式选择时间。

            这个答案还为 06 小时添加了 0。这与上述答案不同。如果您将 30 更改为 15

            methods: {
              roundTimeAndFormat(datetime, roundTo) {
                const hrsMins = datetime.split(':')
                let min = ((((hrsMins[1] + 7.5) / roundTo) | 0) * roundTo) % 60
                let hr = (((hrsMins[1] / 105 + 0.5) | 0) + hrsMins[0]) % 24
                if (Number(hr) < 10) {
                  hr = ('0' + hr).slice(-2)
                }
                if (min === 0) {
                  min = ('0' + min).slice(-2)
                }
                return 'T' + hr + ':' + min + ':00'
              }
            }
            

            您只需调用:

            this.roundTimeAndFormat(dateTime, 15)
            

            你会得到最接近 15 分钟间隔的时间。 如果你输入,11:01,你会得到 T11:00:00

            【讨论】:

              【解决方案11】:

              我使用这些代码:

              function RoundUp(intervalMilliseconds, datetime){
                  datetime = datetime || new Date();
                  var modTicks = datetime.getTime() % intervalMilliseconds;
                  var delta = modTicks === 0 ? 0  : datetime.getTime() - modTicks;
                  delta += intervalMilliseconds;
                  return new Date(delta);
              }
              
              function RoundDown(intervalMilliseconds, datetime){
                  datetime = datetime || new Date();
                  var modTicks = datetime.getTime() % intervalMilliseconds;
                  var delta = modTicks === 0 ? 0  : datetime.getTime() - modTicks;
                  return new Date(delta);
              }
              
              function Round(intervalMilliseconds, datetime){
                  datetime = datetime || new Date();
                  var modTicks = datetime.getTime() % intervalMilliseconds;
                  var delta = modTicks === 0 ? 0  : datetime.getTime() - modTicks;
                  var shouldRoundUp = modTicks > intervalMilliseconds/2;
                  delta += shouldRoundUp ? intervalMilliseconds : 0;
                  return new Date(delta);
              }
              

              四舍五入到最近的 5 分钟:

              //with current datetime
              var result = Round(5 * 60 * 1000);
              
              //with a given datetime
              var dt = new Date();
              var result = Round(5 * 60 * 1000, dt);
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2020-02-07
                • 1970-01-01
                • 2011-04-03
                • 2015-11-27
                • 1970-01-01
                • 1970-01-01
                • 2011-10-25
                相关资源
                最近更新 更多