#javascript #algorithm
#javascript #алгоритм
Вопрос:
Какой самый простой способ в Javascript вычислить количество юбилеев между двумя датами.
Моя попытка:
module.exports.countAnniversariesBetweenTwoDates = (start_date, end_date, anniversary_date) => {
if (start_date == end_date) {
return 0;
}
let start_date_year = start_date.getFullYear();
let end_date_year = end_date.getFullYear();
let anniversary_year = anniversary_date.getFullYear();
let start_date_month_and_day = Number(('0' (start_date.getMonth() 1)).slice(-2) '' ('0' start_date.getDate()).slice(-2));
let end_date_month_and_day = Number(('0' (end_date.getMonth() 1)).slice(-2) '' ('0' end_date.getDate()).slice(-2));
let anniversary_date_month_and_day = Number(('0' (anniversary_date.getMonth() 1)).slice(-2) '' ('0' anniversary_date.getDate()).slice(-2));
let anniversary_count = 0;
// special case for start year
if (start_date_month_and_day < anniversary_date_month_and_day) {
anniversary_count ;
}
let temp_start_date_year = start_date_year 1;
while(temp_start_date_year < end_date_year) {
anniversary_count ;
temp_start_date_year ;
}
// special case for end year
if (end_date_month_and_day > anniversary_date_month_and_day) {
anniversary_count ;
}
return anniversary_count;
}
Комментарии:
1. Почему бы просто не преобразовать обе даты в миллисекунды и получить количество целых лет между ними?
2. Почему мне кажется, что для этого есть однострочное решение, ха-ха?
3. @MattMorgan Это может быть неточно, поскольку вы не учитываете високосные годы этим методом. Если пара часов не имеет большого значения, это замечательно. (Кроме того, не обе даты — достаточным условием будет количество целых лет между максимальной датой начала и годовщиной этого года и датой окончания.)
4. Вычтите годы, затем добавьте / вычтите 1 в зависимости от того, где дата годовщины попадает в диапазон. Что-то вроде
end_year - start_year ( start_day_of_year < anniv_day_of_year ? -1 : 0) (end_day_of_year <= anniv_day_of_year ? 1 : 0)
5. я думаю, что решение @xdhmoore выглядит правильным!
Ответ №1:
Вот один, который учитывает високосные годы:
function validDate(year, month, day) {
var testDate = new Date(year, month, day);
return testDate.getFullYear() === year amp;amp; testDate.getMonth() === month amp;amp; testDate.getDate() === day;
}
function countAnniversaries(begin, end, anniversary) {
var countDate = new Date(anniversary.getTime());
var anniversaries = 0;
var countYear = begin.getFullYear();
var anniversaryMonth = anniversary.getMonth();
var anniversaryDay = anniversary.getDate();
countDate.setFullYear(countYear);
while (countDate.getTime() <= end.getTime()) {
if (validDate(countYear, anniversaryMonth, anniversaryDay) amp;amp; countDate.getTime() >= begin.getTime()) {
anniversaries ;
}
countYear ;
countDate.setFullYear(countYear);
countDate.setMonth(anniversaryMonth);
countDate.setDate(anniversaryDay);
}
return anniversaries;
}
console.log(countAnniversaries(new Date('Feb 1, 2012'), new Date('Feb 4, 2026'), new Date('Feb 2, 2012')))
console.log(countAnniversaries(new Date('Feb 1, 2012'), new Date('Feb 4, 2026'), new Date('Feb 29, 2012')))
Комментарии:
1. это юбилей?
var countDate = new Date(begin.getTime());
2. Это дата, которая потенциально является годовщиной — она устанавливается, а затем проверяется, предшествует ли она дате окончания
3. но мне нужно знать, сколько раз определенный день / месяц (годовщина) встречается в диапазоне дат. т.е. нужно передать 3 параметра функции
start_date, end_date and anniversary_date
4. отредактировано …
countAnniversaries
теперь принимает дату годовщины (игнорируя год)5. Если вы спрашиваете, почему это
3
вместо14
, это потому, что он учитывает только 29 февраля в високосные годы… если вы спрашиваете, почему это3
вместо4
, это потому, что юбилей открыт для интерпретации… Я отредактировал ответ, чтобы подсчитать год начала
Ответ №2:
Если вы используете moment.js вы можете просто получить разницу между двумя датами в виде лет, используя Math.floor() для округления в меньшую сторону до ближайшего полного числа лет.:
yearDiff = Math.floor(moment(new Date(endDate)).diff(new Date(startDate),'years'));
Редактировать: приведенный выше код можно упростить немного больше:
yearDiff = moment(endDate).diff(startDate,'years');
Возможно, вам придется написать дополнительный код для обработки периодов времени менее года или некоторых других особых случаев.
Вы могли бы, конечно, перебирать даты, похожие на то, как вы это делаете:
var startDate = "03/08/2019";
var endDate = "01/01/2022";
var anniversary = "03/07/2015";
var anniversaryCount = 0;
var counterMoment = moment(startDate);
while (counterMoment.isSameOrBefore(endDate)) {
var anniversaryThisYear = moment(anniversary).year(counterMoment.year());
if (counterMoment.isSame(anniversaryThisYear)) {
anniversaryCount ;
}
counterMoment.add(1,'day');
}
alert("Number of anniversaries: " anniversaryCount);
Все зависит от того, каков конечный результат и как вы планируете использовать значение.
Комментарии:
1. решение не использует дату годовщины, или я запутался !?!
2. Если ваш период времени превышает год, он должен быть довольно точным, но, конечно, будут некоторые особые случаи, когда это не даст вам правильного результата. Я обновил свой ответ кодом, который будет перебирать даты, аналогичные тому, что вы делаете.