Ich habe ein startDate und ein endDate in einer SQLite-Datenbank gespeichert und muss die Differenz in Minuten und Sekunden zwischen den beiden Datenzeiten mit Javascript berechnen.

Beispielsweise:

startDate = 2012-10-07 11:01:13
endDate = 2012-10-07 12:42:13

Ich habe zwar viele ähnliche Fragen zu SO gut gelesen, konnte aber nur Dinge finden, die damit zusammenhängen, dies als Teil einer Auswahl zu berechnen.

2
James J 7 Okt. 2012 im 15:44

4 Antworten

Beste Antwort

Alle Antworten sind im Allgemeinen korrekt in Bezug auf die Konvertierung der Daten in Millisekunden in der Epochenzeit, die Subtraktion dieser Daten und die Rückkonvertierung des Ergebnisses von Millisekunden in die erforderlichen Einheiten (obwohl die an anderer Stelle angebotenen spezifischen Implementierungen derzeit nicht genau das liefern, wonach Sie gefragt haben - - dh nur die Anzahl der Minuten und Sekunden zwischen Ihren beiden Datenzeiten).

Bitte beachten Sie jedoch auch ...

neues Datum ('2012-10-07 12:42:13')

... dass dies keine zuverlässige Methode ist, um das Datum aus Ihren SQLite-Datumszeichenfolgen zu erstellen.

Wenn Sie eine Zeichenfolge in den Konstruktor eines Date-Objekts eingeben, rufen Sie effektiv Date.parse() auf. Das verhält sich in verschiedenen Browsern unterschiedlich.

Überprüfen Sie dies heraus:

> new Date('1-1-2012');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)

> new Date('01-01-2012');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)

> new Date('2012-1-1');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)

Sieht ziemlich gut aus, oder? Aber das ist auf Chrome.

Überprüfen Sie nun, was in einer aktuellen Version von Firefox mit genau denselben Aufrufen passiert:

> new Date('1-1-2012');
Date {Invalid Date}

> new Date('01-01-2012');
Date {Invalid Date}

> new Date('2012-1-1');
Date {Invalid Date}

> new Date('2012-01-01');
Date {Sat Dec 31 2011 16:00:00 GMT-0800 (PST)}

Sehen Sie sich dieses Verhalten in beiden Browsern an:

> new Date('2012-01-01');
Sat Dec 31 2011 16:00:00 GMT-0800 (PST)

Das einfache Voranstellen von Nullen vor den Monats- und Datumsangaben führt zu einer Zeitverzerrung! Sie müssen die Zeit und eine Zeitzone (für mich PST) einstellen, damit dies verschwindet:

> new Date('2012-01-01T00:00:00-08:00')
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)

Grundsätzlich ist das Parsen von Datumszeichenfolgen ein Problem. Sie möchten keine Spezifikationen wie dies, dies und this.

Also, hier ist eine bessere Alternative - übergeben Sie die Teile Ihrer datetime als separate Argumente an den Konstruktor des Date-Objekts. Dadurch wird das Datum zuverlässig für Sie erstellt, sodass Ihre nachfolgenden Vergleiche gültig sind.

neues Datum (Jahr, Monat, Tag [, Stunde, Minute, Sekunde, Millisekunde])

So könnte diese Initialisierung für Ihren Fall aussehen:

// Extract month, day, year from SQLite format, 'trimming' whitespace.
var sqlLiteSampleStr = "2012-10-07 11:01:13";
var re = /^\s*(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})\s*$/;
var match = re.exec(sqlLiteSampleStr);
if (match) {
  var year = parseInt(match[1]);
  var month = parseInt(match[2]) - 1; // Zero-indexed months.
  var date = parseInt(match[3]);
  var hour = parseInt(match[4]);
  var minute = parseInt(match[5]);
  var second = parseInt(match[6]);
  var date = new Date(year, month, date, hour, minute, second);
}

Hinweis: Achten Sie auf Zeitzonenüberlegungen. Sie scheinen keine Zeitzonendaten in diesem SQLite-Format-Snippet zu haben.

Aktualisieren

@ James-J hat klargestellt, dass er speziell nach Minuten und Sekunden sucht.

Hier ist ein Ausschnitt, um nur Minuten und Sekunden zu extrahieren:

var msPerMin = 1000 * 60;
var min = Math.floor(timeInMs / msPerMin);
var timeInMs = timeInMs - (min * msPerMin);
var sec = Math.floor(timeInMs / 1000 );
1
manzoid 7 Okt. 2012 im 13:21

Konvertieren Sie die Zeichenfolgen in ein JS Date -Objekt, subtrahieren Sie die Daten und verwenden Sie eine Arithmetik, um Stunden / Sekunden aus dem Ergebnis zu berechnen. Etwas wie:

