【问题标题】:How to add commas and "and" at the right place如何在正确的位置添加逗号和“和”
【发布时间】:2016-08-16 20:15:46
【问题描述】:

输入:秒,输出:语法正确、格式化的时间(拼出单词)。

到目前为止,我设法从 400443731 year, 98 days, 5 hours, 37 minutes, 1 second - 注意正确的复数和逗号。

我缺少的是添加的“and”而不是最后一个逗号(当然只有在输入足够多的情况下)。例如 1 year and 1 second 输入 31556953 而不是我当前的 1 year, 1 second 在这种情况下。

function formatDuration (seconds) {

var numyears = Math.floor(seconds / 31556952);
if (numyears > 1) {var pluryears = " years, "} else {var pluryears = " year, "};
if (numyears > 0) {var printyears = numyears + pluryears;} else {var printyears = ''};

var numdays = Math.floor((seconds % 31556952) / 86400);
if (numdays > 1) {var plurdays = " days, "} else {var plurdays = " day, "};
if (numdays > 0) {var printdays = numdays + plurdays;} else {var printdays = ''};

var numhours = Math.floor(((seconds % 31556952) % 86400) / 3600);
if (numhours > 1) {var plurhours = " hours, "} else {var plurhours = " hour, "};
if (numhours > 0) {var printhours = numhours + plurhours;} else {var printhours = ''};

var numminutes = Math.floor((((seconds % 31556952) % 86400) % 3600) / 60);
if (numminutes > 1) {var plurminutes = " minutes, "} else {var plurminutes = " minute, "};
if (numminutes > 0) {var printminutes = numminutes + plurminutes;} else {var printminutes = ''};

var numseconds = (((seconds % 31556952) % 86400) % 3600) % 60;
if (numseconds > 1) {var plurseconds = " seconds"} else {var plurseconds = " second"};
if (numseconds > 0) {var printseconds = numseconds + plurseconds;} else {var printseconds = ''};

return(printyears + printdays + printhours + printminutes + printseconds)
}

formatDuration(31556953);

