Datums- und Zeitdifferenzen berechnen - Function DateDif

jspit

Lounge-Member
Wieviel Tage sind es noch bis zum Ereignis (Event, Sylvester, Geburtstag), das Alter berechnen oder die verangenen Stunden ab einen bestimmten Zeitpunkt, all diese Fragestellungen laufen auf die Berechnung von Datums- und Zeitdifferenzen hinaus. Unzählige Scripte sind hierzu im Netz vorhanden, doch leider sind auch viele fehlerhaft oder arbeiten nur für ein spezielles Beispiel richtig.
Zwei häufig anzutreffende Fehler seien hier nur genannt:
- Die Existenz einer Sommerzeit wird schlichtweg ignoriert. Der Tag hat ja immer 24 Stunden - falsch. Am Tag der Umstellung auf die Sommerzeit eben nur 23 Stunden, im Herbst gibt es einen Tag mit 25 Stunden. Dies kann zur Folge haben, dass die Berechnung einer Anzahl Tage über einen Umstellungszeitpunkt hinweg falsch wird.
- Bei der Berechnung des Alters werden einfach die Jahreszahlen subtrahiert und nicht berücksichtigt, ob der Kanidat zum aktuellen Zeitpunkt im Jahr schon Geburtstag hatte (und damit ein Jahr älter ist) oder nicht.
Es wird hier eine Funktion zur Diskussion gestellt, die wenig Code umfasst, schnell und transparent ist und für viele Problemstellungen obiger Art nutzbar ist. Alternative Datentypen string und date-object für die Parameter ermöglichen eine flexible Handhabung. Als Zeitintervall für den Rückgabewert werden akzeptiert:
- Millisekunden ('ms')
- Sekunden ('s')
- Minuten ('m')
- Stunden ('h')
- Tage ('d')
- Wochen ('w')
- Jahre ('y')
Als string wird ein Datum neben der normgerechten Form "Feb 1,2010 00:00:00" auch im Format "2010/2/1 00:00:00" von allen modernen Browsern richtig interpretiert, nicht jedoch deutsche Formate wie "1.2.2010".
PHP:
//Beispiel: Anzahl der Tage Februar 2000
var Anzahl = DateDiff("2000/2/1","2000/3/1","d");
Ein leerer String ("") ist gleichbedeutend mit dem aktuellen Datum/Zeit. Die Funktion DateDiff liefert mit der Ausnahme Jahre ("y") Dezimalzahlen. Werden ganze Zahlen gewünscht, ist Math.ceil() bzw. Math.floor() zu benutzten.
PHP:
//Beispiel: Anzahl der Tage bis zum neuen Jahr 2011
var Anzahl = Math.ceil(DateDiff("","2011/1/1","d"));
//Anzahl Stunden bis zum neuen Jahr
var newyear=(new Date()).getFullYear() + 1; //immer das neue Jahr
Anzahl = Math.ceil(DateDiff("",newyear + "/1/1","h"));
Eine Zeit kann auch als Datumsobjekt übergeben werden, wie im Beispiel Zeitmessung gezeigt wird. Die Genauigkeit einer Zeitmessung im ms-Bereich wird durch die Auflösung des internen Timers begrenzt und ist vom Browser und System abhängig. Die von der DateDiff-Funktion benötigte Zeit ist dagegen vernachlässigbar.
PHP:
//Beispiel: Zeitmessung für ein Script
var Startzeit= new Date();
//Hier folgt der Script
//	:
//
var zeit=DateDiff(Startzeit,"","ms");
Eine Differenz in Jahren wird immer als ganze Zahl geliefert, da hier eine Dezimalzahl wenig Sinn macht. Die Berechnung unterliegt im script einer Ausnahmebehandlung und wurde integriert, da dies oft benötigt wird.
PHP:
//Beispiel: Jahre der Zugehörigkeit zum Forum seit Registrierung 17-03-2008 
var Anzahl = DateDiff("2008/3/17","","y");

