将moment.js对象时间舍入到最近的30分钟间隔


72

我试图将moment.js时间对象四舍五入到下一个最近的30分钟间隔。但是看起来我的逻辑我们错了。

例如:

10:13am -> 10:30am
11:45am -> 12:00pm

这是我当前的代码

start = moment();
minuteReminder = start.minute() % 30;
start.add(minuteReminder, 'minutes');
start.format("D YYYY, h:mm:ss a");

只有4种情况,您可以切换大小写。
Junle Li

1
您找到的是其余部分,而不是区别。根据我的解决方案,您需要同时执行这两项操作。
jtromans

对我有效,这是一个很好的解决方案。
sandeep.gosavi '16

Answers:


121

const start = moment('2018-12-08 09:42');
const remainder = 30 - (start.minute() % 30);
 
const dateTime = moment(start).add(remainder, "minutes").format("DD.MM.YYYY, h:mm:ss a");

console.log(dateTime);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>

数百万种方法。您实际上并不需要moment.js。无论如何,这是一个。


我认为您犯了一个错误,```remainder =(moment()。minute()%30)-30`
32teeths

5
我认为应该是code30-(start.minute()%30)
artem_p

找到此对象的人可能想包括在内.startOf('minute'),以重置固有日期对象的秒和毫秒。
AdrianFöder20年

2
这似乎不符合要求。即使样本片段也无法将09:42舍入到最近的30分钟间隔;将其舍入到下一个30分钟间隔。结果应为09:30,而不是10:00。
Thor84no

1
OP在其原始问题中提供了许多示例,因此可以解决这些示例。帖子标题不明确。
jtromans

59

基于@Volune和@Cabloo的答案和评论,更新后的版本如下所示:

function round(date, duration, method) {
    return moment(Math[method]((+date) / (+duration)) * (+duration)); 
}

然后可以这样使用:

var date = moment();
var roundedDate = round(date, moment.duration(15, "minutes"), "ceil");

1
扩展功能的绝佳方式!
Ancinek

2
恢复原始时区可能很有意义,否则此信息会丢失。通过在末尾添加.tz(date.tz())来添加Fe。
XZen

35

通用解决方案:

var ROUNDING = 30 * 60 * 1000; /*ms*/
start = moment();
start = moment(Math.ceil((+start) / ROUNDING) * ROUNDING);
start.format("D YYYY, h:mm:ss a");

你可以改变ROUNDING从30分钟到任何你想要的,而改变Math.ceilMath.round或者Math.floor如果你想另一种方式圆值。


8
我喜欢这一个。您可以在ROUNDING变量转换为moment.duration(...),即function date_round(date, duration) { return moment(Math.floor((+date)/(+duration)) * (+duration)); } 使用像这样date_round(moment(), moment.duration(30, 'minutes'))
赞恩

4

您可以通过一个简单的if-else子句来做到这一点:

            if(moment().minute()> 30){
                var myTime = moment().minute(30).second(0);

            }else{
                var myTime = moment().minute(0).second(0);
            }

1
尽管round标题标题中使用了该词,但OP希望具有类似于的内容ceil。您的解决方案既不提供效果,又提供的效果floor
Fr0zenFyr

3

您可以使用两个if来做到这一点:

// Current date
let now = moment();

// Getting hour and minute
let hour   = now.hour();
let minute = now.minute();

// Rounding minute on 30 mins interval
if(minute <= 30) now.set({minute: 30});
if(minute >  30) now.set({hour: hour + 1, minute: 0});

1

即使问题已得到解答,我也想分享我的解决方案。

var moment = require('moment');

const roundToNearestXXMinutes = (start, roundTo) => {
    let remainder = roundTo - (start.minute()+ start.second()/60) % roundTo;

    remainder = (remainder >  roundTo/2) ? remainder = -roundTo + remainder : remainder;
    const changedDate = moment(start).add(remainder, "minutes" ).seconds(0).format("DD.MM.YYYY HH:mm:ss");    
}

roundToNearestXXMinutes(moment(), 15);

编辑:感谢Ishmael Sibisi指出我的代码中的缺陷!:)


0

下面的代码将当前时间四舍五入为最近的30分钟,并且完美地处理了所有后续秒数

    var moment = require('moment')
    var main = Date.now() //2020-03-13T23:17:34+01:00
    var mainFormat = moment(main)
    var secs = mainFormat.second()
    var justMinutes = mainFormat.subtract(secs, 'seconds')
    var remainder = 30 - (justMinutes.minute() % 30);
    var dateTime = moment(justMinutes).add(remainder, 'minutes')
    var final = dateTime.format()
    console.log(final) 
    //2020-03-13T23:20:00+01:00
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.