javascript - Hvordan beregne antall dager mellom to datoer?


For eksempel, gitt to datoer i inntastingsbokser:

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

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

Hvordan får jeg antall dager mellom to datoer i JavaScript?

Svar #1

Her er en rask og enkel implementering av datediff, som et konseptbevis for å løse problemet slik det er presentert i spørsmålet. Den bygger på det faktum at du kan få antall millisekunder som har gått mellom to datoer ved å trekke dem fra hverandre, noe som tvinger dem til deres primitive tallverdi (millisekunder siden starten av 1970).

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

/**
 * 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]);
}

alert(datediff(parseDate(first.value), parseDate(second.value)));
<input id="first" value="1/1/2000"/>
<input id="second" value="1/1/2001"/>

Du bør være klar over at de "vanlige" Date-APIene (uten "UTC" i navnet) opererer i brukerens nettlesers lokale tidssone, så generelt kan du støte på problemer hvis brukeren din er i en tidszone du ikke forventer, og koden din må håndtere overganger til sommertid. Du bør lese dokumentasjonen for Date-objektet og dets metoder nøye, og for noe mer komplisert bør du sterkt vurdere å bruke et bibliotek som tilbyr mer sikre og kraftige APIer for datohåndtering.

  • Tall og datoer -- MDN JavaScript-guide
  • Dato -- MDN JavaScript-referanse

Også, for illustrasjonsformål, bruker utdraget navngitt tilgang på window-objektet for korthet, men i produksjon bør du bruke standardiserte API-er som getElementById, eller mer sannsynlig, et UI-rammeverk.

Svar #2

Per tidspunktet for denne skrivingen, er det bare ett av de andre svarene som håndterer DST (sommertid) overganger korrekt. Her er resultatene på et system som befinner seg i California:

                                        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

Selv om Math.round gir de riktige resultatene, synes jeg det er noe klønete. I stedet kan vi, ved å eksplisitt ta hensyn til endringer i UTC-offset når sommertid begynner eller slutter, bruke eksakt aritmetikk:

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

Forklaring

JavaScript-datum-beregninger er kompliserte fordi Date-objekter lagrer tid internt i UTC, ikke lokal tid. For eksempel lagres 10.03.2013 12:00 AM Pacific Standard Time (UTC-08:00) som 10.03.2013 08:00 AM UTC, og 11.03.2013 12:00 AM Pacific Daylight Time (UTC-07:00) lagres som 11.03.2013 07:00 AM UTC. Denne dagen er midnatt til midnatt lokal tid bare 23 timer i UTC!

Selv om et døgn i lokal tid kan ha mer eller mindre enn 24 timer, er et døgn i UTC alltid nøyaktig 24 timer.1 daysBetween-metoden vist ovenfor utnytter dette ved først å ringe treatAsUTC for å justere både lokale tider til midnatt UTC, før de trekkes fra hverandre og divideres.

1. JavaScript ignorerer skuddsekunder.

Svar #3

Den enkleste måten å finne forskjellen mellom to datoer på:

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

Du får differansedagene (eller NaN hvis en eller begge ikke kunne parses). Parse-datoen ga resultatet i millisekunder, og for å få det i dager må du dele det på 24 * 60 * 60 * 1000

Hvis du vil ha det delt opp i dager, timer, minutter, sekunder og millisekunder:

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

Her er min omarbeidede versjon av James' versjon:

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

Svar #4

De følgende løsningene vil anta at disse variablene er tilgjengelige i koden:

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

Native JS

Trinn :

  1. Sett startdato
  2. Sett sluttdato
  3. Beregn forskjell
  4. Konverter millisekunder til dager
const diffInMs   = new Date(endDate) - new Date(startDate);
const diffInDays = diffInMs / (1000 * 60 * 60 * 24);

Kommentar:

Jeg vet at dette ikke er en del av spørsmålene dine, men generelt vil jeg ikke anbefale å gjøre noen datoberegning eller manipulering i vanlig JavaScript, og heller bruke et bibliotek som date-fns, Luxon eller moment.js på grunn av mange spesialtilfeller.

Dette vanilje JavaScript-svaret beregner dagene som et desimaltall. I tillegg kan det støte på kanttilfeller når man arbeider med sommertid.


Bruke et bibliotek

- Date-fns

const differenceInDays = require('date-fns/differenceInDays');
const diffInDays = differenceInDays(new Date(endDate), new Date(startDate));

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

- Luxon

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

dokumentasjon: https://moment.github.io/luxon/api-docs/index.html#datetimediff

- Moment.js

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

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


Eksempler på RunKit

Svar #5

Jeg anbefaler å bruke moment.js-biblioteket (http://momentjs.com/docs/#/displaying/difference/). Det håndterer sommertid korrekt og er generelt flott å jobbe med.

Eksempel :

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

Svar #6

Jeg ville bare gå videre og ta tak i dette lille verktøyet, og i det vil du finne funksjoner som gjør dette for deg. Her er et kort eksempel:

        <script type="text/javascript" src="date.js"></script>
        <script type="text/javascript">
            var minutes = 1000*60;
            var hours = minutes*60;
            var days = hours*24;

            var foo_date1 = getDateFromFormat("02/10/2009", "M/d/y");
            var foo_date2 = getDateFromFormat("02/12/2009", "M/d/y");
            
            var diff_date = Math.round((foo_date2 - foo_date1)/days);
            alert("Diff date is: " + diff_date );
        </script>

Svar #7

Bruke Moment.js

var future = moment('05/02/2015');
var start = moment('04/23/2015');
var d = future.diff(start, 'days'); // 9
console.log(d);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>

Svar #8

For å beregne dager mellom 2 gitte datoer kan du bruke følgende kode. Datoene jeg bruker her er 01. januar 2016 og 31. desember 2016

var day_start = new Date("Jan 01 2016");
var day_end = new Date("Dec 31 2016");
var total_days = (day_end - day_start) / (1000 * 60 * 60 * 24);
document.getElementById("demo").innerHTML = Math.round(total_days);
<h3>DAYS BETWEEN GIVEN DATES</h3>
<p id="demo"></p>

Svar #9

Prøv dette

let today = new Date().toISOString().slice(0, 10)

const startDate  = '2021-04-15';
const endDate    = today;

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


alert( diffInDays  );

Svar #10

Datoverdier i JS er dato- og klokkeslettverdier.

Så, direkte datoberegninger er inkonsekvente:

(2013-11-05 00:00:00) - (2013-11-04 10:10:10) < 1 day

for eksempel må vi konvertere den 2. datoen:

(2013-11-05 00:00:00) - (2013-11-04 00:00:00) = 1 day

metoden kunne være å forkorte møllene i begge datoene:

var date1 = new Date('2013/11/04 00:00:00');
var date2 = new Date('2013/11/04 10:10:10'); //less than 1
var start = Math.floor(date1.getTime() / (3600 * 24 * 1000)); //days as integer from..
var end = Math.floor(date2.getTime() / (3600 * 24 * 1000)); //days as integer from..
var daysDiff = end - start; // exact dates
console.log(daysDiff);

date2 = new Date('2013/11/05 00:00:00'); //1

var start = Math.floor(date1.getTime() / (3600 * 24 * 1000)); //days as integer from..
var end = Math.floor(date2.getTime() / (3600 * 24 * 1000)); //days as integer from..
var daysDiff = end - start; // exact dates
console.log(daysDiff);

Svar #11

Bedre å kvitte seg med DST, Math.ceil, Math.floor osv. ved å bruke UTC-tider:

var firstDate = Date.UTC(2015,01,2);
var secondDate = Date.UTC(2015,04,22);
var diff = Math.abs((firstDate.valueOf() 
    - secondDate.valueOf())/(24*60*60*1000));

Dette eksemplet gir en forskjell på 109 dager. 24*60*60*1000 er en dag i millisekunder.

Relaterte artikler