Nun zum Schluss darf der Code der function DateDiff nicht fehlen:
PHP:
<script type="text/javascript">
function DateDiff(dfrom,dto,selector){
//dfrom: Startdatum als String, "" für das aktuelle Datum/Zeit oder Date-Object
//dto:   Enddatum als String, "" für das aktuelle Datum/Zeit  oder Date-Object
//selctor: 'ms' Millisekunden, 's' Sekunden, 'm' Minuten, 'h' Stunden,
// 'd' tage, 'w' wochen, 'y' ganze Jahre
var r,dfy,dy;
var osl = {ms:1,s:1000,m:60000,h:3600000,d:86400000,w:604800000,y:-1};
var df = typeof(dfrom)=="object" ? dfrom : dfrom=="" ? new Date() : new Date(dfrom);
var dt = typeof(dto)=="object" ? dto : dto=="" ? new Date() : new Date(dto);
var sl = osl[selector] || 1;
var sz= sl >= osl['d'] ? (df.getTimezoneOffset()-dt.getTimezoneOffset())*60000 : 0;
if(sl > 0) return (dt.getTime() - df.getTime() +sz)/sl;
else { dfy = df.getFullYear();
       dy = dt.getFullYear() - dfy;
       dt.setFullYear(dfy);
       return (dt.getTime() < df.getTime()) ? dy -1 : dy; }
}
</script>

Getestet mit FF3.5, IE8, Chrome 3.

jspit
 
- Die Existenz einer Sommerzeit wird schlichtweg ignoriert. Der Tag hat ja immer 24 Stunden - falsch. Am Tag der Umstellung auf die Sommerzeit eben nur 23 Stunden, im Herbst gibt es einen Tag mit 25 Stunden. Dies kann zur Folge haben, dass die Berechnung einer Anzahl Tage über einen Umstellungszeitpunkt hinweg falsch wird.

Ich krieg wenn ich normal die Differenz berechne den gleichen Wert wie mit deiner Funktion: (die nächste Uhrumstellung ist am 28.3.2010)
PHP:
var d1 = new Date("2010/3/27");
var d2 = new Date("2010/3/29");
var MS_PER_HOUR = 60 * 60 * 1000;
var MS_PER_DAY = 24 * MS_PER_HOUR;
var Anzahl = DateDiff(d1, d2,"h");  
alert(
'DateDiff='+ Anzahl
+ '\nDiff: '
+ (d2 - d1) / MS_PER_HOUR
);
Also ich gehe davon aus, dass JS die Zeitzonen berücksichtigt.
 
Also ich gehe davon aus, dass JS die Zeitzonen berücksichtigt.
Code:
var d1 = new Date("2010/3/27");
var d2 = new Date("2010/3/29");
alert(d1 + " - " + d2);
Sat Mar 27 00:00:00 UTC+0100 2010 - Mon Mar 29 00:00:00 UTC+0200 2010

EDIT: besser vielleicht

Code:
var d1 = new Date("2010/3/28 01:00:00");
var d2 = new Date("2010/3/28 02:00:00");
var d3 = new Date("2010/3/28 03:00:00");
alert(d1 + " - " + d2 + " - " + d3);

Sun Mar 28 01:00:00 UTC+0100 2010 - Sun Mar 28 01:00:00 UTC+0100 2010 - Sun Mar 28 03:00:00 UTC+0200 2010
 
Zuletzt bearbeitet:
Also ich gehe davon aus, dass JS die Zeitzonen berücksichtigt.

Richtig. Da JS dies tut, kommt das Problem erst bei der Berechnung der Differenz von Tagen (Ich bediene mich mal deines Beispiels):
PHP:
var d1 = new Date("2010/3/27");
var d2 = new Date("2010/3/29");
var MS_PER_HOUR = 60 * 60 * 1000;
var MS_PER_DAY = 24 * MS_PER_HOUR;
alert((d2 - d1) / MS_PER_DAY);

Als Differenz kommt hier nicht 2 Tage, sondern 1.95...
Genau hier macht DateDiff den Fehler nicht.
 
Als Differenz kommt hier nicht 2 Tage, sondern 1.95...
Genau hier macht DateDiff den Fehler nicht.
wobei dann schon wieder fraglich ist, was richtig ist. ehrlich, ich kann es dir nichtmal sagen.
du willst die differenz bist zum neuen jahr, sagen wir mal ab dem 29.03.10.
was ist da richtig? mathematisch sicher js.
 
