How to round time to the nearest quarter hour in JavaScript?

For example:

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


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

Should be pretty simple. But all I was able to produce is lengthy, not very good code to solve the issue. My mind's just gone blank.

Regards

72705 次浏览

假设变量中有小时和分钟(如果没有,也可以通过使用 Date实例 功能Date实例中获取) :

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

minutes can as well be calculated by using 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 中可能会有不同的处理)。 //----

The code here is a little verbose but I'm sure you'll see how you could combine the lines to make this shorter. I've left it this way to clearly show the steps:

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

这个函数的周期是从一刻钟到最近的一刻钟。

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

可以帮助其他人。对于任何语言。主要是圆功能的把戏。

roundedMinutes = yourRoundFun(Minutes / interval) * interval

间隔可以是5分钟,10分钟,15分钟,30分钟。 然后四舍五入的分钟可以重置到各自的日期。

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

also if required then

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

简单?

带有时间字符串

这里有一个方法,它将围绕一个时间字符串,就像你提出的一样。例如“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

有一个 NPM 包裹 @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

Divide by 9e5 milliseconds (15 * 60 * 1000), round, and multiply back by 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) )

另一个带 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);

以毫秒为单位传递时间间隔,按舍入顺序得到下一个循环

例如,如果我想要从当前时间开始的下一个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));

这个方法特别适用于 Vue.js,它需要一段时间,然后返回最接近输入的增量,我基于上面的答案,但这是针对 Vue 的,特别是使用 echma-6标准。它会返回 T: 06:00:00,如果你输入06:05。这是专门与 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分钟间隔的时间。 If you enter, 11:01, you'd get T11:00:00

我使用这些代码:

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