【问题讨论】:

    标签: javascript date time formatting human-readable


    【解决方案1】:

    一个更紧凑的解决方案,按预期输出时间字符串:

    function formatDuration (seconds) {
      var values = {
        years: Math.floor(seconds / 31556952),
        days: Math.floor((seconds % 31556952) / 86400),
        hours: Math.floor(((seconds % 31556952) % 86400) / 3600),
        minutes: Math.floor((((seconds % 31556952) % 86400) % 3600) / 60),
        seconds: (((seconds % 31556952) % 86400) % 3600) % 60,
      };
      var withUnits = Object.keys(values)
      .filter(function(unit) { return values[unit] > 0; })
      .map(function (unit) {
        var value = values[unit];
        return value + ' ' + (value === 1 ? unit.slice(0, -1) : unit);
      });
      return (withUnits.length > 1 ? withUnits.slice(0, -1).join(', ') + ' and ' : '') + withUnits.pop();
    }
    
    console.log(formatDuration(40044373));
    

    【讨论】:

    • 最终这比我的解决方案更好(尽管我会以不同的格式设置它;)
    • 我对 JS 还是很陌生,所以我会仔细检查我是否理解这一点: var x = {a: foo, b: fuu, c: fuh[no trailing逗号在这里,对吗?]} 是设置数组的简写,对吧?在我完全不认识之后发生的事情。 developer.mozilla.org/en/docs/Web/JavaScript/Reference/… 很酷! - 谢谢!
    • (我认为。它做了很多切片和切块,我不确定是否过于清晰。)
    • @Julix 一个对象,而不是一个数组。
    • 整洁。好吧,我想我还有很多阅读要做才能理解那种事情......地图? - 不知道你可以.anything 没有点前面的东西。
    【解决方案2】:

    只是一个替换最后一个逗号的小正则表达式:

    return (printyears + printdays + printhours + printminutes + printseconds)
        .replace(/, (.*)$/, " and $1");
    

    【讨论】:

    • 这有帮助,但如果没有任何秒数(比如 2 分钟),这将替换最后一个逗号,并为输入 120 留下“2 分钟和”。
    【解决方案3】:

    不相关,但呈现的代码很难思考。

    我会将复数位提取到它自己的方法中,大致如下:

    function pluralize(dur, s) {
      var ret = false;
    
      if (dur > 0) {
        ret = dur + ' ' + s;
    
        if (dur > 1) {
          ret += 's';
        }
      }
    
      return ret;
    }
    

    然后是主线代码,而不是手动执行所有操作,而是推入一个数组,例如,

    function formatDuration(seconds) {
      var segments = [];
    
      var years  = Math.floor(seconds / 31556952)
        , sYears = pluralize(years, 'year')
        ;
    
      if (sYears) { 
        segments.push(sYears); 
      }
    
      // etc.
    

    您只需要将seconds 值特殊化:

      var seconds = (((seconds % 31556952) % 86400) % 3600) % 60
        , sSeconds = pluralize(seconds, 'second')
        ;
    
      var tmp = segments.join(', ');
      if (!sSeconds) {
        return tmp;
      }
    
      return tmp + ' and ' + sSeconds;
    }
    

    这可以进一步清理,但会产生如下输出:

    1 year, 2 hours, 46 minutes and 43 seconds
    1 year and 3 seconds
    

    (虽然我更喜欢牛津逗号。)

    我仍然会做的事情:

    • 停止重新计算一切;记录剩余的秒数。
    • 将数组传递到函数中,避免在主线代码中进行人工操作。
      • (或以其他方式包装。)

    https://gist.github.com/davelnewton/a1371867527c5f1530498e1555e2fb0a

    【讨论】:

    • 从github复制并运行它。给我“和 1 秒”持续时间 1。
    • @Julix 所以修复它,这很简单。你知道,SO 不是代码编写服务。
    • 对不起,我之前的评论没有发送(我猜是在不同的选项卡中打开并关闭)-我真的很喜欢你的回答。我了解更多这里发生的事情,我很感谢你发布它。但是,它并不能解决我在这些情况下不知道如何摆脱 and 的问题。 Oliver 的另一个解决方案现在确实做到了,但它使用了比这个解决方案更多的东西,我不明白,这就是为什么我很好奇你会如何尝试摆脱和在所有情况下,但在需要时。
    • 并不是说我有权满足这种好奇心,只是说我仍然感兴趣。
    • @Julix 只需检查一个空数组:)
    【解决方案4】:

    我正是为此目的编写了一个小型库:

    https://github.com/adamshaylor/compound-subject

    在你的情况下,你会像这样使用它:

    var formattedTimeString = compoundSubject([
        numyears + 'years',
        numdays + 'days',
        numhours + 'hours',
        numminutes + 'minutes',
        numseconds + 'seconds'
    ]).make();
    

    产生类似的东西:

    2年5天3小时10分2秒

    您还可以通过调用delimitAll() 添加牛津逗号。

    【讨论】:

      【解决方案5】:

      您只需要在退货中添加“和”即可。

      return(printyears + printdays + printhours + printminutes + 'and' + printseconds)
      

      并删除此行中“分钟”后的逗号

      if (numminutes > 1) {var plurminutes = " minutes "} else {var plurminutes = " minute "};
      

      【讨论】:

      • 除非我遗漏了一些东西,否则即使你只有 1 秒,它也会打印出来,对吗? - 这还不够好。
      • 也会导致 1 年 1 秒(而不是 1 年 1 秒,我想要)
      • 你是对的。在这种情况下,您可以将逗号放在下一个“元素”之前。像这样:而不是“年,”,使用“,日”。
      • 你不能使用 ", day" 因为 numday 仍然必须在 day 前面。
      • 是的,你是对的。对不起这个错误。在这种情况下,您可以将变量放在逗号和“天”之间。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-06
      • 1970-01-01
      • 2016-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多