Moment: Arredondando para o intervalo de 15 minutos mais próximo.

Criado em 27 jul. 2013  ·  18Comentários  ·  Fonte: moment/moment

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.

todo

Comentários muito úteis

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.

Todos 18 comentários

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

Esta página foi útil?
0 / 5 - 0 avaliações