Vom Tag x , 0 Uhr bis zum Tag y, 0 Uhr sind es nunmal immer ganze Tage, alles andere versteht kein Mensch. Die Differenz vom 27.3.2010 zum 29.3.2010 sind 2 Tage, aber nur 47 Stunden (und nicht 2*24h).
Bei irgendeiner Uhrzeit kann man streiten, ob es z.B. am Sylvesterabend ein Tag bis Neujahr oder kein Tag ist. Hier überlasse ich es dem Nutzer, wie er runden möchte.

Edit: Wird mit Zeiten gearbeitet, z.B. 27.3.2010 bis 29.3.2010 01:00:00 liefert die Funktion 2.0416666666 Tage. Aus dem Nachkommateil kann man genau die Zeit ermitteln (1h= 0,0416666666*24).
 
Zuletzt bearbeitet:
27.3.2010 zum 29.3.2010 sind 2 Tage, aber nur 47 Stunden (und nicht 2*24h).
naja, aber 47 h sind nun mal nicht 2 tage (als differenz auf jeden fall)

Edit: Wird mit Zeiten gearbeitet, z.B. 27.3.2010 bis 29.3.2010 01:00:00 liefert die Funktion 2.0416666666 Tage. Aus dem Nachkommateil kann man genau die Zeit ermitteln (1h= 0,0416666666*24).
die stimmt aber nicht, weil 2 tage * 24 h + 1 h = 25 h sind. zw. dem 27.3.2010 und dem 29.3.2010 01:00:00 liegen aber nur 24 h
rechnen kannst du mit deinem ergebnis nicht mehr.
 
Mathematisch ist es doch richtig.
Eben nicht ganz. Sofern immer mit MS_PER_DAY = 24 * MS_PER_HOUR gerechnet wird, ist das genau für den 28.3.2010 nicht richtig, denn dieser Tag hat nur 23h , und man muss korekterweise für den 28.3.2010 mit MS_PER_DAY_Ex = 23 * MS_PER_HOUR rechnen. Das mach ich in der Funktion auch nicht, arbeite statt dessen mit einer Korrektur von 1h je nach dem wo Start- und Enddatum sich befinden. Noch krasser ist wenn man den Monat konstant mit 30 Tagen ansetzt (auf diese Idee würde hier keiner kommen, hab ich aber schon gesehen) und dann rechnet, oder das Jahr konstant mit 365 Tagen ansetzt und die Schaltjahre nicht berücksichtigt.

D.h. dir geht es um die Rundungsfehler bei der Berechnung der vollen Tage zwischen zwei Zonen?
Genau bei einer sinnvollen Rundung ist mir das Problem auf die Füsse gefallen, wenn die Zeiten einmal in der Sommerzeit liegen und das Gegenstück ausserhalb. Ohne Korrektur tritt dann so etwas auf: um 0h30 wird eine Differenz von x Tagen ausgewiesen, 1h30 dann x+1 Tage
 
naja, aber 47 h sind nun mal nicht 2 tage (als differenz auf jeden fall)

die stimmt aber nicht, weil 2 tage * 24 h + 1 h = 25 h sind. zw. dem 27.3.2010 und dem 29.3.2010 01:00:00 liegen aber nur 24 h
rechnen kannst du mit deinem ergebnis nicht mehr.

Der Tag ist für mich immer ein Kalendertag und keine 24h-Einheit (s.a. oben).
Wenn mit DateDiff mit dem Selector "d" gerechnet wird, sind im Ergebnis der ganze Teil die Kalendertage und die Nachkommastellen sind 1/24 Stunden.
Die Differenz zwischen dem 27.3.2010 und dem 29.3.2010 sind nun mal nur 47h (der 28.3.2010 hat nur 23h), deshalb sind die 2 Tage auch nicht "2 Tage * 24 h" !!
 
AW: Sommerzeit für Datum ermitteln

So nebenbei ist eine Funktion entstanden, die für ein beliebiges Datum ermittelt, ob dieses Datum in die Sommerzeit fällt. Hab schon viele Meinungen gelesen, dass dies mit Javascript nicht möglich sei.
Hier die Funktion:
PHP:
function isMESZ(d){
//d: datum als String, "" für das aktuelle Datum/Zeit oder Date-Object
var df = typeof(d)=="object" ? d : d=="" ? new Date() : new Date(d);
return (df.getTimezoneOffset()-(new Date("2000/1/1")).getTimezoneOffset() != 0);
}
Das Resultat ist true, wenn das Datum in die Sommerzeit fällt.

