Moment: Округление до ближайшего 15-минутного интервала.

Созданный на 27 июл. 2013  ·  18Комментарии  ·  Источник: moment/moment

Мне было интересно, есть ли у меня способ округлить до ближайшего 15-минутного интервала вверх или вниз. Я думаю, что это было бы отличной функцией, поскольку некоторые библиотеки, такие как datejs, имеют такую ​​функциональность из того, что я видел при поиске. Мой сценарий состоит в том, что у меня есть точки данных, которые сегментированы на 15-минутные сегменты. Инструмент выбора возвращает любой блок времени, и мне нужно округлить до ближайших 15 минут и округлить до конечного времени.

Делать это таким образом (http://stackoverflow.com/questions/4968250/how-to-round-time-to-the-nearest-quarter-hour-in-javascript) кажется болью .. когда это было бы полезно иметь в самой библиотеке.

Самый полезный комментарий

Не нужно усложнять, простая математика:

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)

Выводит до ближайшего 15-минутного квартала.

Все 18 Комментарий

moment.fn.roundMinutes = function () { return ~(this.minutes() / 15) * 15; }

Я создал это для себя и решил, что это может помочь другим. Имейте в виду, что округляется до ближайших СЛЕДУЮЩИХ 15 мин.

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

РЕДАКТИРОВАТЬ: удалили this.incrementHours () в пользу this.add ('hours', 1);

Не могли бы вы добавить эти функции к моменту ... Было бы здорово иметь возможность округлять до ближайшего, следующего и предыдущего временных интервалов ... Для этого есть миллионы результатов Google и сотни голосов за переполнение стека ..

Теперь, когда я смотрю на это снова, я понятия не имею, как работал incrementHours.
Я отредактировал свой пост к проблеме с исправленным кодом. Наслаждаться!

В пн, 10 марта 2014 г., в 14:29, Блейк Немийски
[email protected] написал :

Какова была ваша функция для incrementHours? Я предполагаю, что и дни
тоже.

Ответьте на это письмо напрямую или просмотрите его на Gi tHubhttps: //github.com/moment/moment/issues/959#issuecomment -37223821
.

спасибо за этот метод @zbarnett . Именно то, что мне нужно для моего проекта

Что ж, мы можем использовать интерфейс startOf как этот startOf(15, 'm') . Он может работать для всех юнитов. Жду пиаров :)

Вот довольно простая формула (в синтаксисе Coffeescript, поскольку именно в этом контексте я столкнулся с этой проблемой):

round_interval = 15
remainder = time.minute() % round_interval
time.subtract('minutes', remainder).add('minutes', if remainder > round_interval / 2 then round_interval else 0)

Я сейчас достаточно занят другими вещами, но если кто-то хочет взять этот код и поместить его прямо в PR, не стесняйтесь.

Закрытие в пользу №1595

Не нужно усложнять, простая математика:

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)

Выводит до ближайшего 15-минутного квартала.

Мне не удалось заставить решение @janwerkhoven работать, поэтому вот мое:

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

Протестировано на Code Pen

Решающим моментом является выполнение .clone() . Без него вы бы редактировали исходный moment() что часто бывает при использовании Moment.js.

Попробуйте, ребята

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

Поздно на вечеринку, я знаю, но ...

Функция nearestMinutes @janwerkhoven неверна ; это означает, что он будет округляться в большую или меньшую сторону в зависимости от минуты, поэтому, округляя до ближайших 15, мы ожидаем 12:34 -> 12:30 и 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

Решение @Silviusconcept преодолевает это с помощью minutesRounded

@kevlarr
Math.round(39/15) возвращает 3, а не 2.
Math.round(39/15) * 15 возвращает 45, а не 30.

Ха-ха, вот что я получаю, прочитав слишком много обсуждений в конце дня, когда не спал ... Я делал Math.floor

Мне нравится _zbarnett solution_ ! Легко использовать
Небольшое обновление функции _ this.milliseconds (0); _

var newdate = turno.date.clone (). roundNext15Min (). add (ожидание, 'минуты');

moment.fn.roundNext15Min = function () {
интервалы var = Math.floor (this.minutes () / 15);
если (this.minutes ()% 15! = 0)
интервалы ++;
если (интервалы == 4) {
this.add ('часы', 1);
интервалы = 0;
}
this.minutes (интервалы * 15);
this.seconds (0);
_ this.milliseconds (0); _
вернуть это;
}

Моя версия ответа

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

Используйте так:

startOf(moment(), 15, 'minute');
endOf(moment(), 15, 'minute')
// with moment-timezone
startOf(moment().tz("Europe/London"), 15, 'minute');

Эти функции изменят исходный объект, при необходимости используйте clone()

другое решение:
let next15Minutes = moment().add(15, 'minutes'); next15Minutes.minutes(Math.floor(next15Minutes.minutes() / 15) * 15); next15Minutes.format('HH:mm');

Была ли эта страница полезной?
0 / 5 - 0 рейтинги