Как рассчитать разницу дат в JavaScript?

181

Я хочу рассчитать разницу в днях, часах, минутах, секундах, миллисекундах, наносекундах. Как мне это сделать?

Фархан Сиддики
источник
1
возможно дубликат Получить разницу между 2 датами в JavaScript?
Андерсон Грин
1
Приведенные ниже решения будут нарушены, если две соответствующие даты находятся в разных часовых поясах. Посмотрите вопрос для более точного решения stackoverflow.com/questions/3224834/… ?
Шьям Хабаракада

Ответы:

219

Предполагая, что у вас есть два Dateобъекта , вы можете просто вычесть их, чтобы получить разницу в миллисекундах:

var difference = date2 - date1;

Оттуда вы можете использовать простую арифметику для получения других значений.

icktoofay
источник
38
Это так правильный ответ. Например: чтобы получить разницу в днях Math.floor((date2 - date1) / (1000*60*60*24))- для разницы в любой другой единице настройте знаменатель (базовое значение в мс).
trisweb
33
Не существует "простой" арифметики для преобразования миллисекунд в годы. Вы должны знать о биссекстильном году, часовом поясе, а в некоторых днях есть 23 или 25 часов. Некоторые годы имеют 365,25 дней, поэтому здесь нет простой арифметики (все еще ищем точное решение).
Александр Саломе
6
@Alexandre: Вопрос никогда не задавался годами. Действительно, вычисление различий по годам нетривиально. Однако для дней это правильно, если предположить, что даты находятся в одном и том же часовом поясе (не безосновательное предположение). Насколько я знаю, день определяется как 24 часа, и любое «изменение» из-за перехода на летнее время на самом деле является переключением часовых поясов. Если вы уже не различаете часовые пояса, попытка выяснить разницу во времени приведет вас к миру боли, не в последнюю очередь потому, что переключение DST «повторяет» время. Оставайтесь в одном часовом поясе, и все это работает.
icktoofay
12
@ trisweb - даже такая простая вещь, как получение разницы в днях, более сложна, чем ваш комментарий. Сколько дней между 22:00 вторника и 9:00 среды? Ваш алгоритм говорит 0. Другие могут подумать 1.
RobG
Релятивисты @RobG могут даже думать больше, чем 1 или меньше 0. Все зависит от наблюдателя.
Невинный Свидетель
78
var DateDiff = {

    inDays: function(d1, d2) {
        var t2 = d2.getTime();
        var t1 = d1.getTime();

        return parseInt((t2-t1)/(24*3600*1000));
    },

    inWeeks: function(d1, d2) {
        var t2 = d2.getTime();
        var t1 = d1.getTime();

        return parseInt((t2-t1)/(24*3600*1000*7));
    },

    inMonths: function(d1, d2) {
        var d1Y = d1.getFullYear();
        var d2Y = d2.getFullYear();
        var d1M = d1.getMonth();
        var d2M = d2.getMonth();

        return (d2M+12*d2Y)-(d1M+12*d1Y);
    },

    inYears: function(d1, d2) {
        return d2.getFullYear()-d1.getFullYear();
    }
}

var dString = "May, 20, 1984";

var d1 = new Date(dString);
var d2 = new Date();

document.write("<br />Number of <b>days</b> since "+dString+": "+DateDiff.inDays(d1, d2));
document.write("<br />Number of <b>weeks</b> since "+dString+": "+DateDiff.inWeeks(d1, d2));
document.write("<br />Number of <b>months</b> since "+dString+": "+DateDiff.inMonths(d1, d2));
document.write("<br />Number of <b>years</b> since "+dString+": "+DateDiff.inYears(d1, d2));

Пример кода взят отсюда .

Пареш Майани
источник
Это только возвращает разницу в дате в данном формате, если используется в качестве единого счетчика. Например, если вы хотите 3 месяца, 4 дня и 5 часов, это НЕ даст таких результатов. Еще в очереди 3 месяца 96 дней и много часов.
Йорис Кроос
30

Другое решение - преобразовать разницу в новый объект Date и получить год этой даты (разница с 1970), месяц, день и т. Д.

var date1 = new Date(2010, 6, 17);
var date2 = new Date(2013, 12, 18);
var diff = new Date(date2.getTime() - date1.getTime());
// diff is: Thu Jul 05 1973 04:00:00 GMT+0300 (EEST)

