Gostaria de saber se existe uma maneira de arredondar para cima ou para baixo para o intervalo de 15 minutos mais próximo. Acho que seria ótimo ter esse recurso no momento, já que algumas bibliotecas como datejs meio que têm essa funcionalidade pelo que vi durante a pesquisa. Meu cenário é que tenho pontos de dados que são segmentados em intervalos de 15 minutos. A ferramenta de seleção retorna qualquer bloco de tempo e preciso arredondar para os 15 minutos mais próximos e arredondar para cima para o tempo de término.
Fazê-lo desta forma (http://stackoverflow.com/questions/4968250/how-to-round-time-to-the-nearest-quarter-hour-in-javascript) parece ser uma dor ... quando é seria útil ter na própria biblioteca.
moment.fn.roundMinutes = function () { return ~(this.minutes() / 15) * 15; }
Eu criei isso para meu próprio uso e descobri que pode ajudar outras pessoas. Lembre-se de que ele gira para os próximos 15 minutos.
moment.fn.roundNext15Min = function () {
var intervals = Math.floor(this.minutes() / 15);
if(this.minutes() % 15 != 0)
intervals++;
if(intervals == 4) {
this.add('hours', 1);
intervals = 0;
}
this.minutes(intervals * 15);
this.seconds(0);
return this;
}
EDIT: removido this.incrementHours () em favor de this.add ('horas', 1);
Você pode adicionar essas funções ao momento .. Seria muito legal poder arredondar para o intervalo de tempo mais próximo, próximo e anterior ... Existem milhões de resultados do Google para isso e centenas de upvotes de estouro de pilha ..
Agora que olho para ele novamente, não tenho ideia de como incrementHours estava funcionando.
Eu editei minha postagem sobre o problema com o código corrigido. Aproveitar!
Na segunda-feira, 10 de março de 2014 às 14h29, Blake Niemyjski
notificaçõ[email protected] :
Qual foi a sua função para incrementHours? Eu estou supondo que também fez dias
também.Responda a este e-mail diretamente ou visualize-o no Gi tHubhttps: //github.com/moment/moment/issues/959#issuecomment -37223821
.
obrigado por esse método @zbarnett . Exatamente o que eu precisava para meu projeto
Bem, podemos usar a interface startOf como esta startOf(15, 'm')
. Pode funcionar para todas as unidades. Aguardando PRs :)
Aqui está uma fórmula bem simples (na sintaxe Coffeescript, já que é o contexto onde me deparei com esse problema):
round_interval = 15
remainder = time.minute() % round_interval
time.subtract('minutes', remainder).add('minutes', if remainder > round_interval / 2 then round_interval else 0)
Estou ocupado o suficiente com outras coisas agora, mas se alguém quiser pegar esse código e colocá-lo direto em um PR, fique à vontade.
Fechando em favor de # 1595
Não há necessidade de complicar, matemática simples:
const rounded = Math.round(moment().minute() / 15) * 15;
const roundedDown = Math.floor(moment().minute() / 15) * 15;
const roundedUp = Math.ceil(moment().minute() / 15) * 15;
moment().minute(roundedUp).second(0)
Saídas para o trimestre de 15 minutos mais próximo.
Não consegui fazer a solução de @janwerkhoven funcionar, então aqui está a minha:
function round15(minute) {
let intervals = [15, 30, 45, 59, 0];
let closest;
let min = 90;
for (let i = 0; i < intervals.length; i++) {
let iv = intervals[i];
let maybeMin = Math.abs(minute - iv);
if (maybeMin < min) {
min = maybeMin;
closest = iv;
}
}
if (closest === 59) {
closest = 0;
}
return closest;
}
let myMoment = moment();
myMoment.minutes(round15(myMoment.minutes()));
@ ground5hark
function nearestMinutes(interval, someMoment){
const roundedMinutes = Math.round(someMoment.clone().minute() / interval) * interval;
return someMoment.clone().minute(roundedMinutes).second(0);
}
function nearestPastMinutes(interval, someMoment){
const roundedMinutes = Math.floor(someMoment.minute() / interval) * interval;
return someMoment.clone().minute(roundedMinutes).second(0);
}
function nearestFutureMinutes(interval, someMoment){
const roundedMinutes = Math.ceil(someMoment.minute() / interval) * interval;
return someMoment.clone().minute(roundedMinutes).second(0);
}
const now = moment();
const nearest5min = nearestMinutes(5, now);
const nearest15min = nearestMinutes(15, now);
const nearest30min = nearestMinutes(30, now);
const nearestFuture5min = nearestFutureMinutes(5, now);
const nearestPast5min = nearestPastMinutes(5, now);
Testado na Code Pen
A parte crucial é fazer .clone()
. Sem ele, você estaria editando o moment()
que é uma armadilha comum ao usar o Moment.js.
Tente isso caras
time = moment("01:46", "HH:mm");
round_interval = 30;//15;
intervals = Math.floor(time.minutes() / round_interval);
minutesToRound = time.minutes() % round_interval;
minutesRounded = minutesToRound>round_interval/2 ? round_interval: 0;
minutes = intervals * round_interval + minutesRounded;
time.minutes(minutes);
alert(time.format("HH:mm"))
Atrasado para a festa, eu sei, mas ...
A função nearestMinutes
@janwerkhoven não está correta; isso implica que ele será arredondado para cima OU para baixo dependendo do minuto, então, arredondando para os 15 próximos, esperaríamos 12:34 -> 12:30
e 12:39 -> 12:45
const roundedMinutes = Math.round(someMoment.clone().minute() / interval) * interval;
// 12:34 is fine...
// => Math.round(34 / 15) * 15
// => 2 * 15
30
// ... but 12:39 is not - it should be 45
// => Math.round(39 / 15) * 15
// => 2 * 15
30
A solução da @Silviusconcept supera isso com minutesRounded
@kevlarr
Math.round(39/15)
retorna 3, não 2.
Math.round(39/15) * 15
retorna 45, não 30.
Haha, isso é o que eu ganho por ler muitos tópicos no final do dia quando não dormi. Eu estava fazendo Math.floor
Eu gosto de _zbarnett solution_ ! Fácil de usar
Pouca atualização para a função _ this.milliseconds (0); _
var newdate = turno.date.clone (). roundNext15Min (). add (antecipação, 'minutos');
moment.fn.roundNext15Min = function () {
intervalos var = Math.floor (this.minutes () / 15);
if (this.minutes ()% 15! = 0)
intervalos ++;
if (intervalos == 4) {
this.add ('horas', 1);
intervalos = 0;
}
this.minutes (intervalos * 15);
this.seconds (0);
_ this.milliseconds (0); _
devolva isso;
}
Minha versão de uma resposta
const startOf = (m, n, unit) => {
const units = [
'year',
'month',
'hour',
'minute',
'second',
'millisecond',
];
const pos = units.indexOf(unit);
if (pos === -1) {
throw new Error('Unsupported unit');
}
for (let i = pos + 1; i < units.length; i++) {
m.set(units[i], 0);
}
m.set(unit, Math.floor(m.get(unit) / n) * n);
return m;
};
const endOf = (m, n, unit) => {
const units = [
'year',
'month',
'hour',
'minute',
'second',
'millisecond',
];
const pos = units.indexOf(unit);
if (pos === -1) {
throw new Error('Unsupported unit');
}
for (let i = pos + 1; i < units.length; i++) {
m.set(units[i], units[i] === 'millisecond' ? 999 : 59);
}
m.set(unit, Math.floor(m.get(unit) / n) * n + n - 1);
return m;
};
Use assim:
startOf(moment(), 15, 'minute');
endOf(moment(), 15, 'minute')
// with moment-timezone
startOf(moment().tz("Europe/London"), 15, 'minute');
Estas funções irão mudar o objeto original, use clone()
quando necessário
outra solução seria:
let next15Minutes = moment().add(15, 'minutes');
next15Minutes.minutes(Math.floor(next15Minutes.minutes() / 15) * 15);
next15Minutes.format('HH:mm');
Comentários muito úteis
Não há necessidade de complicar, matemática simples:
Saídas para o trimestre de 15 minutos mais próximo.