Используя .date () в JS, чтобы вычислить разницу между двумя датами, что я делаю неправильно? - PullRequest
1 голос
/ 28 января 2011

Вторая половина дня

Я рассчитываю разницу между двумя датами, используя JS. Я пытаюсь получить результат с точностью до секунды. Я очень хорошо с этим справлялся, но заметил проблему. Первые две даты, показанные ниже, показывают разницу в 5 лет, но как только я добавляю еще один год к будущей дате, она показывает 5 лет, 1 день. Откуда прибывает дополнительный день? Когда будущая дата достигает 2020 года, это добавляет еще один день к результату, это повторяющийся шаблон. Может ли кто-нибудь просветить меня? У меня пока нет никаких расчетов високосного года, я поместил свой код ниже:

$(document).ready(function(){

    var todaysDate = new Date('2010/11/24 23:00:00');   
    var futureDate = new Date('2020/11/24 22:59:00');

    calculateTime(todaysDate,futureDate);
});

function calculateTime(todaysDate,futureDate){  
    var difference = futureDate.getTime() - todaysDate.getTime(); 

    var years = Math.floor(difference/1000/60/60/24/365);
        difference -= years*1000*60*60*24*365;

    var days = Math.floor(difference/1000/60/60/24);
        difference -= days*1000*60*60*24;

    var hours = Math.floor(difference/1000/60/60);
        difference -= hours*1000*60*60;

    var minutes = Math.floor(difference/1000/60);
        difference -= minutes*60*1000;

    var seconds = Math.floor(difference/1000);

    var result = years + ' Years, ';
        result += days + ' Days, ';
        result += hours + ' Hours, ';
        result += minutes + ' Minutes, ';
        result += seconds + ' Seconds';

    $('#time').html(result)
 }

Ответы [ 3 ]

4 голосов
/ 28 января 2011

Да, 2020 год високосный, поэтому, если ваш первоначальный тест был на 2010-2019 годы, то вы пробуете 2010-2020, есть дополнительный день из-за високосного года. Даже если вы явно не обрабатываете високосные годы, объект даты Javascript учитывает високосный год, поэтому разница будет заключаться в дополнительном дне в секундах.

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

1) 2010/11/24 -> 2020/02/28
2) 2010/11/24 -> 2020/03/01

В результате вы получите 86,400,000 различий.

0 голосов
/ 29 марта 2011

Самая большая ошибка в том, что вы не написали набор тестов:

  1. Чтобы проверить пограничный случай, который вы знаете во время разработки
  2. Чтобы позже легко проверить другой обнаруженный пограничный случай
  3. Тестируемый код обычно более модульный (см. Ниже фиктивный объект Я должен был создать, чтобы обойти сильную связь вашей функции с jQuery: было бы проще, если бы вызов jQuery былиз calculateTime)

Это называется разработка на основе тестирования .

Теперь вот еще несколько ошибок, которые янайдено:

  1. Ваш формат строки даты не соответствует спецификации .Ваша система понимает ваш формат, но некоторые могут этого не делать.
  2. В ваших строках даты не указан часовой пояс, поэтому у вас возникнут проблемы с локалью, для которых предусмотрено летнее время.
  3. Ваша функция даст вам эффективную работуистекшее время, но это может быть не то, что интересует ваших пользователей. В частности, когда используется летнее время: у вас может быть + 1 / -1 час.

Вот набор тестов, который работает отприглашение командной строки Windows (используйте cscript testsuite.js для его запуска):

// jQuery mock object for calculateTime testing
// $('#time').html(result) => result is stored in $.result
var $ = (function() {
    var $, $$ = {
        html: function(result) {
            $.result = result
        }
    }
    return $ = function(ignore) {
        return $$
    }
})();

// Henryz's unmodified function
function calculateTime(todaysDate,futureDate) {
    var difference = futureDate.getTime() - todaysDate.getTime(); 

    var years = Math.floor(difference/1000/60/60/24/365);
        difference -= years*1000*60*60*24*365;

    var days = Math.floor(difference/1000/60/60/24);
        difference -= days*1000*60*60*24;

    var hours = Math.floor(difference/1000/60/60);
        difference -= hours*1000*60*60;

    var minutes = Math.floor(difference/1000/60);
        difference -= minutes*60*1000;

    var seconds = Math.floor(difference/1000);

    var result = years + ' Years, ';
        result += days + ' Days, ';
        result += hours + ' Hours, ';
        result += minutes + ' Minutes, ';
        result += seconds + ' Seconds';

    return $('#time').html(result)
}

function test(a, b, expected) {
    var toString = Object.prototype.toString;
    if (toString.apply(a) != '[object Date]') a = new Date(a);
    if (toString.apply(b) != '[object Date]') b = new Date(b);
    calculateTime(a, b);
    var got = $.result;
    WScript.Echo(
        got === expected
        ? "ok"
        : "not ok - ["+a.toString()+"] to ["+b.toString()+"]\r\n#      Got: "+got+"\r\n# Expected: "+expected
    );
}

test('2010/11/24 23:00:00', '2011/11/24 23:00:00', '1 Years, 0 Days, 0 Hours, 0 Minutes, 0 Seconds');
test('Nov 24, 2010 23:00:00', 'Nov 24, 2011 23:00:00', '1 Years, 0 Days, 0 Hours, 0 Minutes, 0 Seconds');
test('2010/11/24 23:00:00', '2020/11/24 22:59:00', '10 Years, 0 Days, 0 Hours, 0 Minutes, 0 Seconds');
test('2011/03/26 23:00:00', '2011/03/27 23:00:00', '0 Years, 1 Days, 0 Hours, 0 Minutes, 0 Seconds');
test('2010/10/30 23:00:00', '2010/10/31 23:00:00', '0 Years, 1 Days, 0 Hours, 0 Minutes, 0 Seconds');

Вот мой вывод (смещение локального часового пояса (Франция) изменилось на 2010-10-31 и 2011-03-26):

ok
ok
not ok - [Wed Nov 24 23:00:00 UTC+0100 2010] to [Tue Nov 24 22:59:00 UTC+0100 2020]
#      Got: 10 Years, 2 Days, 23 Hours, 59 Minutes, 0 Seconds
# Expected: 10 Years, 0 Days, 0 Hours, 0 Minutes, 0 Seconds
not ok - [Sat Mar 26 23:00:00 UTC+0100 2011] to [Sun Mar 27 23:00:00 UTC+0200 2011]
#      Got: 0 Years, 0 Days, 23 Hours, 0 Minutes, 0 Seconds
# Expected: 0 Years, 1 Days, 0 Hours, 0 Minutes, 0 Seconds
not ok - [Sat Oct 30 23:00:00 UTC+0200 2010] to [Sun Oct 31 23:00:00 UTC+0100 2010]
#      Got: 0 Years, 1 Days, 1 Hours, 0 Minutes, 0 Seconds
# Expected: 0 Years, 1 Days, 0 Hours, 0 Minutes, 0 Seconds

Таким образом, вы должны полностью переписать функцию или лучше, использовать существующую, протестированную реализацию.

0 голосов
/ 28 января 2011

Да, проблема в високосных годах. Ваша линия

var years = Math.floor(difference/1000/60/60/24/365);

не вычисляет разницу в количестве лет между двумя датами, а вместо этого вычисляет количество 365-дневных периодов между ними

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...