isMESZ online testen
 
javascript DateDiffArray - Datumsdifferenz als Tag, Stunde, Minute und Sekunde

Eine Zeitdifferenz wird mitunter als Tage, Stunden, Minuten und Sekunden benötigt, z.B. für Countdowns. Die folgende function DateDiffArray liefert für zwei Zeitpunkte die Differenz als array
(Index 0:Tage, 1:Stunden, 2:Minuten, 3:Sekunden):
PHP:
function DateDiffArray(dfrom,dto){
  var dhms =[], d = [86400000,3600000,60000,1000];
  var df = typeof(dfrom)=="object" ? dfrom : dfrom=="" ? new Date() : new Date(dfrom);
  var dt = typeof(dto)=="object" ? dto : dto=="" ? new Date() : new Date(dto);
  var r = dt.getTime() - df.getTime() + (df.getTimezoneOffset()-dt.getTimezoneOffset())*60000;
  if(r < 0) return false;  //Zeile streichen wenn negative Werte zugelassen werden sollen
  for(var i=0;i<4;i++) {
    dhms[i] = parseInt(r/d[i]);
    r %= d[i];
  }
  return dhms;
}

Als Parameter können der function strings oder Datumsobjecte übergeben werden. Das Endatum muß größer oder gleich dem Startdatum sein, wenn nicht wird false zurückgegeben.
Beispiele:
PHP:
result = DateDiffArray("2011/10/1","2012/1/1 00:00:00");
alert(result[0] + " Tage");
//mit Datumsobject
var heute = new Date();
result = DateDiffArray(heute,"2012/1/1 00:00:00");
if(result === false) alert("schon vorbei");
else alert(result[0] + " Tage");
//Leerstring als vereinfachte Schreibweise für 'new Date()'
result = DateDiffArray("","2012/1/1 00:00:00");
Ein Countdown wird mit der function DateDiffArray zum Kinderspiel, dazu noch kurz und übersichtlich.
Hier ein einfaches Beispiel mit 2 Countern:
HTML:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function DateDiffArray(dfrom,dto){
  var dhms =[], d = [86400000,3600000,60000,1000];
  var df = typeof(dfrom)=="object" ? dfrom : dfrom=="" ? new Date() : new Date(dfrom);
  var dt = typeof(dto)=="object" ? dto : dto=="" ? new Date() : new Date(dto);
  var r = dt.getTime() - df.getTime() + (df.getTimezoneOffset()-dt.getTimezoneOffset())*60000;
  if(r < 0) return false;  //Zeile streichen wenn negative Werte zugelassen werden
  for(var i=0;i<4;i++) {
    dhms[i] = parseInt(r/d[i]);
    r %= d[i];
  }
  return dhms;
}
function countdown(){
  var dt={"Counter1":"2011/6/28 13:00","Counter2":"2013/7/30"};
  var carr =[], s;
  for(var i in dt) {
      carr = DateDiffArray("",dt[i]);
      if(carr === false) s = "Beendet";
      else s =  carr[0] + " Tage " + carr[1] + " Std " + carr[2] + " Min " + carr[3] + " Sek.";
      document.getElementById(i).innerHTML = s;
  }
  window.setTimeout(countdown,500);
}
window.onload = countdown;
</script>
</head>
<body>
<h1>Simple Counter with function DateDiffArray</h1>
<div id="Counter1" >test1</div>
<div id="Counter2" >test2</div>
</body>
</html>
 
Zuletzt bearbeitet:
AW: javascript DateDiffArray - Datumsdifferenz als Tag, Stunde, Minute und Sekunde

Hallo,

Habe das Script ausprobiert und ist super. Aber wie bekommen ich es hin das die Counter nebeneinander sind und nicht untereinander.

gruss
 
Zuletzt bearbeitet von einem Moderator:
Indem du entweder aus dem <div>s <span>s machst oder indem du im CSS die display Eigenschaft für die beiden <div> auf inline setzt...
 
Zurück
Oben