2016-02-14 3 views
0

Функция пытается финансировать разницу между датами, но я изо всех сил стараюсь не возвращать отрицательное число, если дата прошла мимо определенной точки. Я пробовал несколько работ, как использование ABS, но это может вызвать проблемы в будущих областях.Как заставить эту функцию не возвращать отрицательную дату?

var DateCalc = {}; 
 

 
DateCalc.totalDaysLeft = 0; 
 

 
DateCalc.calculate = function(dateToParse) { 
 
    DateCalc.init(dateToParse); 
 
    return DateCalc.stringify(DateCalc.years(), DateCalc.months(), DateCalc.days()); 
 
}; 
 

 
DateCalc.init = function(dateToParse) { 
 
    var date = DateCalc.parseDate(dateToParse); 
 
    var today = Date.now(); 
 
    var oneDay = 24 * 60 * 60 * 1000; 
 
    DateCalc.totalDaysLeft = Math.floor((date - today)/oneDay); 
 
}; 
 

 
DateCalc.parseDate = function(dateToParse) { 
 
    var dateVars = dateToParse.split(',').map(Number); 
 
    return new Date(dateVars[0], dateVars[1] - 1, dateVars[2]); 
 
}; 
 

 
DateCalc.years = function() { 
 
    var years = Math.floor(DateCalc.totalDaysLeft/365); 
 
    DateCalc.totalDaysLeft -= Math.floor(years * 365); 
 
    return years; 
 
}; 
 

 
DateCalc.months = function() { 
 
    var months = Math.floor(DateCalc.totalDaysLeft/30); 
 
    DateCalc.totalDaysLeft -= Math.floor(months * 30); 
 
    return months; 
 
}; 
 

 
DateCalc.days = function() { 
 
    return Math.floor(DateCalc.totalDaysLeft/24); 
 
}; 
 

 
DateCalc.stringify = function(years, months, days) { 
 
    var dateString = ""; 
 

 
    if (years !== 0) 
 
    dateString += years + " years, "; 
 
    if (months !== 0) 
 
    dateString += months + " months, "; 
 
    dateString += days + " day(s)."; 
 

 
    return dateString; 
 
}; 
 

 
//here is the .abs() code. 
 

 

 
function age(year, month, day) { 
 
    var yearDifference = Math.abs(new Date().getFullYear() - year); 
 
    var monthDifference = Math.abs(new Date().getMonth() - month + 1); 
 
    var dayDifference = Math.abs(new Date().getDate() - day); 
 

 
    var differences = { 
 
    year: yearDifference, 
 
    month: monthDifference, 
 
    day: dayDifference 
 
    }; 
 
    var final = []; 
 

 
    for (var time in differences) { 
 
    if (differences[time] > 0) { 
 
     var addString = differences[time] + " " + time; 
 
     if (differences[time] > 1) { 
 
     addString += "s" 
 
     } 
 
     final.push(addString); 
 
    } 
 
    } 
 
    return final.join(" "); 
 
}; 
 
console.log(age(2017, 11, 17)); 
 
console.log(age(2016, 1, 2));

// если вы пытались посмотреть, как далеко в январе следующего года в то время как вы находитесь в декабре, он расскажет вам, что 1 год 11 месяцев теперь вместо 1 месяц , Это потому, что он добавляет 11 месяцев вместо того, чтобы вычитать его. Я пытаюсь найти решение, поскольку эта функция более узкая, а другая - более универсальная. Функция выше, я заменил .floor() раундами значение вниз с .abs(), надеясь, что он просто будет использовать абсолютное значение данной операции, однако это было не так.

+0

использовать 'Math.abs (num)', чтобы получить абсолютное значение –

+0

Не могли бы вы вывести несколько примеров ожидаемого результата? – Amnon

+0

Я пробовал использовать Math.abs (num), однако мне сказали: «Метод абсолютного значения имеет ошибки, которые становятся более заметными по мере того, как год продолжается. Например, если вы попытались посмотреть, как далеко в следующем январе, re в декабре, он скажет вам, что через 1 месяц 11 месяцев вместо 1 месяца это будет 1 год, потому что он добавляет 11 месяцев вместо вычитания. Фактически вы можете увидеть эту ошибку в работе сейчас, пытаясь получить сумму времени до декабря прошлого года ». – thecommunictycodeguy

ответ

1

Проблема в том, что вы используете функцию .abs() ненадлежащим образом. Большинство математических функций не подчиняются дистрибутивному правилу, и к ним принадлежит функция .abs(). Для более легкого понимания давайте забудем вашу текущую проблему на мгновение и рассмотрим простой, приведенный пример:

Предположим, вы хотите знать абсолютное значение -10. Очевидно, что правильный результат равен +10.

С другой стороны, -10 может быть записано как (-20 + 10). Но, тем не менее, вы можете не вычислить абс (-10), используя эти знания:

абс (-20 + 10) = 10, но абс (-20) + ABS (+10) = 30

Применяя эти знания к вашей проблеме, мы видим, что abs (Y years + M months + D days) обычно не равен (abs (Y лет) + abs (M месяцев) + abs (D дней)).

В связи с этой проблемой существует дополнительная странность, заключающаяся в том, что каждый из членов результата имеет другую единицу и что члены зависят друг от друга (например, не может быть термина типа 13 месяцев), поскольку это будет «1 год плюс 1 месяц»), но я не буду вдаваться в подробности здесь.

Существует простое решение:

1) Определите желаемое разрешение вашего результата (т.е. если ваш результат будет с точностью до секунды, аттосекунды, дней или что-то еще).

2) Преобразование двух дат в устройство, определенное на шаге 1), используя случайно выбранную, но неподвижную точку во времени в качестве общей начальной точки.

