578 Stimmen

Wie berechnet man die Anzahl der Tage zwischen zwei Daten?

Ein Beispiel: Zwei Daten in Eingabefeldern:

<input id="first" value="1/1/2000"/>
<input id="second" value="1/1/2001"/>

<script>
  alert(datediff("day", first, second)); // what goes here?
</script>

Wie ermittle ich die Anzahl der Tage zwischen zwei Daten in JavaScript?

20 Stimmen

In 99 % der Fälle, in denen der Benutzer nach der "Anzahl der Tage zwischen zwei Daten" fragt, versteht er nicht, dass er versucht, Äpfel mit Birnen zu vergleichen. Das Problem wird so einfach, wenn man fragt: "Wie viele DATEN liegen in einem DATUMSBEREICH?", oder wie viele Quadrate ich auf dem Kalender ankreuzen muss. Die Verwirrung wird uns durch die datetime-Datenstruktur auferlegt, die reiner Unfug ist. Es gibt so etwas wie datetime nicht, es gibt Datum und es gibt Zeit, zwei sehr unterschiedliche Objekte sowohl in der Natur als auch im Verhalten.

0 Stimmen

Für eine Funktion, die die Differenz in (ganze) Zeiteinheiten aufteilt, verwenden Sie die Antwort unter stackoverflow.com/a/53092438/3787376 .

1 Stimmen

Meiner Meinung nach sollte diese Frage gestrichen oder zumindest mit "vermeiden" gekennzeichnet werden, da die meisten Antworten entweder falsch oder von verschiedenen Bibliotheken abhängig sind.

542voto

Miles Punkte 29684

Hier ist ein schnell und schmutzig Umsetzung von datediff als Beweis für ein Konzept zur Lösung des Problems, wie es in der Frage dargestellt ist. Es beruht auf der Tatsache, dass man die verstrichenen Millisekunden zwischen zwei Daten durch Subtraktion erhalten kann, was sie in ihren primitiven Zahlenwert zwingt (Millisekunden seit Beginn des Jahres 1970).

// new Date("dateString") is browser-dependent and discouraged, so we'll write
// a simple parse function for U.S. date format (which does no error checking)
function parseDate(str) {
    var mdy = str.split('/');
    return new Date(mdy[2], mdy[0]-1, mdy[1]);
}

function datediff(first, second) {
    // Take the difference between the dates and divide by milliseconds per day.
    // Round to nearest whole number to deal with DST.
    return Math.round((second-first)/(1000*60*60*24));
}

alert(datediff(parseDate(first.value), parseDate(second.value)));

<input id="first" value="1/1/2000"/>
<input id="second" value="1/1/2001"/>

Sie sollten sich darüber im Klaren sein, dass die "normalen" Date-APIs (ohne "UTC" im Namen) in der lokalen Zeitzone des Browsers des Benutzers arbeiten, so dass Sie im Allgemeinen auf Probleme stoßen könnten, wenn sich Ihr Benutzer in einer Zeitzone befindet, die Sie nicht erwarten, und Ihr Code mit Sommerzeitumstellungen umgehen muss. Sie sollten die Dokumentation für das Date-Objekt und seine Methoden sorgfältig lesen und für kompliziertere Aufgaben unbedingt eine Bibliothek verwenden, die sicherere und leistungsfähigere APIs für die Datumsmanipulation bietet.

Zur Veranschaulichung verwendet das Snippet außerdem <a href="https://www.w3.org/TR/html5/browsers.html#named-access-on-the-window-object" rel="noreferrer">benannter Zugang auf der <code>window</code> Objekt </a>der Kürze halber, aber in der Produktion sollten Sie standardisierte APIs wie <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById" rel="noreferrer">getElementById </a>oder, was wahrscheinlicher ist, ein UI-Framework.

3 Stimmen

Ich denke, Math.trunc() ist besser geeignet. Nur für den Fall, dass jemand präzisere Datumsobjekte verwendet (d.h. einschließlich Stunden, Minuten und Sekunden)

43 Stimmen

Als die Antwort, die als richtig markiert wurde und (bisher) die meisten Stimmen erhalten hat, ist es erwähnenswert, dass diese Antwort die Sommerzeit nicht korrekt behandelt. Siehe stattdessen die Antwort von Michael Liu.

0 Stimmen

Was genau macht parseDate?

268voto

Michael Liu Punkte 48128

Zum jetzigen Zeitpunkt kann nur eine der anderen Antworten die Umstellung auf die Sommerzeit korrekt verarbeiten. Hier sind die Ergebnisse für ein System in Kalifornien:

                                        1/1/2013- 3/10/2013- 11/3/2013-
