【问题标题】:jQuery Datatables column sum() of hh:mm:sshh:mm:ss 的 jQuery 数据表列 sum()
【发布时间】:2016-09-22 20:26:17
【问题描述】:

我正在使用 jQuery 数据表,我需要对时间 (hh:mm:ss) 列求和。

我正在使用 sum() 插件 (https://cdn.datatables.net/plug-ins/1.10.11/api/sum%28%29.js) 添加列数据,但我并不真正了解它是如何工作的。

        var time_api = this.api();
        //total
        var total = time_api.column(3)
                .data()
                .sum();           
            
        //footer
        $(time_api.column(3)
            .footer())
            .html(total);

这给了我一个总和的输出,但它需要一些调整,而且我不知道如何转换它

变成这个:12:03:05(正确的和输出)。

请帮忙。

【问题讨论】:

    标签: javascript jquery time datatables momentjs


    【解决方案1】:
    <script type="text/javascript" language="javascript">
    
    var table = $('#example').DataTable({
    "footerCallback": function ( row, data, start, end, display ) {
        var api = this.api(), data;
        // Total over all pages
        total_ID = api.column(0).data().reduce( function (a, b) {
            return ~~a + ~~b;
        }, 0 );
        total_Duration = api.column(1).data().reduce( function (a, b) {
            return moment.duration(a).asMilliseconds() + moment.duration(b).asMilliseconds();
        }, 0 );
        // Total over this page
        pageTotal_ID = api.column(0, { page: 'current'} ).data().reduce( function (a, b) {
            return ~~a + ~~b;
        }, 0 );
        pageTotal_Duration = api.column(1, { page: 'current'} ).data().reduce( function (a, b) {
            return moment.duration(a).asMilliseconds() + moment.duration(b).asMilliseconds();
        }, 0 );
        // Update footer Column "quantita"
        $( api.column(0).footer()).html(
            pageTotal_ID + ' ('+ total_ID +' total)'
        );
        $( api.column(1).footer()).html(
            moment.utc(pageTotal_Duration).format("HH:mm:ss") + ' ('+ moment.utc(total_Duration).format("HH:mm:ss") + ' total)'
        );
    }   
    });
    </script>
    

    【讨论】:

    • 你能添加一些描述吗?
    【解决方案2】:

    正如您在plugin source 中看到的,它首先将字符串单元格内容转换为数字,然后执行加法。您应该通过解析格式化值 HH:MM:SS(例如通过正则表达式)来扩展单元格值的处理,然后将其转换为以秒为单位的时间间隔(HH*24+MM*60+SS),然后总结这些值,然后将其转换回小时/分钟/秒。

    你可以像这样更新sum函数:

    jQuery.fn.dataTable.Api.register( 'sum()', function ( ) {
        return this.flatten().reduce( function ( a, b ) {
    
            var timeRegexp = /^(\d{2}):(\d{2}):(\d{2})$/
    
            var matches = a.match(timeRegexp);
            if (matches) {
                var hh = matches[1], mm = matches[2], ss = matches[3];
                var intervalAsSeconds = hh * 24 + mm * 60 + ss;
                return b + intervalAsSeconds;
            }
    
            if ( typeof a === 'string' ) {
                a = a.replace(/[^\d.-]/g, '') * 1;
            }
            if ( typeof b === 'string' ) {
                b = b.replace(/[^\d.-]/g, '') * 1;
            }
    
            return a + b;
        }, 0 );
    } );
    

    要将总和(以秒为单位)转换回 HH:MM:SS,您可以使用以下函数:

    function secondsToTime(seconds) {
      var hours = Math.floor(seconds / 3600);
      var minutes = Math.floor((seconds % 3600) / 60); 
      var seconds = Math.floor(seconds % 60);
      return (hours < 10 ? "0" + hours : hours) + ":" + 
             (minutes < 10 ? "0" + minutes : minutes) + ":" + 
             (seconds < 10 ? "0" + seconds : seconds);
    }
    

    一些反向转换的例子:

    console.log(secondsToTime(45)) // 00:00:45
    console.log(secondsToTime(125)) // 00:02:05
    console.log(secondsToTime(3600)) // 01:00:00
    console.log(secondsToTime(3725)) // 01:02:05
    

    【讨论】:

    • 所以你说将数字拆分为 11:62:65,然后创建公式以使输出看起来像 12:03:05?你有任何可以让我开始的代码sn-p吗?谢谢!
    • 答案已更新(将单元格值转换为秒并返回 HH:MM:SS)。这是普通的javascript,我相信你也可以使用moment.js的一些辅助函数(因为你在标签中提到过)来更容易地处理间隔。
    • @Alexey 上面的代码将错误抛出为 TypeError: a.match is not a function。有什么解决办法吗?
    • @Steffi datatables api 可能会更改,因此 this.flatten()... 可能会返回集合以外的其他内容 请在调用 .match() 之前检查它的类型和 a 的类型,预计会是一个字符串。
    【解决方案3】:

    此方案适配Pranav C Balans 's answer

            var time_api= this.api();
    
            var total= tempo.column(3)
                    .data()
                    .sum();            
            total= total.toString();       
            while (total.length < 6){
               tempoTotal = "0" + tempoTotal   
            }    
    
            total= total.replace(/^(\d+)(\d{2})(\d{2})$/, function(m, m1, m2, m3) {
                m1 = Number(m1); // convert captured group value to number
                m2 = Number(m2);
                m2 += parseInt(m3 / 60, 10); // get minutes from second and add it to minute
                m3 = m3 % 60; // get soconds
                m1 += parseInt(m2 / 60, 10); // get minutes from minute and add it to hour
                m2 = m2 % 60; // get minutes
                // add 0 to minute and second if single digit , slice(-2) will select last 2 digit
                return m1 + ':' + ('0' + m2).slice(-2) + ':' + ('0' + m3).slice(-2); // return updated string
            })
    
            //write in footer
            $(tempo.column(3)
                .footer())
                .html(total);
    

    【讨论】:

    • 如果你不想添加 sum js 和 api() 那么它可以通过没有 api 的 javascript。
    【解决方案4】:

    在这种情况下我会有点棘手。使用time 创建一个隐藏列,但仅使用seconds。现在我可以使用此列计算total 并将其转换回我需要的任何格式。

        $('#tblTime').DataTable({
        "footerCallback": function (row, data, start, end, display) {
    
            var api = this.api();
    
            //convert seconds to hour:minute:seconds
            var secondsToHms = function(d) {
              d = Number(d);
              var h = Math.floor(d / 3600);
              var m = Math.floor(d % 3600 / 60);
              var s = Math.floor(d % 3600 % 60);
    
              return h + ":" + m + ":" + s;
            };
    
            //sum of hidden colunm hours in seconds
            var sum_hours_estimated = api
              .column( 2 ) //hidden column
              .data()
              .reduce( function (a, b) {
                  return intVal(a) + intVal(b);
            }, 0 );
    
            //covert the seconds into hour.minute
            var hours_estimated = secondsToHms(sum_hours_estimated);   
    
            var summary = '<ul><li>Total Time ' + hours_estimated + '</li><ul>';
            $(api.column(1).footer()).html(summary);
        },
        //hide the column
        "columnDefs": [
            {
                "targets": [ 2 ],
                "visible": false,
                "searchable": false
            }
        ]
    });
    
    //Use this if "columnDefs" doesn't work
    $('#tblTime').DataTable().column( 2 ).visible( false );
    

    【讨论】:

      【解决方案5】:

      我遇到了同样的问题,我找到了适合我的解决方案:

      footerCallback: function ( row, data, start, end, display ) {
              var api = this.api(), data;
      
              var intVal = function ( i ) {
                  return i != null ? moment.duration(i).asSeconds() : 0;
              };
      
              var total = api.column( 3 ).data()
                  .reduce( function (a, b) {
                  var total = intVal(a) + intVal(b);
                  var totalFormatted = [
                      parseInt(total / 60 / 60),
                      parseInt(total / 60 % 60),
                      parseInt(total % 60)
                  ].join(":").replace(/\b(\d)\b/g, "0$1");
                  return totalFormatted;
              }, 0 );
      
              jQuery(api.column( 3 ).footer()).html(total);
          }
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-21
        • 1970-01-01
        • 2013-05-18
        • 2018-03-25
        • 1970-01-01
        • 1970-01-01
        • 2017-07-23
        • 1970-01-01
        相关资源
        最近更新 更多