如何降低此功能的圈复杂度?

时间:2018-01-27 18:46:27

标签: javascript

我有一个在时代中占用时间戳的函数(如1517073001)并以简单的格式返回自那时以来经过的时间,例如" 2小时前" (不会像#34; 2小时,31分15秒前那样进一步啰嗦")。

该函数按预期工作,但JSHint抱怨使用太多语句(30)并且其圈复杂度太高(12)。我想知道什么是改善这两个方面的方法。

这是功能:



function msToTime(epoch) {
  var previous = new Date(epoch * 1000);
  var current = Math.floor(new Date().getTime());
  var ms = current - previous;
  var years = parseInt((ms / (1000 * 60 * 60 * 24 * 30 * 12)).toFixed(20), 10);
  var months = parseInt((ms / (1000 * 60 * 60 * 24 * 30) % 12).toFixed(20), 10);
  var days = parseInt((ms / (1000 * 60 * 60 * 24) % 30).toFixed(20), 10);
  var hours = parseInt((ms / (1000 * 60 * 60) % 24).toFixed(20), 10);
  var minutes = parseInt(ms / (1000 * 60) % 60, 10);
  var seconds = parseInt(ms / 1000 % 60, 10);
  var formatted = '';

  if (years > 0) {
    if (years > 1) {
      formatted = years + ' years ago';
    } else {
      formatted = years + ' year ago';
    }
  } else if (months > 0) {
    if (months > 1) {
      formatted = months + ' months ago';
    } else {
      formatted = months + ' month ago';
    }
  } else if (days > 0) {
    if (days > 1) {
      formatted = days + ' days ago';
    } else {
      formatted = days + ' day ago';
    }
  } else if (hours > 0) {
    if (hours > 1) {
      formatted = hours + ' hours ago';
    } else {
      formatted = hours + ' hour ago';
    }
  } else if (minutes > 0) {
    if (minutes > 1) {
      formatted = minutes + ' minutes ago';
    } else {
      formatted = minutes + ' minute ago';
    }
  } else {
    if (seconds > 1) {
      formatted = seconds + ' seconds ago';
    } else {
      formatted = seconds + ' second ago';
    }
  }

  return formatted;
}

var div = document.getElementById('time');
div.innerHTML = msToTime(1517073001);

<div id="time"></div>
&#13;
&#13;
&#13;

提前谢谢你。 :)

4 个答案:

答案 0 :(得分:2)

针对div和模块操作优化的另一个版本

function msToTime(epoch) {
    var value = (Math.floor(new Date().getTime()) - new Date(epoch * 1000)) / 1000;

    var time_factors = [['second', 60], ['minute', 60], ['hour', 24], ['day', 30], ['month', 12], ['year', NaN]];

    for (factor of time_factors) {

        if (value < factor[1] || isNaN(factor[1])) {
            var t = Math.floor(value);
            return t + ' ' + (t > 1 ? factor[0] + 's' : factor[0]) + ' ago';
        }
        value /= factor[1];
    }
}

答案 1 :(得分:1)

if...else if...else if...替换为switch (true)并将单数或复数的构建放入函数中:

&#13;
&#13;
function msToTime(epoch) {
  let previous = new Date(epoch * 1000);
  let current = Math.floor(new Date().getTime());
  let ms = current - previous;
  let years = parseInt((ms / (1000 * 60 * 60 * 24 * 30 * 12)).toFixed(20), 10);
  let months = parseInt((ms / (1000 * 60 * 60 * 24 * 30) % 12).toFixed(20), 10);
  let days = parseInt((ms / (1000 * 60 * 60 * 24) % 30).toFixed(20), 10);
  let hours = parseInt((ms / (1000 * 60 * 60) % 24).toFixed(20), 10);
  let minutes = parseInt(ms / (1000 * 60) % 60, 10);
  let seconds = parseInt(ms / 1000 % 60, 10);
  let formatted = '';

  function timeAgo(count, word) {
    return `${count} ${(count === 1 ? word : word + 's')} ago`
  }
  
  switch (true) {
  case years > 0: 
    formatted = timeAgo(years, 'year')
    break
  case months > 0: 
    formatted = timeAgo(months, 'month')
    break
  case days > 0: 
    formatted = timeAgo(days, 'day')
    break
  case hours > 0: 
    formatted = timeAgo(hours, 'hour')
    break
  case minutes > 0: 
    formatted = timeAgo(minutes, 'minute')
    break
  default: 
    formatted = timeAgo(seconds, 'second')
  }

  return formatted;
}

time.innerHTML = msToTime(1517073001);
&#13;
<div id="time"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

将日期定义为数组并迭代它会将Cyclomatic复杂度数字减少到4(!),只有12个语句。

  function msToTime(epoch) {
    var previous = new Date(epoch * 1000);
    var current = Math.floor(new Date().getTime());
    var ms = current - previous;
    var formatted = '';
    var completeDate = [
      ['year', parseInt((ms / (1000 * 60 * 60 * 24 * 30 * 12)).toFixed(20), 10)],
      ['month', parseInt((ms / (1000 * 60 * 60 * 24 * 30) % 12).toFixed(20), 10)],
      ['day', parseInt((ms / (1000 * 60 * 60 * 24) % 30).toFixed(20), 10)],
      ['hour', parseInt((ms / (1000 * 60 * 60) % 24).toFixed(20), 10)],
      ['minute', parseInt(ms / (1000 * 60) % 60, 10)],
      ['second', parseInt(ms / 1000 % 60, 10)]
    ];

    for (var i = 0; i < completeDate.length; i++) {
      var amount = completeDate[i][1];
      if (amount > 0) {
        var unit = completeDate[i][0];
        formatted = amount + ' ' + (amount > 1 ? unit + 's' : unit) + ' ago';
        break;
      }
    }

    return formatted;
  }

  var div = document.getElementById('time');
  div.innerHTML = msToTime(1517073001);
<div id="time"></div>

感谢@connexo提供重要建议!

答案 3 :(得分:-1)

  function msToTime (epoch) {
    var previous = new Date(epoch * 1000);
    var current = Math.floor(new Date().getTime());
    var ms = current - previous;
    var years = parseInt((ms / (1000 * 60 * 60 * 24 * 30 * 12)).toFixed(20), 10);
    var months = parseInt((ms / (1000 * 60 * 60 * 24 * 30) % 12).toFixed(20), 10);
    var days = parseInt((ms / (1000 * 60 * 60 * 24) % 30).toFixed(20), 10);
    var hours = parseInt((ms / (1000 * 60 * 60) % 24).toFixed(20), 10);
    var minutes = parseInt(ms / (1000 * 60) % 60, 10);
    var seconds = parseInt(ms / 1000 % 60, 10);
    var formatted = '';

    if (years > 0) {
        formatted = years > 1 ? years + ' years ago' : years + ' year ago';

    } else if (months > 0) {
        formatted = months > 1 ? ' months ago' :  ' month ago';
    } else if (days > 0) {
        formatted = days > 1 ? ' days ago' :  ' day ago';
    } else if (hours > 0) {
      formatted = hours > 1 ? ' hours ago' :  ' hour ago';
    } else if (minutes > 0) {
      formatted = minutes > 1 ? ' minutes ago' :  ' minute ago';
    } else {
      formatted = seconds > 1 ? ' seconds ago' :  ' second ago';
    }

    return formatted;
  }

  var div = document.getElementById('time');
  div.innerHTML = msToTime(1417073002);

我使用JS三元运算符来缩短你的代码。希望它有所帮助。