round up/ round down a momentjs moment to nearest

2019-02-02 19:34发布

问题:

How do you round up/ round down a momentjs moment to nearest minute?

I have checked the docs, but there doesn't appear to be a method for this.

Note that I do not want a string rounded to the nearest minute, I want a moment returned (or modified in place, either is fine). I prefer not to have to convert to a string, and the convert back too.

Thanks.


As requested, here is some code:

var now = new moment(new Date());

if (now.seconds() > 0) {
    now.add('minutes', -1);
}

now.seconds(0);

as you can see, I have managed to manually round down the moment here, but it seems rather hacky. Just after a more elegant way of accomplishing this.

回答1:

To round up, you need to add a minute and then round it down. To round down, just use the startOf method.

Note the use of a ternary operator to check if the time should be rounded (for instance, 13:00:00 on the dot doesn't need to be rounded).

Round up/down to the nearest minute

var m = moment('2017-02-17 12:01:01');
var roundDown = m.startOf('minute');
console.log(roundDown.toString()); // outputs Tue Feb 17 2017 12:01:00 GMT+0000

var m = moment('2017-02-17 12:01:01');
var roundUp = m.second() || m.millisecond() ? m.add(1, 'minute').startOf('minute') : m.startOf('minute');
console.log(roundUp.toString());  // outputs Tue Feb 17 2017 12:02:00 GMT+0000

Round up/down to the nearest hour

var m = moment('2017-02-17 12:59:59');
var roundDown = m.startOf('hour');
console.log(roundDown.toString()); // outputs Tue Feb 17 2017 12:00:00 GMT+0000

var m = moment('2017-02-17 12:59:59');
var roundUp = m.minute() || m.second() || m.millisecond() ? m.add(1, 'hour').startOf('hour') : m.startOf('hour');
console.log(roundUp.toString());  // outputs Tue Feb 17 2017 13:00:00 GMT+0000


回答2:

Partial answer:

To round down to nearest moment minute:

var m = moment();
m.startOf('minute');

However, the equivalent for rounding up, endOf, doesn't quite give the expected result.



回答3:

The roundTo feature could make it into a future release.

Examples:

moment().roundTo('minute', 15); // output: 12:45
moment().roundTo('minute', 15, 'down'); // output: 12:30


回答4:

Rounding to the nearest hour can be achieved by adding half an hour and then run .startOf('hour'). This is the same for any time measurement.

var now = moment();
// -> Wed Sep 30 2015 11:01:00
now.add(30, 'minutes').startOf('hour'); // -> Wed Sep 30 2015 11:31:00
// -> Wed Sep 30 2015 11:00:00

var now = moment();
// -> Wed Sep 30 2015 11:31:00
now.add(30, 'minutes').startOf('hour'); // -> Wed Sep 30 2015 12:01:00
// -> Wed Sep 30 2015 12:00:00


回答5:

Rounding Down

Easy. As stated by many others, just use Moment.startOf:

var roundDown = moment('2015-02-17 12:59:59').startOf('hour');
roundDown.format('HH:mm:SS'); // 12:00:00

Importantly, this also works as expected:

var roundDown = moment('2015-02-17 12:00:00').startOf('hour');
roundDown.format('HH:mm:SS'); // 12:00:00

Rounding Up

Slightly trickier, if we want to round up with a proper ceiling function: for example, when rounding up by hour, we want 12:00:00 to round up to 12:00:00.

This does not work

var roundUp = moment('2015-02-17 12:00:00').add(1, 'hour').startOf('hour');
roundUp.format('HH:mm:SS'); // ERROR: 13:00:00

Solution

function roundUp(momentObj, roundBy){
  if (momentObj.millisecond() != 1){
    momentObj.subtract(1,'millisecond');
  }
  return momentObj.add(1, roundBy).startOf(roundBy);
}


var caseA = moment('2015-02-17 12:00:00');
roundUp(caseA, 'minute').format('HH:mm:SS'); // 12:00:00

var caseB = moment('2015-02-17 12:00:00.001');
roundUp(caseB, 'minute').format('HH:mm:SS'); // 12:01:00

var caseC = moment('2015-02-17 12:00:59');
roundUp(caseC, 'minute').format('HH:mm:SS'); // 12:01:00


回答6:

A more precise answer:

t.add(30, 'seconds').startOf('minute')

Case1: Rounding down if seconds < 30

t = moment(); //12:00:05
t.add(30, 'seconds').startOf('minute') //12:00:00

Case2: Rounding up if seconds >= 30

t = moment(); //12:00:33
t.add(30, 'seconds').startOf('minute') //12:01:00


回答7:

This solution worked for me;

function round_up_to_nearest_hour(date = new Date()) {
   return moment(date).add(59, 'minutes').startOf('hour').toDate();
}


回答8:

Just another possibility:

var now = moment();
// -> Wed Sep 30 2015 11:57:20 GMT+0200 (CEST)
now.add(1, 'm').startOf('minute');
// -> Wed Sep 30 2015 11:58:00 GMT+0200 (CEST)


回答9:

Copy this file into your project:

// copied from here https://github.com/WebDevTmas/moment-round/blob/1d20ce5d338529c76da8439fe594cc6984505810/src/moment-round.js and modified
import moment from 'moment';

moment.fn.round = function(precision, key, direction='round') {
    let keys = ['Hours', 'Minutes', 'Seconds', 'Milliseconds'];
    let maxValues = [24, 60, 60, 1000];

    // Capitalize first letter
    key = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();

    // make sure key is plural
    if(key.indexOf('s', key.length - 1) === -1) {
        key += 's';
    }
    let value = 0;
    let rounded = false;
    let subRatio = 1;
    let maxValue;
    for(let i=0; i<keys.length; ++i) {
        let k = keys[i];
        if(k === key) {
            value = this._d['get' + key]();
            maxValue = maxValues[i];
            rounded = true;
        } else if(rounded) {
            subRatio *= maxValues[i];
            value += this._d['get' + k]() / subRatio;
            this._d['set' + k](0);
        }
    }

    value = Math[direction](value / precision) * precision;
    value = Math.min(value, maxValue);
    this._d['set' + key](value);

    return this;
};

moment.fn.ceil = function(precision, key) {
    return this.round(precision, key, 'ceil');
};

moment.fn.floor = function(precision, key) {
    return this.round(precision, key, 'floor');
};

And import it:

import Moment from 'moment';
import '../../moment-round';

Assuming you're using CommonJS/Babel/Webpack.