console.log(diff.getUTCFullYear() - 1970); // Gives difference as year
// 3

console.log(diff.getUTCMonth()); // Gives month count of difference
// 6

console.log(diff.getUTCDate() - 1); // Gives day count of difference
// 4

Таким образом, разница как «3 года и 6 месяцев и 4 дня». Если вы хотите почувствовать разницу в удобочитаемом стиле, это может вам помочь.

Мурат Чорлу
источник
Это не смысл! Мы хотим ВСЕ различие! В этом экзамене разница в днях составляет 1281, а не 4!
chaim.dev
3
@ chaim.dev «Если вы хотите почувствовать разницу в удобочитаемом стиле, это может вам помочь».
Мурат Чорлу
7
Это не надежно. В нем не учитываются разные месячные или високосные годы и другие аномалии.
Марк Дурдин
2
Спасибо Мурат, Это решение решило мою проблему. То, что я действительно хочу, это должно работать так же, как это делает php.
Ритеш Патадия
27

Выражения типа «разница в днях» никогда не бывают такими простыми, как кажется. Если у вас есть следующие даты:

d1: 2011-10-15 23:59:00
d1: 2011-10-16 00:01:00

разница во времени составляет 2 минуты, должна ли «разница в днях» быть 1 или 0? Аналогичные проблемы возникают при любом выражении разницы в месяцах, годах и т. Д., Поскольку годы, месяцы и дни имеют разную продолжительность и разное время (например, день, когда начинается переход на летнее время, на 1 час короче обычного и на два часа короче дня, когда Это конец).

Вот функция для разницы в днях, которая игнорирует время, то есть для вышеуказанных дат она возвращает 1.

/*
   Get the number of days between two dates - not inclusive.

   "between" does not include the start date, so days
   between Thursday and Friday is one, Thursday to Saturday
   is two, and so on. Between Friday and the following Friday is 7.

   e.g. getDaysBetweenDates( 22-Jul-2011, 29-jul-2011) => 7.

   If want inclusive dates (e.g. leave from 1/1/2011 to 30/1/2011),
   use date prior to start date (i.e. 31/12/2010 to 30/1/2011).

   Only calculates whole days.

   Assumes d0 <= d1
*/
function getDaysBetweenDates(d0, d1) {

  var msPerDay = 8.64e7;

  // Copy dates so don't mess them up
  var x0 = new Date(d0);
  var x1 = new Date(d1);

  // Set to noon - avoid DST errors
  x0.setHours(12,0,0);
  x1.setHours(12,0,0);

  // Round to remove daylight saving errors
  return Math.round( (x1 - x0) / msPerDay );
}

Это может быть более кратким:

/*  Return number of days between d0 and d1.
**  Returns positive if d0 < d1, otherwise negative.
**
**  e.g. between 2000-02-28 and 2001-02-28 there are 366 days
**       between 2015-12-28 and 2015-12-29 there is 1 day
**       between 2015-12-28 23:59:59 and 2015-12-29 00:00:01 there is 1 day
**       between 2015-12-28 00:00:01 and 2015-12-28 23:59:59 there are 0 days
**        
**  @param {Date} d0  - start date
**  @param {Date} d1  - end date
**  @returns {number} - whole number of days between d0 and d1
**
*/
function daysDifference(d0, d1) {
  var diff = new Date(+d1).setHours(12) - new Date(+d0).setHours(12);
  return Math.round(diff/8.64e7);
}

// Simple formatter
function formatDate(date){
  return [date.getFullYear(),('0'+(date.getMonth()+1)).slice(-2),('0'+date.getDate()).slice(-2)].join('-');
}

// Examples
[[new Date(2000,1,28), new Date(2001,1,28)],  // Leap year
 [new Date(2001,1,28), new Date(2002,1,28)],  // Not leap year
 [new Date(2017,0,1),  new Date(2017,1,1)] 
].forEach(function(dates) {
  document.write('From ' + formatDate(dates[0]) + ' to ' + formatDate(dates[1]) +
                 ' is ' + daysDifference(dates[0],dates[1]) + ' days<br>');
});

