Runde moment.js Objektzeit auf das nächste 30-Minuten-Intervall


72

Ich habe versucht, das Zeitobjekt von moment.j auf das nächste 30-Minuten-Intervall abzurunden. Aber sieht meine Logik uns falsch aus.

Ex:

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

Hier ist mein aktueller Code

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

Es gibt nur 4 Bedingungen, Sie können sie umschalten.
Junle Li

1
Sie finden den Rest, nicht den Unterschied. Sie müssen beides gemäß meiner Lösung tun.
Jtromans

Das funktioniert bei mir, es ist wirklich eine gute Lösung.
Sandeep.gosavi

Antworten:


120

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>

Millionen Möglichkeiten, dies zu tun. Du brauchst moment.js nicht wirklich. Wie auch immer, hier ist einer.


Ich denke, Sie machen einen Fehler, `` `rest = (moment (). Minute ()% 30) -30```
32teeths

5
Ich denke, es sollte code30 sein - (start.minute ()% 30)
artem_p

Personen, die dies finden, möchten möglicherweise einschließen .startOf('minute'), um Sekunden und Millisekunden des intrinsischen Datumsobjekts zurückzusetzen.
Adrian Föder

2
Dies scheint nicht das zu tun, wonach gefragt wurde. Selbst das Sample-Snippet rundet 09:42 nicht auf das nächste 30-Minuten-Intervall ab. es rundet es auf das nächste 30-Minuten-Intervall. Das Ergebnis sollte 09:30 und nicht 10:00 sein.
Thor84no

1
Das OP hat in seiner ursprünglichen Frage eine Reihe von Beispielen angegeben, die diese Beispiele ansprechen. Der Titel des Beitrags ist nicht eindeutig.
Jtromans

59

Basierend auf den Antworten und Kommentaren von @Volune und @Cabloo kann eine aktualisierte Version folgendermaßen aussehen:

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

Welches kann dann verwendet werden wie:

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

1
Geniale Möglichkeit, erweiterte Funktionen zu ermöglichen!
Ancinek

2
Wahrscheinlich ist es sinnvoll, die ursprüngliche Zeitzone wiederherzustellen, da sonst diese Informationen verloren gehen. Fe durch Hinzufügen von .tz (date.tz ()) am Ende.
XZen

35

Eine generische Lösung:

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

Sie können ROUNDINGvon 30 Minuten auf das ändern , was Sie möchten, und Math.ceilnach Math.roundoder, Math.floorwenn Sie eine andere Möglichkeit zum Runden des Werts wünschen.


8
Ich mag diesen. Sie könnten die ROUNDING-Variable in eine moment.duration (...) konvertieren, dh function date_round(date, duration) { return moment(Math.floor((+date)/(+duration)) * (+duration)); } wie folgt verwendetdate_round(moment(), moment.duration(30, 'minutes'))
Zane

4

Sie können dies mit einer einfachen if-else-Klausel tun:

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

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

1
Obwohl das Wort roundim Fragentitel verwendet wurde, möchte OP etwas Ähnliches haben ceil. Ihre Lösung bietet keine, sondern eine Wirkung von floor.
Fr0zenFyr

3

Sie könnten es mit zwei Wenns tun:

// 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

Obwohl die Frage beantwortet wurde, möchte ich auch meine Lösung teilen.

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

EDIT: Danke an Ishmael Sibisi für den Hinweis auf einen Fehler in meinem Code! :) :)


0

Der folgende Code rundet die aktuelle Zeit auf die nächsten 30 Minuten auf und kümmert sich auch fehlerfrei um alle nachfolgenden Sekunden

    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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.