Jak zaokrąglać czas do najbliższego kwadransa w JavaScript?

Na przykład:

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

Given time: 08:23 => Rounded to: 08:30
Powinno być całkiem proste. Ale wszystko, co udało mi się wyprodukować, to długi, niezbyt dobry kod do rozwiązania problemu. Mam pustkę w głowie.

Pozdrawiam

Author: holographic-principle, 2011-02-11

9 answers

Biorąc pod uwagę, że w zmiennych są godziny i minuty (jeśli ich nie ma, można je pobrać z instancji Date za pomocą funkcji Date instancja ):

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

Minut można również obliczyć za pomocą Math.round():

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

Lub robi to w bardziej wyrafinowanym wyrażeniu javascript bez żadnych funkcji:

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

Możesz sprawdzić test jsPerf, który pokazuje Math.round() jest najwolniejszy z trzech, podczas gdy głównie ostatni jest najszybszy, ponieważ jest to tylko wyrażenie bez wywołania funkcji (Brak wywołania funkcji narzutu tj. manipulacji stosem, chociaż natywne funkcje mogą być traktowane inaczej w JavaScript VM). //----

 100
Author: Robert Koritnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-07 07:17:37

Ta funkcja jest ustawiana w czasie do najbliższego kwadransa.

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;
}
 20
Author: Antoine Desbois,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-21 09:02:26

With Time String

Oto metoda, która będzie zaokrąglać ciąg czasowy, taki jak ten, który przedstawiłeś. Np "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"

Z godzinami i minutami już rozdzielonymi

Możesz użyć tej metody, jeśli nie musisz analizować ciągów godzin i minut, Jak pokazuje przykład

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}

Z Istniejącym Obiektem Date

Lub, jeśli chcesz zaokrąglić istniejący obiekt date do najbliższych X minut, możesz użyć tej metody.

If you don ' t give it Dowolna data będzie zaokrąglać aktualny czas. W Twoim przypadku możesz zaokrąglić się do najbliższych 15 minut.

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
 14
Author: joshuakcockrell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-30 00:53:51

Kod tutaj jest trochę gadatliwy, ale jestem pewien, że zobaczysz, jak można połączyć linie, aby to skrócić. Zostawiłam to w ten sposób, aby wyraźnie pokazać kroki:

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);
 7
Author: Lazarus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-11 11:19:38

Podziel przez 9e5 milisekund (15 * 60 * 1000), zaokrąglić i pomnożyć przez 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) )
 5
Author: Slai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-16 10:30:38

Istnieje Pakiet NPM @qc/date-round to może być użyte. Biorąc pod uwagę, że masz Date instancję do zaokrąglenia

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)

Wtedy możesz użyć date-fns aby sformatować datę

import format from 'date-fns/format';

console.log(format(dateOut, 'HH:mm')) // 24-hr
console.log(format(dateOut, 'hh:mm a')) // 12-hr
 0
Author: Danny Hurlburt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-04 17:44:08

Kolejny z datą-fns (nieobowiązkowy)

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);
 0
Author: Raja Sekar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-21 16:20:54

Podaj interwał w milisekundach uzyskaj następny cykl w kolejności roundUp

Przykład jeśli chcę następny 15 minutowy cykl od bieżącego czasu, to wywołaj tę metodę jak *calculateNextCycle(15 * 60 * 1000);*

To samo przez kwadrans przechodzić interwał

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));
 0
Author: Shubham Rai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-06 17:02:35

Może pomóc innym. Dla każdego języka. Głównie sztuczka z funkcją rundy.

roundedMinutes = yourRoundFun(Minutes / interval) * interval

Np. interwał może wynosić 5 minut, 10 minut, 15 minut, 30 minut. Następnie zaokrąglone minuty można zresetować do odpowiedniej daty.

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

Również jeśli jest to wymagane

yourDateObj.setSeconds(0) 
yourDateObj.setMilliSeconds(0) 
Proste?
 -1
Author: Sai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-03 18:59:06