RobG
источник
1
@ rudeovskizebear - протестировано в IE, Firefox и Safari, работает отлично. Он использует базовый ECMAScript, который я ожидал бы работать в любом браузере, что у вас не работает?
RobG
Я поместил его на тестовую страницу, и он отлично работал в Chrome, но я продолжал получать нулевое значение в IE9 и последней версии FF
mnsr
@ RafiB. - Я не знаю, как вы думаете, что один более точный, чем другой, по сути, они делают одно и то же, то есть вычисляют разницу в целых днях, используя значение времени UTC. Неопределенность в вопросе не выяснена. Если это так, это может привести к другому решению.
RobG
@RobG Пожалуйста, отредактируйте примеры в комментариях более краткого решения. Месяц должен быть «12», а не «22»
S.aad
1
@ IgorKudryashov - извините, я просто не понимаю. 2000 год является високосным, поэтому с 28 февраля 2000 года по 28 февраля 2001 года - 366 дней. В не високосный год это 365 дней. Я добавил еще несколько примеров.
RobG
18
<html lang="en">
<head>
<script>
function getDateDiff(time1, time2) {
  var str1= time1.split('/');
  var str2= time2.split('/');

  //                yyyy   , mm       , dd
  var t1 = new Date(str1[2], str1[0]-1, str1[1]);
  var t2 = new Date(str2[2], str2[0]-1, str2[1]);

  var diffMS = t1 - t2;    
  console.log(diffMS + ' ms');

  var diffS = diffMS / 1000;    
  console.log(diffS + ' ');

  var diffM = diffS / 60;
  console.log(diffM + ' minutes');

  var diffH = diffM / 60;
  console.log(diffH + ' hours');

  var diffD = diffH / 24;
  console.log(diffD + ' days');
  alert(diffD);
}

//alert(getDateDiff('10/18/2013','10/14/2013'));
</script>
</head>
<body>
  <input type="button" 
       onclick="getDateDiff('10/18/2013','10/14/2013')" 
       value="clickHere()" />

</body>
</html>
Анади Кумар
источник
Не помогает мне Не может распространиться на месяцы или годы в том же подходе.
Томазалин
9

использование Moment.js для всех ваших расчетов даты и времени, связанных с JavaScript

Ответ на ваш вопрос:

var a = moment([2007, 0, 29]);   
var b = moment([2007, 0, 28]);    
a.diff(b) // 86400000  

Полную информацию можно найти здесь

Басант Саху
источник
4
И принять дополнительные 400 Кб для простой разницы дат.
Ромео Михальча
@RomeoMihalcea Текущий минимизированный момент.js 2.22.2 с одной локалью - 53 КБ, 17 КБ распакованы. Я понимаю вашу озабоченность, хотя. Это огромная библиотека, которую можно использовать для одной простой функции, но она заботится о столь многих причудах, связанных с датой и временем, что она того стоит.
HeikoS
8
function DateDiff(date1, date2) {
    date1.setHours(0);
    date1.setMinutes(0, 0, 0);
    date2.setHours(0);
    date2.setMinutes(0, 0, 0);
    var datediff = Math.abs(date1.getTime() - date2.getTime()); // difference 
    return parseInt(datediff / (24 * 60 * 60 * 1000), 10); //Convert values days and return value      
}
user2513608
источник
Спасибо за решения :)
Bhagirathi
Большинство решений, которые я нашел, либо не работают, либо слишком затянуто. Ваше решение является самым простым и работает точно так, как задумано! Приветствия :)
Брюс
Что если я хочу узнать разницу с точностью более часа? в почтовом вопросе есть часы и секунды, зачем все эти зеросеттинги?
2
8

С моментами все просто:

moment("2016-04-08").fromNow();
Джош Ламар
источник
1
moment.js - это круто! :)
Ками
Хороший ответ, но, вероятно, излишний для этой конкретной ситуации.
HappyDog
6
var d1=new Date(2011,0,1); // jan,1 2011
var d2=new Date(); // now

var diff=d2-d1,sign=diff<0?-1:1,milliseconds,seconds,minutes,hours,days;
diff/=sign; // or diff=Math.abs(diff);
diff=(diff-(milliseconds=diff%1000))/1000;
diff=(diff-(seconds=diff%60))/60;
diff=(diff-(minutes=diff%60))/60;
days=(diff-(hours=diff%24))/24;

console.info(sign===1?"Elapsed: ":"Remains: ",
             days+" days, ",
             hours+" hours, ",
             minutes+" minutes, ",
             seconds+" seconds, ",
             milliseconds+" milliseconds.");
Андрей Д.
источник
4

