Разница между двумя датами в годах, месяцах, днях в JavaScript
Я искал 4 часа и не нашел решения, чтобы получить разницу между двумя датами в годах, месяцах и днях в JavaScript, например: 10 апреля 2010 года было 3 года, x месяц и год дней назад.
Есть много решений, но они предлагают только разницу в формате дней или месяцев ИЛИ лет, или они неверны (что означает не заботиться о фактическом количестве дней в месяц или високосных годах и т.д.)., Неужели это так сложно?
Я посмотрел:
В php это легко, но, к сожалению, я могу использовать только клиентский script для этого проекта. Любая библиотека или фреймворк, которые могут это сделать, тоже будут хороши.
Ниже приведен список ожидаемых результатов для различий даты:
//Expected output should be: "1 year, 5 months".
diffDate(new Date('2014-05-10'), new Date('2015-10-10'));
//Expected output should be: "1 year, 4 months, 29 days".
diffDate(new Date('2014-05-10'), new Date('2015-10-09'));
//Expected output should be: "1 year, 3 months, 30 days".
diffDate(new Date('2014-05-10'), new Date('2015-09-09'));
//Expected output should be: "9 months, 27 days".
diffDate(new Date('2014-05-10'), new Date('2015-03-09'));
//Expected output should be: "1 year, 9 months, 28 days".
diffDate(new Date('2014-05-10'), new Date('2016-03-09'));
//Expected output should be: "1 year, 10 months, 1 days".
diffDate(new Date('2014-05-10'), new Date('2016-03-11'));
Ответы
Ответ 1
Насколько точны вам быть? Если вам нужно учитывать общие годы и високосные годы и точную разницу в днях между месяцами, тогда вам придется написать что-то более продвинутое, но для базового и грубого расчета это должно сделать трюк:
today = new Date()
past = new Date(2010,05,01) // remember this is equivalent to 06 01 2010
//dates in js are counted from 0, so 05 is june
function calcDate(date1,date2) {
var diff = Math.floor(date1.getTime() - date2.getTime());
var day = 1000 * 60 * 60 * 24;
var days = Math.floor(diff/day);
var months = Math.floor(days/31);
var years = Math.floor(months/12);
var message = date2.toDateString();
message += " was "
message += days + " days "
message += months + " months "
message += years + " years ago \n"
return message
}
a = calcDate(today,past)
console.log(a) // returns Tue Jun 01 2010 was 1143 days 36 months 3 years ago
Имейте в виду, что это неточно, для того, чтобы рассчитать дату с полной точностью, нужно было бы иметь календарь и знать, год ли високосный год или нет, также как я рассчитываю количество месяцев является приблизительным.
Но вы можете легко его улучшить.
Ответ 2
На самом деле, есть решение с плагином moment.js, и это очень просто.
Вы можете использовать moment.js
Не изобретайте снова колесо.
Просто подключите Moment.js Плагин диапазона дат.
Пример:
var starts = moment('2014-02-03 12:53:12');
var ends = moment();
var duration = moment.duration(ends.diff(starts));
// with ###moment precise date range plugin###
// it will tell you the difference in human terms
var diff = moment.preciseDiff(starts, ends, true);
// example: { "years": 2, "months": 7, "days": 0, "hours": 6, "minutes": 29, "seconds": 17, "firstDateWasLater": false }
// or as string:
var diffHuman = moment.preciseDiff(starts, ends);
// example: 2 years 7 months 6 hours 29 minutes 17 seconds
document.getElementById('output1').innerHTML = JSON.stringify(diff)
document.getElementById('output2').innerHTML = diffHuman
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
<script src="https://raw.githubusercontent.com/codebox/moment-precise-range/master/moment-precise-range.js"></script>
</head>
<body>
<h2>Difference between "NOW and 2014-02-03 12:53:12"</h2>
<span id="output1"></span>
<br />
<span id="output2"></span>
</body>
</html>
Ответ 3
Я использовал этот простой код, чтобы получить разницу в годах, месяцах, днях с текущей датой.
var sdt = new Date('1972-11-30');
var difdt = new Date(new Date() - sdt);
alert((difdt.toISOString().slice(0, 4) - 1970) + "Y " + (difdt.getMonth()+1) + "M " + difdt.getDate() + "D");
Ответ 4
Для быстрого и легкого использования я написал эту функцию некоторое время назад. Он возвращает разницу между двумя датами в хорошем формате. Не стесняйтесь использовать его (проверено на webkit).
/**
* Function to print date diffs.
*
* @param {Date} fromDate: The valid start date
* @param {Date} toDate: The end date. Can be null (if so the function uses "now").
* @param {Number} levels: The number of details you want to get out (1="in 2 Months",2="in 2 Months, 20 Days",...)
* @param {Boolean} prefix: adds "in" or "ago" to the return string
* @return {String} Diffrence between the two dates.
*/
function getNiceTime(fromDate, toDate, levels, prefix){
var lang = {
"date.past": "{0} ago",
"date.future": "in {0}",
"date.now": "now",
"date.year": "{0} year",
"date.years": "{0} years",
"date.years.prefixed": "{0} years",
"date.month": "{0} month",
"date.months": "{0} months",
"date.months.prefixed": "{0} months",
"date.day": "{0} day",
"date.days": "{0} days",
"date.days.prefixed": "{0} days",
"date.hour": "{0} hour",
"date.hours": "{0} hours",
"date.hours.prefixed": "{0} hours",
"date.minute": "{0} minute",
"date.minutes": "{0} minutes",
"date.minutes.prefixed": "{0} minutes",
"date.second": "{0} second",
"date.seconds": "{0} seconds",
"date.seconds.prefixed": "{0} seconds",
},
langFn = function(id,params){
var returnValue = lang[id] || "";
if(params){
for(var i=0;i<params.length;i++){
returnValue = returnValue.replace("{"+i+"}",params[i]);
}
}
return returnValue;
},
toDate = toDate ? toDate : new Date(),
diff = fromDate - toDate,
past = diff < 0 ? true : false,
diff = diff < 0 ? diff * -1 : diff,
date = new Date(new Date(1970,0,1,0).getTime()+diff),
returnString = '',
count = 0,
years = (date.getFullYear() - 1970);
if(years > 0){
var langSingle = "date.year" + (prefix ? "" : ""),
langMultiple = "date.years" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (years > 1 ? langFn(langMultiple,[years]) : langFn(langSingle,[years]));
count ++;
}
var months = date.getMonth();
if(count < levels && months > 0){
var langSingle = "date.month" + (prefix ? "" : ""),
langMultiple = "date.months" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (months > 1 ? langFn(langMultiple,[months]) : langFn(langSingle,[months]));
count ++;
} else {
if(count > 0)
count = 99;
}
var days = date.getDate() - 1;
if(count < levels && days > 0){
var langSingle = "date.day" + (prefix ? "" : ""),
langMultiple = "date.days" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (days > 1 ? langFn(langMultiple,[days]) : langFn(langSingle,[days]));
count ++;
} else {
if(count > 0)
count = 99;
}
var hours = date.getHours();
if(count < levels && hours > 0){
var langSingle = "date.hour" + (prefix ? "" : ""),
langMultiple = "date.hours" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (hours > 1 ? langFn(langMultiple,[hours]) : langFn(langSingle,[hours]));
count ++;
} else {
if(count > 0)
count = 99;
}
var minutes = date.getMinutes();
if(count < levels && minutes > 0){
var langSingle = "date.minute" + (prefix ? "" : ""),
langMultiple = "date.minutes" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (minutes > 1 ? langFn(langMultiple,[minutes]) : langFn(langSingle,[minutes]));
count ++;
} else {
if(count > 0)
count = 99;
}
var seconds = date.getSeconds();
if(count < levels && seconds > 0){
var langSingle = "date.second" + (prefix ? "" : ""),
langMultiple = "date.seconds" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (seconds > 1 ? langFn(langMultiple,[seconds]) : langFn(langSingle,[seconds]));
count ++;
} else {
if(count > 0)
count = 99;
}
if(prefix){
if(returnString == ""){
returnString = langFn("date.now");
} else if(past)
returnString = langFn("date.past",[returnString]);
else
returnString = langFn("date.future",[returnString]);
}
return returnString;
}
Ответ 5
Я думаю, вы ищете то же самое, что я хотел. Я попытался сделать это, используя разницу в миллисекундах, которую предоставляет javascript, но эти результаты не работают в реальном мире дат. Если вы хотите разницу между 1 февраля 2016 года и 31 января 2017 года, я бы хотел получить 1 год, 0 месяцев и 0 дней. Ровно один год (при условии, что вы считаете последний день как полный день, например, в аренду для квартиры). Тем не менее, миллисекундный подход даст вам 1 год 0 месяцев и 1 день, так как диапазон дат включает високосный год. Итак, вот код, который я использовал в javascript для моей формы adobe (вы можете назвать поля): (отредактирован, произошла ошибка, которую я исправил)
var f1 = this.getField("LeaseExpiration");
var g1 = this.getField("LeaseStart");
var end = f1.value
var begin = g1.value
var e = new Date(end);
var b = new Date(begin);
var bMonth = b.getMonth();
var bYear = b.getFullYear();
var eYear = e.getFullYear();
var eMonth = e.getMonth();
var bDay = b.getDate();
var eDay = e.getDate() + 1;
if ((eMonth == 0)||(eMonth == 2)||(eMonth == 4)|| (eMonth == 6) || (eMonth == 7) ||(eMonth == 9)||(eMonth == 11))
{
var eDays = 31;
}
if ((eMonth == 3)||(eMonth == 5)||(eMonth == 8)|| (eMonth == 10))
{
var eDays = 30;
}
if (eMonth == 1&&((eYear % 4 == 0) && (eYear % 100 != 0)) || (eYear % 400 == 0))
{
var eDays = 29;
}
if (eMonth == 1&&((eYear % 4 != 0) || (eYear % 100 == 0)))
{
var eDays = 28;
}
if ((bMonth == 0)||(bMonth == 2)||(bMonth == 4)|| (bMonth == 6) || (bMonth == 7) ||(bMonth == 9)||(bMonth == 11))
{
var bDays = 31;
}
if ((bMonth == 3)||(bMonth == 5)||(bMonth == 8)|| (bMonth == 10))
{
var bDays = 30;
}
if (bMonth == 1&&((bYear % 4 == 0) && (bYear % 100 != 0)) || (bYear % 400 == 0))
{
var bDays = 29;
}
if (bMonth == 1&&((bYear % 4 != 0) || (bYear % 100 == 0)))
{
var bDays = 28;
}
var FirstMonthDiff = bDays - bDay + 1;
if (eDay - bDay < 0)
{
eMonth = eMonth - 1;
eDay = eDay + eDays;
}
var daysDiff = eDay - bDay;
if(eMonth - bMonth < 0)
{
eYear = eYear - 1;
eMonth = eMonth + 12;
}
var monthDiff = eMonth - bMonth;
var yearDiff = eYear - bYear;
if (daysDiff == eDays)
{
daysDiff = 0;
monthDiff = monthDiff + 1;
if (monthDiff == 12)
{
monthDiff = 0;
yearDiff = yearDiff + 1;
}
}
if ((FirstMonthDiff != bDays)&&(eDay - 1 == eDays))
{
daysDiff = FirstMonthDiff;
}
event.value = yearDiff + " Year(s)" + " " + monthDiff + " month(s) " + daysDiff + " days(s)"
Ответ 6
Некоторая математика в порядке.
Вы можете вычесть один объект Date из другого в Javascript, и вы получите разницу между ними в milisseconds. Из этого результата вы можете извлечь другие части, которые вы хотите (дни, месяцы и т.д.).
Например:
var a = new Date(2010, 10, 1);
var b = new Date(2010, 9, 1);
var c = a - b; // c equals 2674800000,
// the amount of milisseconds between September 1, 2010
// and August 1, 2010.
Теперь вы можете получить любую часть, которую хотите. Например, сколько дней прошло между двумя датами:
var days = (a - b) / (60 * 60 * 24 * 1000);
// 60 * 60 * 24 * 1000 is the amount of milisseconds in a day.
// the variable days now equals 30.958333333333332.
Это почти 31 день. Затем вы можете округлить в течение 30 дней и использовать все, что осталось, чтобы получить количество часов, минут и т.д.
Ответ 7
Изменено это, чтобы быть более точным. Он преобразует даты в формат "ГГГГ-ММ-ДД", игнорируя ЧЧ: ММ: СС, и принимает необязательный endDate или использует текущую дату, и не заботится о порядке значений.
function dateDiff(startingDate, endingDate) {
var startDate = new Date(new Date(startingDate).toISOString().substr(0, 10));
if (!endingDate) {
endingDate = new Date().toISOString().substr(0, 10); // need date in YYYY-MM-DD format
}
var endDate = new Date(endingDate);
if (startDate > endDate) {
var swap = startDate;
startDate = endDate;
endDate = swap;
}
var startYear = startDate.getFullYear();
var february = (startYear % 4 === 0 && startYear % 100 !== 0) || startYear % 400 === 0 ? 29 : 28;
var daysInMonth = [31, february, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var yearDiff = endDate.getFullYear() - startYear;
var monthDiff = endDate.getMonth() - startDate.getMonth();
if (monthDiff < 0) {
yearDiff--;
monthDiff += 12;
}
var dayDiff = endDate.getDate() - startDate.getDate();
if (dayDiff < 0) {
if (monthDiff > 0) {
monthDiff--;
} else {
yearDiff--;
monthDiff = 11;
}
dayDiff += daysInMonth[startDate.getMonth()];
}
return yearDiff + 'Y ' + monthDiff + 'M ' + dayDiff + 'D';
}
Тогда вы можете использовать это так:
// based on a current date of 2019-05-10
dateDiff('2019-05-10'); // 0Y 0M 0D
dateDiff('2019-05-09'); // 0Y 0M 1D
dateDiff('2018-05-09'); // 1Y 0M 1D
dateDiff('2018-05-18'); // 0Y 11M 23D
dateDiff('2019-01-09'); // 0Y 4M 1D
dateDiff('2019-02-10'); // 0Y 3M 0D
dateDiff('2019-02-11'); // 0Y 2M 27D
dateDiff('2016-02-11'); // 3Y 2M 28D - leap year
dateDiff('1972-11-30'); // 46Y 5M 10D
dateDiff('2016-02-11', '2017-02-11'); // 1Y 0M 0D
dateDiff('2016-02-11', '2016-03-10'); // 0Y 0M 28D - leap year
dateDiff('2100-02-11', '2100-03-10'); // 0Y 0M 27D - not a leap year
dateDiff('2017-02-11', '2016-02-11'); // 1Y 0M 0D - swapped dates to return correct result
dateDiff(new Date() - 1000 * 60 * 60 * 24); // 0Y 0M 1D
Более старая, менее точная, но более простая версия
Ответ @RajeevPNadig был тем, что я искал, но его код возвращает неверные значения, как написано. Это не очень точно, потому что предполагает, что последовательность дат с 1 января 1970 года такая же, как и любая другая последовательность того же числа дней. Например, он рассчитывает разницу с 1 июля по 1 сентября (62 дня) как 0Y 2M 3D, а не 0Y 2M 0D, потому что 1 января 1970 года плюс 62 дня - 3 марта.
// startDate must be a date string
function dateAgo(date) {
var startDate = new Date(date);
var diffDate = new Date(new Date() - startDate);
return ((diffDate.toISOString().slice(0, 4) - 1970) + "Y " +
diffDate.getMonth() + "M " + (diffDate.getDate()-1) + "D");
}
Тогда вы можете использовать это так:
// based on a current date of 2018-03-09
dateAgo('1972-11-30'); // "45Y 3M 9D"
dateAgo('2017-03-09'); // "1Y 0M 0D"
dateAgo('2018-01-09'); // "0Y 2M 0D"
dateAgo('2018-02-09'); // "0Y 0M 28D" -- a little odd, but not wrong
dateAgo('2018-02-01'); // "0Y 1M 5D" -- definitely "feels" wrong
dateAgo('2018-03-09'); // "0Y 0M 0D"
Если ваш вариант использования - это просто строки с датой, то это работает нормально, если вы просто хотите быстрый и грязный 4 лайнер.
Ответ 8
Еще одно решение, основанное на некотором PHP-коде.
Функция strtotime, также основанная на PHP, можно найти здесь: http://phpjs.org/functions/strtotime/.
Date.dateDiff = function(d1, d2) {
d1 /= 1000;
d2 /= 1000;
if (d1 > d2) d2 = [d1, d1 = d2][0];
var diffs = {
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0
}
$.each(diffs, function(interval) {
while (d2 >= (d3 = Date.strtotime('+1 '+interval, d1))) {
d1 = d3;
++diffs[interval];
}
});
return diffs;
};
Использование:
> d1 = new Date(2000, 0, 1)
Sat Jan 01 2000 00:00:00 GMT+0100 (CET)
> d2 = new Date(2013, 9, 6)
Sun Oct 06 2013 00:00:00 GMT+0200 (CEST)
> Date.dateDiff(d1, d2)
Object {
day: 5
hour: 0
minute: 0
month: 9
second: 0
year: 13
}
Ответ 9
Я создал, еще один, для этой цели:
function dateDiff(date) {
date = date.split('-');
var today = new Date();
var year = today.getFullYear();
var month = today.getMonth() + 1;
var day = today.getDate();
var yy = parseInt(date[0]);
var mm = parseInt(date[1]);
var dd = parseInt(date[2]);
var years, months, days;
// months
months = month - mm;
if (day < dd) {
months = months - 1;
}
// years
years = year - yy;
if (month * 100 + day < mm * 100 + dd) {
years = years - 1;
months = months + 12;
}
// days
days = Math.floor((today.getTime() - (new Date(yy + years, mm + months - 1, dd)).getTime()) / (24 * 60 * 60 * 1000));
//
return {years: years, months: months, days: days};
}
Не требует сторонних библиотек. Принимает один аргумент - дату в формате ГГГГ-ММ-ДД.
https://gist.github.com/lemmon/d27c2d4a783b1cf72d1d1cc243458d56
Ответ 10
let startDate = moment(new Date('2017-05-12')); // yyyy-MM-dd
let endDate = moment(new Date('2018-09-14')); // yyyy-MM-dd
let Years = newDate.diff(date, 'years');
let months = newDate.diff(date, 'months');
let days = newDate.diff(date, 'days');
console.log("Year: " + Years, ", Month: " months-(Years*12), ", Days: " days-(Years*365.25)-((365.25*(days- (Years*12)))/12));
Над фрагментом будет напечатан: Год: 1, Месяц: 4, Дней: 2
Ответ 11
У этой ссылки есть лучший ответ
http://forums.asp.net/t/1610039.aspx?How+to+calculate+difference+between+two+dates+in+years
Вам нужно только добавить подтверждение для дней, somthing like:
if (firstDate.getDate() <= now.getDate())
Ответ 12
Очень старая нить, я знаю, но вот мой вклад, поскольку поток еще не решен.
Это требует високосных лет и не требует фиксированного количества дней в месяц или год.
Это может быть ошибочным в пограничных случаях, поскольку я не тестировал его полностью, но он работает на все даты, указанные в исходном вопросе, таким образом, я уверен.
function calculate() {
var fromDate = document.getElementById('fromDate').value;
var toDate = document.getElementById('toDate').value;
try {
document.getElementById('result').innerHTML = '';
var result = getDateDifference(new Date(fromDate), new Date(toDate));
if (result && !isNaN(result.years)) {
document.getElementById('result').innerHTML =
result.years + ' year' + (result.years == 1 ? ' ' : ') +
result.months + ' month' + (result.months == 1 ? ' ' : ') + 'and ' +
result.days + ' day' + (result.days == 1 ? '' : 's');
}
} catch (e) {
console.error(e);
}
}
function getDateDifference(startDate, endDate) {
if (startDate > endDate) {
console.error('Start date must be before end date');
return null;
}
var startYear = startDate.getFullYear();
var startMonth = startDate.getMonth();
var startDay = startDate.getDate();
var endYear = endDate.getFullYear();
var endMonth = endDate.getMonth();
var endDay = endDate.getDate();
// We calculate February based on end year as it might be a leep year which might influence the number of days.
var february = (endYear % 4 == 0 && endYear % 100 != 0) || endYear % 400 == 0 ? 29 : 28;
var daysOfMonth = [31, february, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var startDateNotPassedInEndYear = (endMonth < startMonth) || endMonth == startMonth && endDay < startDay;
var years = endYear - startYear - (startDateNotPassedInEndYear ? 1 : 0);
var months = (12 + endMonth - startMonth - (endDay < startDay ? 1 : 0)) % 12;
// (12 + ...) % 12 makes sure index is always between 0 and 11
var days = startDay <= endDay ? endDay - startDay : daysOfMonth[(12 + endMonth - 1) % 12] - startDay + endDay;
return {
years: years,
months: months,
days: days
};
}
<p><input type="text" name="fromDate" id="fromDate" placeholder="yyyy-mm-dd" value="1999-02-28" /></p>
<p><input type="text" name="toDate" id="toDate" placeholder="yyyy-mm-dd" value="2000-03-01" /></p>
<p><input type="button" name="calculate" value="Calculate" onclick="javascript:calculate();" /></p>
<p />
<p id="result"></p>
Ответ 13
Я лично использовал http://www.datejs.com/, очень удобный. В частности, посмотрите файл time.js: http://code.google.com/p/datejs/source/browse/trunk/src/time.js
Ответ 14
Временной интервал в полные дни, часы, минуты, секунды, миллисекунды:
// Extension for Date
Date.difference = function (dateFrom, dateTo) {
var diff = { TotalMs: dateTo - dateFrom };
diff.Days = Math.floor(diff.TotalMs / 86400000);
var remHrs = diff.TotalMs % 86400000;
var remMin = remHrs % 3600000;
var remS = remMin % 60000;
diff.Hours = Math.floor(remHrs / 3600000);
diff.Minutes = Math.floor(remMin / 60000);
diff.Seconds = Math.floor(remS / 1000);
diff.Milliseconds = Math.floor(remS % 1000);
return diff;
};
// Usage
var a = new Date(2014, 05, 12, 00, 5, 45, 30); //a: Thu Jun 12 2014 00:05:45 GMT+0400
var b = new Date(2014, 02, 12, 00, 0, 25, 0); //b: Wed Mar 12 2014 00:00:25 GMT+0400
var diff = Date.difference(b, a);
/* diff: {
Days: 92
Hours: 0
Minutes: 5
Seconds: 20
Milliseconds: 30
TotalMs: 7949120030
} */
Ответ 15
Ни один из кодов не работает для меня, поэтому я использую это вместо нескольких месяцев и дней:
function monthDiff(d2, d1) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth() + 1;
return months <= 0 ? 0 : months;
}
function daysInMonth(date) {
return new Date(date.getYear(), date.getMonth() + 1, 0).getDate();
}
function diffDate(date1, date2) {
if (date2 && date2.getTime() && !isNaN(date2.getTime())) {
var months = monthDiff(date1, date2);
var days = 0;
if (date1.getUTCDate() >= date2.getUTCDate()) {
days = date1.getUTCDate() - date2.getUTCDate();
}
else {
months--;
days = date1.getUTCDate() - date2.getUTCDate() + daysInMonth(date2);
}
// Use the variables months and days how you need them.
}
}
Ответ 16
Ниже приведен алгоритм, который дает правильный, но не полностью точный, поскольку он не учитывает високосный год. Он также предполагает 30 дней в месяц. Например, хороший пример: если кто-то живет в адресе с 12/11/2010 по 11/10/2011, он может быстро сказать, что человек живет там 10 месяцев и 29 дней. С 12/11/2010 по 11/12/2011 - 11 месяцев и 1 день. Для некоторых типов приложений такая точность является достаточной. Это относится к тем типам приложений, поскольку оно предназначено для простоты:
var datediff = function(start, end) {
var diff = { years: 0, months: 0, days: 0 };
var timeDiff = end - start;
if (timeDiff > 0) {
diff.years = end.getFullYear() - start.getFullYear();
diff.months = end.getMonth() - start.getMonth();
diff.days = end.getDate() - start.getDate();
if (diff.months < 0) {
diff.years--;
diff.months += 12;
}
if (diff.days < 0) {
diff.months = Math.max(0, diff.months - 1);
diff.days += 30;
}
}
return diff;
};
Модульные тесты
Ответ 17
Чтобы рассчитать разницу между двумя датами в Years, Months, Days, Minutes, Seconds, Milliseconds, используя TypeScript/JavaScript
dateDifference(actualDate) {
// Calculate time between two dates:
const date1 = actualDate; // the date you already commented/ posted
const date2: any = new Date(); // today
let r = {}; // object for clarity
let message: string;
const diffInSeconds = Math.abs(date2 - date1) / 1000;
const days = Math.floor(diffInSeconds / 60 / 60 / 24);
const hours = Math.floor(diffInSeconds / 60 / 60 % 24);
const minutes = Math.floor(diffInSeconds / 60 % 60);
const seconds = Math.floor(diffInSeconds % 60);
const milliseconds =
Math.round((diffInSeconds - Math.floor(diffInSeconds)) * 1000);
const months = Math.floor(days / 31);
const years = Math.floor(months / 12);
// the below object is just optional
// if you want to return an object instead of a message
r = {
years: years,
months: months,
days: days,
hours: hours,
minutes: minutes,
seconds: seconds,
milliseconds: milliseconds
};
// check if difference is in years or months
if (years === 0 && months === 0) {
// show in days if no years / months
if (days > 0) {
if (days === 1) {
message = days + ' day';
} else { message = days + ' days'; }
} else if (hours > 0) {
if (hours === 1) {
message = hours + ' hour';
} else {
message = hours + ' hours';
}
} else {
// show in minutes if no years / months / days
if (minutes === 1) {
message = minutes + ' minute';
} else {message = minutes + ' minutes';}
}
} else if (years === 0 && months > 0) {
// show in months if no years
if (months === 1) {
message = months + ' month';
} else {message = months + ' months';}
} else if (years > 0) {
// show in years if years exist
if (years === 1) {
message = years + ' year';
} else {message = years + ' years';}
}
return 'Posted ' + message + ' ago';
// this is the message a user see in the view
}
Однако вы можете обновить приведенную выше логику, чтобы сообщение отображало секунды и миллисекунды, или же использовать объект 'r' для форматирования сообщения так, как вы хотите.
Если вы хотите напрямую скопировать код, вы можете просмотреть мой текст с приведенным выше кодом здесь.
Ответ 18
Я знаю, что это старая нить, но я бы хотел поставить свои 2 цента на основе ответа @Pawel Miech.
Это правда, что вам нужно преобразовать разницу в миллисекунды, тогда вам нужно сделать некоторую математику. Но обратите внимание, что вам нужно сделать математику в обратном порядке, то есть вам нужно рассчитать годы, месяцы, дни, часы и минуты.
Я делал что-то вроде этого:
var mins;
var hours;
var days;
var months;
var years;
var diff = new Date() - new Date(yourOldDate);
// yourOldDate may be is coming from DB, for example, but it should be in the correct format ("MM/dd/yyyy hh:mm:ss:fff tt")
years = Math.floor((diff) / (1000 * 60 * 60 * 24 * 365));
diff = Math.floor((diff) % (1000 * 60 * 60 * 24 * 365));
months = Math.floor((diff) / (1000 * 60 * 60 * 24 * 30));
diff = Math.floor((diff) % (1000 * 60 * 60 * 24 * 30));
days = Math.floor((diff) / (1000 * 60 * 60 * 24));
diff = Math.floor((diff) % (1000 * 60 * 60 * 24));
hours = Math.floor((diff) / (1000 * 60 * 60));
diff = Math.floor((diff) % (1000 * 60 * 60));
mins = Math.floor((diff) / (1000 * 60));
Но, конечно, это не точно, потому что предполагает, что все годы имеют 365 дней, а все месяцы - 30 дней, что неверно во всех случаях.
Ответ 19
Использование самолета Javascript:
function dateDiffInDays(start, end) {
var MS_PER_DAY = 1000 * 60 * 60 * 24;
var a = new Date(start);
var b = new Date(end);
const diffTime = Math.abs(a - b);
const diffDays = Math.ceil(diffTime / MS_PER_DAY);
console.log("Days: ", diffDays);
// Discard the time and time-zone information.
const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
return Math.floor((utc2 - utc1) / MS_PER_DAY);
}
function dateDiffInDays_Months_Years(start, end) {
var m1 = new Date(start);
var m2 = new Date(end);
var yDiff = m2.getFullYear() - m1.getFullYear();
var mDiff = m2.getMonth() - m1.getMonth();
var dDiff = m2.getDate() - m1.getDate();
if (dDiff < 0) {
var daysInLastFullMonth = getDaysInLastFullMonth(start);
if (daysInLastFullMonth < m1.getDate()) {
dDiff = daysInLastFullMonth + dDiff + (m1.getDate() -
daysInLastFullMonth);
} else {
dDiff = daysInLastFullMonth + dDiff;
}
mDiff--;
}
if (mDiff < 0) {
mDiff = 12 + mDiff;
yDiff--;
}
console.log('Y:', yDiff, ', M:', mDiff, ', D:', dDiff);
}
function getDaysInLastFullMonth(day) {
var d = new Date(day);
console.log(d.getDay() );
var lastDayOfMonth = new Date(d.getFullYear(), d.getMonth() + 1, 0);
console.log('last day of month:', lastDayOfMonth.getDate() ); //
return lastDayOfMonth.getDate();
}
Использование moment.js:
function dateDiffUsingMoment(start, end) {
var a = moment(start,'M/D/YYYY');
var b = moment(end,'M/D/YYYY');
var diffDaysMoment = b.diff(a, 'days');
console.log('Moments.js : ', diffDaysMoment);
preciseDiffMoments(a,b);
}
function preciseDiffMoments( a, b) {
var m1= a, m2=b;
m1.add(m2.utcOffset() - m1.utcOffset(), 'minutes'); // shift timezone of m1 to m2
var yDiff = m2.year() - m1.year();
var mDiff = m2.month() - m1.month();
var dDiff = m2.date() - m1.date();
if (dDiff < 0) {
var daysInLastFullMonth = moment(m2.year() + '-' + (m2.month() + 1),
"YYYY-MM").subtract(1, 'M').daysInMonth();
if (daysInLastFullMonth < m1.date()) { // 31/01 -> 2/03
dDiff = daysInLastFullMonth + dDiff + (m1.date() -
daysInLastFullMonth);
} else {
dDiff = daysInLastFullMonth + dDiff;
}
mDiff--;
}
if (mDiff < 0) {
mDiff = 12 + mDiff;
yDiff--;
}
console.log('getMomentum() Y:', yDiff, ', M:', mDiff, ', D:', dDiff);
}
Протестировал вышеуказанные функции, используя следующие образцы:
var sample1 = all('2/13/2018', '3/15/2018'); // {'M/D/YYYY'} 30, Y: 0 , M: 1 , D: 2
console.log(sample1);
var sample2 = all('10/09/2019', '7/7/2020'); // 272, Y: 0 , M: 8 , D: 29
console.log(sample2);
function all(start, end) {
dateDiffInDays(start, end);
dateDiffInDays_Months_Years(start, end);
try {
dateDiffUsingMoment(start, end);
} catch (e) {
console.log(e);
}
}
Ответ 20
Это очень просто, пожалуйста, используйте код ниже, и он даст разницу в этом формате в соответствии с этим //3 года 9 месяцев 3 недели 5 дней 15 часов 50 минут
Date.getFormattedDateDiff = function(date1, date2) {
var b = moment(date1),
a = moment(date2),
intervals = ['years','months','weeks','days'],
out = [];
for(var i=0; i<intervals.length; i++){
var diff = a.diff(b, intervals[i]);
b.add(diff, intervals[i]);
out.push(diff + ' ' + intervals[i]);
}
return out.join(', ');
};
var today = new Date(),
newYear = new Date(today.getFullYear(), 0, 1),
y2k = new Date(2000, 0, 1);
//(AS OF NOV 29, 2016)
//Time since New Year: 0 years, 10 months, 4 weeks, 0 days
console.log( 'Time since New Year: ' + Date.getFormattedDateDiff(newYear, today) );
//Time since Y2K: 16 years, 10 months, 4 weeks, 0 days
console.log( 'Time since Y2K: ' + Date.getFormattedDateDiff(y2k, today) );
Ответ 21
Я наткнулся на это, имея ту же проблему.
Вот мой код.
Он полностью опирается на функцию даты JS, поэтому обрабатываются високосные годы и не сравнивает дни по часам, что позволяет избежать проблем с переходом на летнее время.
function dateDiff(start, end) {
let years = 0, months = 0, days = 0;
// Day diffence. Trick is to use setDate(0) to get the amount of days
// from the previous month if the end day less than the start day.
if (end.getDate() < start.getDate()) {
months = -1;
let datePtr = new Date(end);
datePtr.setDate(0);
days = end.getDate() + (datePtr.getDate() - start.getDate());
} else {
days = end.getDate() - start.getDate();
}
if (end.getMonth() < start.getMonth() ||
(end.getMonth() === start.getMonth() && end.getDate() < start.getDate())) {
years = -1;
months += end.getMonth() + (12 - start.getMonth());
} else {
months += end.getMonth() - start.getMonth();
}
years += end.getFullYear() - start.getFullYear();
console.log('${years}y ${months}m ${days}d');
return [years, months, days];
}