User       Formula                      2/1/2013  3/11/2013  11/4/2013  Result
---------  ---------------------------  --------  ---------  ---------  ---------
Miles                   (d2 - d1) / N   31        0.9583333  1.0416666  Incorrect
some         Math.floor((d2 - d1) / N)  31        0          1          Incorrect
fuentesjr    Math.round((d2 - d1) / N)  31        1          1          Correct
toloco     Math.ceiling((d2 - d1) / N)  31        1          2          Incorrect

N = 86400000

Obwohl Math.round die richtigen Ergebnisse liefert, halte ich es für etwas umständlich. Stattdessen können wir durch die explizite Berücksichtigung von Änderungen des UTC-Offsets bei Beginn oder Ende der Sommerzeit eine exakte Arithmetik verwenden:

function treatAsUTC(date) {
    var result = new Date(date);
    result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
    return result;
}

function daysBetween(startDate, endDate) {
    var millisecondsPerDay = 24 * 60 * 60 * 1000;
    return (treatAsUTC(endDate) - treatAsUTC(startDate)) / millisecondsPerDay;
}

alert(daysBetween($('#first').val(), $('#second').val()));

Erläuterung

JavaScript-Datumsberechnungen sind kompliziert, weil Date Objekte speichern Zeiten intern in UTC, nicht in Ortszeit. Zum Beispiel wird 3/10/2013 12:00 Uhr Pazifische Standardzeit (UTC-08:00) als 3/10/2013 8:00 Uhr UTC gespeichert, und 3/11/2013 12:00 Uhr Pazifische Sommerzeit (UTC-07:00) wird als 3/11/2013 7:00 Uhr UTC gespeichert. An diesem Tag sind es von Mitternacht bis Mitternacht Ortszeit nur 23 Stunden in UTC!

Obwohl ein Tag in Ortszeit mehr oder weniger als 24 Stunden haben kann, ist ein Tag in UTC immer genau 24 Stunden lang. 1 Die daysBetween Methode macht sich diese Tatsache zunutze, indem sie zuerst die treatAsUTC um beide Ortszeiten an Mitternacht UTC anzupassen, bevor sie subtrahiert und dividiert werden.

1. JavaScript ignoriert Schaltsekunden.

3 Stimmen

Es ist nicht notwendig, UTC zu verwenden, es reicht aus, die Ortszeit auf Mitternacht zu setzen (oder denselben Wert für beide Daten). Der Bruchteil des Tages, der durch die Sommerzeit eingeführt wird, beträgt höchstens ±0,04 (und an manchen Orten weniger), also rundet es sich mit Math.rund . ;-) Sich beim Parsen von Strings auf den Date-Konstruktor zu verlassen, ist keine gute Idee. Wenn Sie wirklich UTC-Werte verwenden wollen, parsen Sie die Strings mit Date.UTC(...) an erster Stelle.

3 Stimmen

@RobG: Wie ich in meiner Antwort angegeben habe: "Obwohl Math.round die richtigen Ergebnisse liefert, halte ich es für etwas klobig. Stattdessen können wir durch die explizite Berücksichtigung von Änderungen des UTC-Offsets, wenn die Sommerzeit beginnt oder endet, eine exakte Arithmetik verwenden.

2 Stimmen

Eigentlich sind die Zeiten, die Sie als "falsch" dargestellt haben, technisch gesehen korrekt. Sie ändern die DateTimes nicht in UTC... Sie ändern nur die Zeit jedes DateTime, um eine künstliche ganze Zahl zu erhalten. Runden ist nicht "klobig"... es ist genau der richtige Ansatz hier, weil das ist, was Sie in Ihrem Kopf sowieso tun: Sie sind Rundung weg die Zeit Teil (Stunden, Minuten, Sekunden) und nur versuchen, einen ganzen Tag Zahl zu erhalten.

142voto

some Punkte 45857

Der einfachste Weg, um die Differenz zwischen zwei Daten zu ermitteln:

var diff = Math.floor((Date.parse(str2) - Date.parse(str1)) / 86400000);

Sie erhalten die Differenztage (oder NaN, wenn einer oder beide nicht geparst werden konnten). Das Parse-Datum liefert das Ergebnis in Millisekunden, und um es als Tag zu erhalten, muss man es teilen durch 24 * 60 * 60 * 1000

Wenn Sie es durch Tage, Stunden, Minuten, Sekunden und Millisekunden teilen möchten:

function dateDiff( str1, str2 ) {
    var diff = Date.parse( str2 ) - Date.parse( str1 ); 
    return isNaN( diff ) ? NaN : {
        diff : diff,
        ms : Math.floor( diff            % 1000 ),
        s  : Math.floor( diff /     1000 %   60 ),
        m  : Math.floor( diff /    60000 %   60 ),
        h  : Math.floor( diff /  3600000 %   24 ),
        d  : Math.floor( diff / 86400000        )
    };
}