Извините, но плоский миллисекундный расчет не является надежным Спасибо за все ответы, но некоторые из опробованных мной функций не работают: 1. Дата, близкая к сегодняшней, 2. Дата в 1970 или 3. Дата в високосном году.

Подход, который лучше всего сработал для меня и охватывает все сценарии, например високосный год, недалекую дату в 1970 году, 29 февраля и т. Д.

var someday = new Date("8/1/1985");
var today = new Date();
var years = today.getFullYear() - someday.getFullYear();

// Reset someday to the current year.
someday.setFullYear(today.getFullYear());

// Depending on when that day falls for this year, subtract 1.
if (today < someday)
{
    years--;
}
document.write("Its been " + years + " full years.");
jaiveeru
источник
3

Если вы используете moment.js, то найти разницу в дате довольно просто.

var now  = "04/09/2013 15:00:00";
var then = "04/09/2013 14:20:30";

moment.utc(moment(now,"DD/MM/YYYY HH:mm:ss").diff(moment(then,"DD/MM/YYYY HH:mm:ss"))).format("HH:mm:ss")
Джеймс Хокингс
источник
3
function DateDiff(b, e)
{
    let
        endYear = e.getFullYear(),
        endMonth = e.getMonth(),
        years = endYear - b.getFullYear(),
        months = endMonth - b.getMonth(),
        days = e.getDate() - b.getDate();
    if (months < 0)
    {
        years--;
        months += 12;
    }
    if (days < 0)
    {
        months--;
        days += new Date(endYear, endMonth, 0).getDate();
    }
    return [years, months, days];
}

[years, months, days] = DateDiff(
    new Date("October 21, 1980"),
    new Date("July 11, 2017")); // 36 8 20
Александр Черносвитов
источник
3

Я думаю, что это должно сделать это.

let today = new Date();
let form_date=new Date('2019-10-23')
let difference=form_date>today ? form_date-today : today-form_date
let diff_days=Math.floor(difference/(1000*3600*24))
Эбука Джозеф Акеру
источник
2

Вот как вы можете реализовать разницу между датами без рамки.

function getDateDiff(dateOne, dateTwo) {
        if(dateOne.charAt(2)=='-' & dateTwo.charAt(2)=='-'){
            dateOne = new Date(formatDate(dateOne));
            dateTwo = new Date(formatDate(dateTwo));
        }
        else{
            dateOne = new Date(dateOne);
            dateTwo = new Date(dateTwo);            
        }
        let timeDiff = Math.abs(dateOne.getTime() - dateTwo.getTime());
        let diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
        let diffMonths = Math.ceil(diffDays/31);
        let diffYears = Math.ceil(diffMonths/12);

        let message = "Difference in Days: " + diffDays + " " +
                      "Difference in Months: " + diffMonths+ " " + 
                      "Difference in Years: " + diffYears;
        return message;
     }

    function formatDate(date) {
         return date.split('-').reverse().join('-');
    }

    console.log(getDateDiff("23-04-2017", "23-04-2018"));
Аравинда Мевалаараччи
источник
1

function daysInMonth (month, year) {
    return new Date(year, month, 0).getDate();
}
function getduration(){

let A= document.getElementById("date1_id").value
let B= document.getElementById("date2_id").value

let C=Number(A.substring(3,5))
let D=Number(B.substring(3,5))
let dif=D-C
let arr=[];
let sum=0;
for (let i=0;i<dif+1;i++){
  sum+=Number(daysInMonth(i+C,2019))
}
let sum_alter=0;
for (let i=0;i<dif;i++){
  sum_alter+=Number(daysInMonth(i+C,2019))
}
let no_of_month=(Number(B.substring(3,5)) - Number(A.substring(3,5)))
let days=[];
if ((Number(B.substring(3,5)) - Number(A.substring(3,5)))>0||Number(B.substring(0,2)) - Number(A.substring(0,2))<0){
days=Number(B.substring(0,2)) - Number(A.substring(0,2)) + sum_alter
}

if ((Number(B.substring(3,5)) == Number(A.substring(3,5)))){
console.log(Number(B.substring(0,2)) - Number(A.substring(0,2)) + sum_alter)
}

time_1=[]; time_2=[]; let hour=[];
 time_1=document.getElementById("time1_id").value
 time_2=document.getElementById("time2_id").value
  if (time_1.substring(0,2)=="12"){
     time_1="00:00:00 PM"
  }
if (time_1.substring(9,11)==time_2.substring(9,11)){
hour=Math.abs(Number(time_2.substring(0,2)) - Number(time_1.substring(0,2)))
}
if (time_1.substring(9,11)!=time_2.substring(9,11)){
hour=Math.abs(Number(time_2.substring(0,2)) - Number(time_1.substring(0,2)))+12
}
let min=Math.abs(Number(time_1.substring(3,5))-Number(time_2.substring(3,5)))
document.getElementById("duration_id").value=days +" days "+ hour+"  hour " + min+"  min " 
}
<input type="text" id="date1_id" placeholder="28/05/2019">
<input type="text" id="date2_id" placeholder="29/06/2019">
<br><br>
<input type="text" id="time1_id" placeholder="08:01:00 AM">
<input type="text" id="time2_id" placeholder="00:00:00 PM">
<br><br>
<button class="text" onClick="getduration()">Submit </button>
<br><br>
<input type="text" id="duration_id" placeholder="days hour min">