3) Теперь вы можете вычесть две (конвертированные) даты и использовать функцию .abs() без проблем.

4) Преобразуйте результат обратно в человекообразную форму.

Как вы это делаете на практике? Ну, шаги 1), 3) и 4) легки, но как насчет шага 2)?

Почти каждая OS, которую я знаю (и, следовательно, почти каждый язык программирования), делает преобразование, необходимое для шага 2) для вас. Чаще всего фиксированный момент времени - это период с 1970 по 01:00 00:00:00, а язык ОС/программирования предоставляет процедуры для преобразования любой даты/времени в число секунд (или какой-либо другой единицы), которые истекли так как эта неподвижная точка.

Например, в JavaScript функция myDate.getTime() возвращает число миллисекунд, прошедшее с 1970-01-01 года до myDate.

Так конвертируйте обе даты в «миллисекунды с 1970-01-01» и вычтите их. Используйте функцию .abs() для результата. Затем у вас есть желаемый временной интервал как значение положительных миллисекунд. Преобразовать его обратно в читаемую форму, то есть годы, месяцы и дни (что не является проблемой, так?)

Второе простое решение (только для избежания отрицательных результатов):

Я надеюсь, что вы согласитесь со мной, что , сравнивая, две даты намного проще, чем вычислять разницу между ними (сначала сравните год, если годы отличаются, вы, несомненно, нашли «большую» дату, если годы равны, делайте то же самое с месяцев и т. д.). Затем обменять две даты, если это необходимо. Таким образом, вы всегда можете убедиться, что вы вычитаете «меньшую» дату из «более высокой» даты и что результат всегда будет положительным.

Но учтите, что даже при этом все же будут отрицательные результаты в части расчета при фактическом вычитании дат, поэтому при использовании функции .abs() у вас будут одинаковые проблемы.

Более сложное решение:

Вы могли бы сделать вычитании себя хорошо, но тогда функция .abs() не поможет вам много. Один из алгоритмов, о которых я могу думать, может работать как вычитание, которое делается вручную (я имею в виду вычитание нормальных чисел, которые вы изучили в школе):

Начните с наименее значимого устройства (например, дней). Вычтите дни; если результат отрицательный, то добавьте 28, 29, 30 или 31 (в зависимости от месяца) и сделайте перенос в месяцы, в противном случае сохраните результат; то делайте то же самое с месяцами и так далее. Но, как я уже писал в своем комментарии, во время этого есть много подводных камней (високосные годы, месяцы имеют разные числа дней и т. Д.), А функция .abs() не поможет вам здесь.

Вывод:

Лично я предпочел бы первый (простой) решение, которое я даю. Это легко, понятно и перспективно.

+0

Большое спасибо за ваш ответ. Более простое решение - это именно то, к чему я пошел, и я смог переписать его и получить желаемый результат. Спасибо за отличную обратную связь @Binarus, вы должны научить класс. – thecommunictycodeguy

+0

Ничего. Если бы это помогло, было бы неплохо, если бы вы могли пометить мой ответ как принятый ответ ... И продолжайте - пробовать самые простые вещи и (только для упражнений, а не для производства), используя собственную функцию, а не библиотеки, вы получите глубокое понимание того, что происходит за кулисами при использовании библиотек. – Binarus

+0

У меня только 14 репутации на данный момент, как только я доберусь до 15, я отвечу ваш ответ. Спасибо за подсказку, и я надеюсь, что это так, поэтому мое понимание станет глубже. Слава богу за все эти удивительные библиотеки? – thecommunictycodeguy

0

//initial variables 
 

 
var today = new Date(); 
 
var day = today.getDate(); 
 
var month = today.getMonth() + 1; 
 
var year = today.getFullYear(); 
 
var otherDate = new Date(); 
 
var day2 = 0; 
 
var month2 = 0; 
 
var year2 = 0; 
 

 

 

 
if (day < 10) { 
 
    day = '0' + day; 
 
} 
 

 
if (month < 10) { 
 
    month = '0' + month; 
 
} 
 

 
function age(day2, month2, year2) { 
 
    dayConv = day2; 
 
    monthConv = month2; 
 
    yearConv = year2; 
 
    newDate = day - dayConv; 
 
    newMonth = month - monthConv; 
 
    newYear = year - yearConv; 
 
} 
 

 
function mathDate() { 
 
    if (newYear >= 1) { 
 
    if (newMonth >= 1) { 
 
     if (newDate >= 1) { 
 
     console.log(newYear + " years and " + newMonth + " months and " + newDate + " days."); 
 
     return newYear + " years and " + newMonth + " months and " + newDate + " days."; 
 
     } else if (newDate <= 0) { 
 
     console.log(newYear + " years and " + newMonth + " months."); 
 
     return newYear + " years and " + newMonth + " months."; 
 
     } 
 
    } else if (newMonth <= 0) { 
 
     console.log(newYear + " years and " + newDate + " days."); 
 
     return newYear + " years and " + newDate + " days."; 
 
    } 
 
    } else if (newYear <= 1) { 
 
    if (newMonth >= 1) { 
 
     console.log(newMonth + " months and " + newDate + " days."); 
 
     return newMonth + " months and " + newDate + " days."; 
 
    } else if (newDate <= 0) { 
 
     console.log(newMonth + " months."); 
 
     return newMonth + " months."; 
 
    } else if (newMonth <= 0) { 
 
     console.log(newDate + " days."); 
 
     return newDate + " days."; 
 
    } 
 

 
    } 
 
} 
 

 
age(13, 4, 2016); 
 
mathDate();

Вот ответ, который я был в состоянии создать.

Смежные вопросы