Hier ist meine umgestaltete Version von James Version:

function mydiff(date1,date2,interval) {
    var second=1000, minute=second*60, hour=minute*60, day=hour*24, week=day*7;
    date1 = new Date(date1);
    date2 = new Date(date2);
    var timediff = date2 - date1;
    if (isNaN(timediff)) return NaN;
    switch (interval) {
        case "years": return date2.getFullYear() - date1.getFullYear();
        case "months": return (
            ( date2.getFullYear() * 12 + date2.getMonth() )
            -
            ( date1.getFullYear() * 12 + date1.getMonth() )
        );
        case "weeks"  : return Math.floor(timediff / week);
        case "days"   : return Math.floor(timediff / day); 
        case "hours"  : return Math.floor(timediff / hour); 
        case "minutes": return Math.floor(timediff / minute);
        case "seconds": return Math.floor(timediff / second);
        default: return undefined;
    }
}

10 Stimmen

Schlechte Antwort. Mit Math.floor() verlieren Sie einen Tag, wenn die Uhren während der Sommerzeit vorwärts gehen. Math.round() liefert in den meisten Fällen die richtige Antwort, aber es gibt auch bessere Optionen für andere Antworten.

0 Stimmen

@some Wo sehen Sie James-Version ? Wer ist James?

0 Stimmen

@stomy Sieht aus, als sei diese Version gelöscht worden.

132voto

stephenbez Punkte 5431

Ich empfehle die Verwendung der moment.js-Bibliothek ( http://momentjs.com/docs/#/displaying/difference/ ). Es geht korrekt mit der Sommerzeit um und ist im Allgemeinen sehr benutzerfreundlich.

Ejemplo:

var start = moment("2013-11-03");
var end = moment("2013-11-04");
end.diff(start, "days")
1

30 Stimmen

Nur als Warnung, während momentjs ist groß, es ist eine ziemlich große Abhängigkeit

0 Stimmen

Eigentlich müsste es heißen end.diff(start,"days") obwohl der Code wie geschrieben funktioniert, weil das Startdatum nach dem Enddatum liegt!

131voto

marcobiedermann Punkte 2837

Schritte

  1. Starttermin festlegen
  2. Enddatum festlegen
  3. Berechnung der Differenz
  4. Millisekunden in Tage umrechnen

Native JS

const startDate  = '2020-01-01';
const endDate    = '2020-03-15';

const diffInMs   = new Date(endDate) - new Date(startDate)
const diffInDays = diffInMs / (1000 * 60 * 60 * 24);

Kommentar

Ich weiß, dies ist nicht Teil Ihrer Fragen, aber im Allgemeinen würde ich nicht empfehlen, jede Datumsberechnung oder -manipulation in Vanilla JavaScript zu tun und eher eine Bibliothek wie zu verwenden datum-fns , Luxon o moment.js wegen der vielen Grenzfälle.


Benutzung einer Bibliothek

Date-fns

https://date-fns.org/v2.16.1/docs/differenceInDays

const differenceInDays = require('date-fns/differenceInDays');

const startDate  = '2020-01-01';
const endDate    = '2020-03-15';

const diffInDays = differenceInDays(new Date(endDate), new Date(startDate));

Luxon

https://moment.github.io/luxon/docs/class/src/datetime.js~DateTime.html#instanz-methode-diff

const { DateTime } = require('luxon');

const startDate  = '2020-01-01';
const endDate    = '2020-03-15';

const diffInDays = DateTime.fromISO(endDate).diff(DateTime.fromISO(startDate), 'days').toObject().days;

Moment.js

https://momentjs.com/docs/#/displaying/difference/

const moment = require('moment');

const startDate  = '2020-01-01';
const endDate    = '2020-03-15';

const diffInDays = moment(endDate).diff(moment(startDate), 'days');

Beispiele auf RunKit

https://runkit.com/marcobiedermann/5f573e211e85e7001a37ab00

9 Stimmen

Ich schätze Antworten wie diese: kurz, einfach und keine zufälligen Abhängigkeiten erforderlich! Zum Wohl!

2 Stimmen

Geht es nur mir so, dass timeDiff negativ beantwortet? Müsste nicht timeDiff sein (new Date(endDate)) - (new Date(startDate)); ?

0 Stimmen

@feyisayo-sonubi hängt davon ab, in welcher Reihenfolge Sie Ihr Start- und Enddatum eingeben. In diesem Beispiel (new Date('2017-11-08')) - (new Date('2017-10-01')) // 3283200000

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X