Максимус Су
источник
Этот код дает точные результаты о количестве дней, времени и даже минут
Maximus Su
Надеюсь, вы, ребята, используете это
Maximus Su
0

Хорошо, есть множество способов сделать это. Да, вы можете использовать старый добрый JS. Просто попробуй:

let dt1 = new Date()
let dt2 = new Date()

Давайте эмулируем переход, используя Date.prototype.setMinutes и убедимся, что мы находимся в диапазоне.

dt1.setMinutes(7)
dt2.setMinutes(42)
console.log('Elapsed seconds:',(dt2-dt1)/1000)

В качестве альтернативы вы можете использовать библиотеку, такую ​​как js-joda , где вы можете легко делать такие вещи (прямо из документов):

var dt1 = LocalDateTime.parse("2016-02-26T23:55:42.123");
var dt2 = dt1
  .plusYears(6)
  .plusMonths(12)
  .plusHours(2)
  .plusMinutes(42)
  .plusSeconds(12);

// obtain the duration between the two dates
dt1.until(dt2, ChronoUnit.YEARS); // 7
dt1.until(dt2, ChronoUnit.MONTHS); // 84
dt1.until(dt2, ChronoUnit.WEEKS); // 356
dt1.until(dt2, ChronoUnit.DAYS); // 2557
dt1.until(dt2, ChronoUnit.HOURS); // 61370
dt1.until(dt2, ChronoUnit.MINUTES); // 3682242
dt1.until(dt2, ChronoUnit.SECONDS); // 220934532

Существует множество других библиотек, но js-joda имеет дополнительный бонус за доступность также на Java, где она была тщательно протестирована. Все эти тесты были перенесены в js-joda, он также неизменен.

mwojtera
источник
-1

это должно работать нормально, если вам просто нужно показать, сколько времени осталось, так как JavaScript использует кадры, в то время как у вас будет время окончания - Время RN, после чего мы можем разделить его на 1000, поскольку, очевидно, 1000 кадров = 1 секунда, после этого вы можете использовать основную математику времени, но в этом коде по-прежнему есть проблема, поскольку вычисления являются статическими, они не могут компенсировать разницу в количестве дней в году (360/365/366), куча Если после вычисления значение обнуляется, если время меньше 0, надеюсь, это поможет, хотя это не совсем то, что вы просите :)

var now = new Date();
var end = new Date("End Time");
var total = (end - now) ;
var totalD =  Math.abs(Math.floor(total/1000));

var years = Math.floor(totalD / (365*60*60*24));
var months = Math.floor((totalD - years*365*60*60*24) / (30*60*60*24));
var days = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24)/ (60*60*24));
var hours = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24)/ (60*60));
var minutes = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24 - hours*60*60)/ (60));
var seconds = Math.floor(totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24 - hours*60*60 - minutes*60);

var Y = years < 1 ? "" : years + " Years ";
var M = months < 1 ? "" : months + " Months ";
var D = days < 1 ? "" : days + " Days ";
var H = hours < 1 ? "" : hours + " Hours ";
var I = minutes < 1 ? "" : minutes + " Minutes ";
var S = seconds < 1 ? "" : seconds + " Seconds ";
var A = years == 0 && months == 0 && days == 0 && hours == 0 && minutes == 0 && seconds == 0 ? "Sending" : " Remaining";

document.getElementById('txt').innerHTML = Y + M + D + H + I + S + A;
KratzXD
источник