function convertMS(ms) {
  var d, h, m, s, ts, tm, th;
  s = ts = Math.floor(ms / 1000);
  m = tm = Math.floor(s / 60);
  s = s % 60;
  h = th = Math.floor(m / 60);
  m = m % 60;
  d = Math.floor(h / 24);
  h = h % 24;
  return { d: d, h: h, m: m, s: s, tm: tm, th: th, ts: ts};
};
var start = new Date('2012-10-07 11:01:13'.split('-').join('/'))
   ,end   = new Date('2012-10-07 12:42:13'.split('-').join('/'))
   ,dif   = convertMS(end - start);
console.log(dif.h+':'+dif.m);​​​​​​ //=> ​1:41
console.log('total minutes dif: '+dif.tm);​​​​​​ //=> total ​minutes dif: 101
console.log('total seconds dif: '+dif.ts);​​​​​​ //=> ​total seconds dif: 6060

[ Bearbeiten basierend auf Kommentar]
'Manuelles' Parsen einer Datumszeichenfolge im angegebenen Format:

Date.tryParse = function(ds){
  var  arr =  ds.match(/\d+/g)
      ,err = 'Expected at least yyyy'
      ,dat = arr.length && String(arr[0]).length === 4
              ? doParse.apply(null,arr) : err;
  return dat;

  function doParse(y,m,d,h,mi,s,ms){
   var dat = new Date(+y,(+m-1)||0,+d||1,+h||0,+mi||0,+s||0,+ms||0);
   return isNaN(dat) ? new Date : dat;
  }
}
var start = Date.tryParse('2012-10-07 11:01:13'); //=> Sun Oct 07 2012 11:01:13
var test  = Date.tryParse('2009');                //=> Sun Jan 01 2009 00:00:00
2
KooiInc 8 Okt. 2012 im 05:46

JavaScript macht das Subtrahieren von Daten ziemlich einfach. So funktioniert das:

// Create Date objects from the strings
startDate = new Date('2012-10-07 11:01:13');
endDate = new Date('2012-10-07 12:42:13');

// Subtract Date objects to return milliseconds between them
millisecondsBetween = (endDate - startDate);

// Convert to whatever you like
alert(millisecondsBetween/1000/60 + ' minutes');
0
jncraton 7 Okt. 2012 im 12:00

Andere Antworten sind korrekt, aber Browser analysieren Datumszeichenfolgen nicht konsistent (siehe unten), daher sollten Sie die Zeichenfolgen manuell analysieren. Das Format im OP stimmt auch nicht mit dem Format in ES5 überein und wird von einigen Browsern nicht korrekt analysiert. Eine einfache Funktion zum Konvertieren des OP-Formats in ein Datum, das in allen Browsern funktioniert, ist:

function stringToDate(s) { 
    s = s.split(/[-\/\. :]/);
    return new Date(s[0], --s[1], s[2], s[3], s[4], s[5], 0)
}

Es gibt einige Formate, die von allen Browsern analysiert werden. Sie sind jedoch nicht standardkonform und hängen bei Verwendung davon ab, dass alle Implementierungen weiterhin nicht spezifizierte Formate unterstützen.

Bearbeiten

Um fehlerhafte Eingaben (zusätzliches Leerzeichen, verschiedene Trennzeichen, zusätzliche Zeichen) zu tolerieren, kann match anstelle von split verwendet werden:

function stringToDate(s) { 
    s = s.match(/\d+/g);
    return new Date(s[0], --s[1], s[2], s[3], s[4], s[5], 0)
}

Da die Werte jedoch aus einer Datenbank stammen und ein Format angegeben wurde, sollten die Datumszeichenfolgen zum Format passen. Fehlerhafte Daten sollten nicht an erster Stelle gespeichert werden.

Der Vollständigkeit halber ist hier eine Funktion, um zu tun, was Sie wollen:

/*  Return difference between two dates as minutes and seconds mm:ss.
 *  Input format is yyyy-mm-dd hh:mm:ss
 *  If strings don't converted to dates (incorrect format or invalid values),
 *  return undefined.
 */
function diffInMins(s0, s1) {
  var diff;

  // Convert strings to date ojbects
  var d0 = stringToDate(s0);
  var d1 = stringToDate(s1);

  // Helper function to padd with leading zero
  function z(n) {
    return (n<10? '0' : '') + n;
  }

  // Check conversions
  if (d0 && d1 && typeof d0 == 'object' && typeof d1 == 'object') {

    // Return difference formatted as mm:ss
    if (d0 && d1) {
      diff = d1 - d0;
      return z(diff/60000 | 0) + ':' + z(Math.round(diff%60000/1000));
    }
  }
}
1
RobG 8 Okt. 2012 im 00:11