Как получить количество дней между двумя датами в JavaScript? Например, даны две даты в полях ввода:
<input id="first" value="1/1/2000"/>
<input id="second" value="1/1/2001"/>
<script>
alert(datediff("day", first, second)); // what goes here?
</script>
Вот быстрая и грязная реализация datediff
, в качестве доказательства концепции для решения проблемы, представленной в вопросе. Она опирается на тот факт, что вы можете получить прошедшие миллисекунды между двумя датами путем их вычитания, что приводит их к примитивному числовому значению (миллисекунды с начала 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"/>
Вы должны знать, что "обычные" API Date (без "UTC" в названии) работают в локальном часовом поясе браузера пользователя, поэтому в общем случае вы можете столкнуться с проблемами, если ваш пользователь находится в часовом поясе, который вы не ожидаете, и вашему коду придется иметь дело с переходом на летнее время. Вам следует внимательно прочитать документацию по объекту Date и его методам, а для чего-либо более сложного настоятельно рекомендуется использовать библиотеку, предлагающую более безопасные и мощные API для работы с датами.
Кроме того, в целях иллюстрации в данном фрагменте для краткости используется именованный доступ к объекту window
, но в производстве вы должны использовать стандартизированные API, такие как getElementById, или, что более вероятно, какой-нибудь UI framework.
На момент написания статьи только один из других ответов правильно обрабатывает переходы DST (летнее время). Вот результаты по системе, расположенной в Калифорнии:
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
Хотя Math.round
возвращает правильные результаты, я думаю, что это несколько неуклюже. Вместо этого, явно принимая во внимание изменения в смещении UTC, когда DST начинается или заканчивается, мы можем использовать точную арифметику:
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()));
Расчеты даты JavaScript сложны, потому что Date
объектов хранит время внутри в UTC, а не по местному времени. Например, 3/10/2013 12:00 и # 160; стандартное время AM Pacific (UTC-08: 00) хранится как 3/10/2013 8:00 и # 160; UTC, полночь и 3/11/2013 12:00 и # 160; AM Pacific Daylight Time 0!
Хотя день в местное время может иметь более или менее 24 часов, день в UTC всегда ровно 24 часа. 1 < / sup > Показанный выше метод daysBetween
использует этот факт, сначала вызывая treatAsUTC
, чтобы настроить оба локальных времени до полуночи UTC, прежде чем вычитать и разделить.
1. JavaScript игнорирует високосные секунды.& Лт; / sup >
Самый простой способ получить разницу между двумя датами:
var diff = Math.floor(( Date.parse(str2) - Date.parse(str1) ) / 86400000);
Вы получаете разницу дней (или NaN, если один или оба не могут быть проанализированы). Дата анализа дала результат в миллисекундах, и чтобы получить его по дням, вы должны разделить его на 24 60 60 * 1000
Если вы хотите, чтобы он был разделен на дни, часы, минуты, секунды и миллисекунды:
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 )
};
}
Вот моя рефакторированная версия Джеймса версии:
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;
}
}
Я рекомендую использовать библиотеку moment.js (http://momentjs.com/docs/#/displaying/difference/). Он правильно обрабатывает летнее время и в целом отлично работает.
Пример:
var start = moment("2013-11-03");
var end = moment("2013-11-04");
end.diff(start, "days")
1
Я бы пошел вперед и взял эту небольшую утилиту, и в ней вы найдете функции, которые помогут вам в этом. Вот короткий пример:
<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>
const startDate = '2017-11-08';
const endDate = '2017-10-01';
const timeDiff = (new Date(startDate)) - (new Date(endDate));
const days = timeDiff / (1000 * 60 * 60 * 24)
Обновление: Я знаю, что это не является частью ваших вопросов, но в целом я бы не рекомендовал делать какие-либо вычисления даты или манипуляции в ванильном JavaScript и скорее использовать библиотеку, такую как date-fns или moment.js для него из-за множества краевых случаев.
Использование Moment.js
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
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>
& Лт;!- конец фрагмента - >
Значения даты в JS являются значениями даты и времени.
Таким образом, прямые вычисления даты противоречивы:
(2013-11-05 00:00:00) - (2013-11-04 10:10:10) < 1 day
например, нам нужно преобразовать de 2nd date:
(2013-11-05 00:00:00) - (2013-11-04 00:00:00) = 1 day
метод может усечь мельницы в обе даты:
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
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);
& Лт;!- конец фрагмента - >
Чтобы рассчитать дни между 2 заданными датами, вы можете использовать следующий код. Даты, которые я использую здесь, - 01 января 2016 года и 31 декабря 2016 года
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
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>
& Лт;!- конец фрагмента - >
Можно рассчитать полную разницу дней доказательства между двумя датами, покоящимися на разных TZ, используя следующую формулу:
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
var start = new Date('10/3/2015');
var end = new Date('11/2/2015');
var days = (end - start) / 1000 / 60 / 60 / 24;
console.log(days);
// actually its 30 ; but due to daylight savings will show 31.0xxx
// which you need to offset as below
days = days - (end.getTimezoneOffset() - start.getTimezoneOffset()) / (60 * 24);
console.log(days);
& Лт;!- конец фрагмента - >
Лучше избавиться от DST, Math.ceil, Math.floor и т. Д. используя UTC время:
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));
Этот пример дает разницу в 109 дней. 24 * 60 * 60 * 1000
- один день в миллисекундах.
Я нашел этот вопрос, когда хочу немного рассчитать две даты, но дата имеет значение часов и минут, я изменил ответ @ michael-liu, чтобы соответствовать моему требованию, и он прошел мой тест.
дни различий 2012-12-31 23:00
и 2013-01-01 01:00
должны равняться 1. (2 часа)
дни различий 2012-12-31 01:00
и 2013-01-01 23:00
должны равняться 1. (46 часов)
function treatAsUTC(date) {
var result = new Date(date);
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
return result;
}
var millisecondsPerDay = 24 * 60 * 60 * 1000;
function diffDays(startDate, endDate) {
return Math.floor(treatAsUTC(endDate) / millisecondsPerDay) - Math.floor(treatAsUTC(startDate) / millisecondsPerDay);
}
Я думаю, что решения не верны, 100% я бы использовал ceil вместо ploor , раунд будет работать, но это не правильная операция.
function dateDiff(str1, str2){
var diff = Date.parse(str2) - Date.parse(str1);
return isNaN(diff) ? NaN : {
diff: diff,
ms: Math.ceil(diff % 1000),
s: Math.ceil(diff / 1000 % 60),
m: Math.ceil(diff / 60000 % 60),
h: Math.ceil(diff / 3600000 % 24),
d: Math.ceil(diff / 86400000)
};
}
Как насчет использования formatDate из виджета DatePicker? Вы можете использовать его для преобразования дат в формат временной метки (миллисекунды с 01/01/1970), а затем выполнить простое вычитание.
var start= $("#firstDate").datepicker("getDate");
var end= $("#SecondDate").datepicker("getDate");
var days = (end- start) / (1000 * 60 * 60 * 24);
alert(Math.round(days));
[jsfiddle][1] пример :)
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
function timeDifference(date1, date2) {
var oneDay = 24 * 60 * 60; // hours*minutes*seconds
var oneHour = 60 * 60; // minutes*seconds
var oneMinute = 60; // 60 seconds
var firstDate = date1.getTime(); // convert to milliseconds
var secondDate = date2.getTime(); // convert to milliseconds
var seconds = Math.round(Math.abs(firstDate - secondDate) / 1000); //calculate the diffrence in seconds
// the difference object
var difference = {
"days": 0,
"hours": 0,
"minutes": 0,
"seconds": 0,
}
//calculate all the days and substract it from the total
while (seconds >= oneDay) {
difference.days++;
seconds -= oneDay;
}
//calculate all the remaining hours then substract it from the total
while (seconds >= oneHour) {
difference.hours++;
seconds -= oneHour;
}
//calculate all the remaining minutes then substract it from the total
while (seconds >= oneMinute) {
difference.minutes++;
seconds -= oneMinute;
}
//the remaining seconds :
difference.seconds = seconds;
//return the difference object
return difference;
}
console.log(timeDifference(new Date(2017,0,1,0,0,0),new Date()));
& Лт;!- конец фрагмента - >
Возможно, это не самое элегантное решение, но, похоже, оно отвечает на вопрос относительно простым кодом. Разве вы не можете использовать что-то вроде этого?
function dayDiff(startdate, enddate) {
var dayCount = 0;
while(enddate >= startdate) {
dayCount++;
startdate.setDate(startdate.getDate() + 1);
}
return dayCount;
}
Это предполагает, что вы передаете объекты даты в качестве параметров.
Будьте осторожны, когда используют миллисекунды .
date.getTime () возвращает миллисекунды, и выполнение математической операции с миллисекундами требует включения
Пример из комментария выше - лучшее решение, которое я нашел до сих пор https://stackoverflow.com/a/11252167/2091095 . Но используйте + 1 к его результату, если вы хотите, чтобы подсчитывать все вовлеченные дни.
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;
}
var diff = daysBetween($('#first').val(), $('#second').val()) + 1;
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
Date.prototype.days = function(to) {
return Math.abs(Math.floor(to.getTime() / (3600 * 24 * 1000)) - Math.floor(this.getTime() / (3600 * 24 * 1000)))
}
console.log(new Date('2014/05/20').days(new Date('2014/05/23'))); // 3 days
console.log(new Date('2014/05/23').days(new Date('2014/05/20'))); // 3 days
& Лт;!- конец фрагмента - >
У меня была такая же проблема в Angular. Я делаю копию, потому что еще он перезапишет первое свидание. Обе даты должны иметь время 00:00:00 (очевидно)
/*
* Deze functie gebruiken we om het aantal dagen te bereken van een booking.
* */
$scope.berekenDagen = function ()
{
$scope.booking.aantalDagen=0;
/*De loper is gelijk aan de startdag van je reservatie.
* De copy is nodig anders overschijft angular de booking.van.
* */
var loper = angular.copy($scope.booking.van);
/*Zolang de reservatie beschikbaar is, doorloop de weekdagen van je start tot einddatum.*/
while (loper < $scope.booking.tot) {
/*Tel een dag op bij je loper.*/
loper.setDate(loper.getDate() + 1);
$scope.booking.aantalDagen++;
}
/*Start datum telt natuurlijk ook mee*/
$scope.booking.aantalDagen++;
$scope.infomsg +=" aantal dagen: "+$scope.booking.aantalDagen;
};