如何使用JavaScript将秒转换为HH-MM-SS字符串?


当前回答

对于任何使用AngularJS的人来说,一个简单的解决方案是使用date API来过滤值,它会根据请求的格式将毫秒转换为字符串。例子:

<div>Offer ends in {{ timeRemaining | date: 'HH:mm:ss' }}</div>

请注意,这需要毫秒,所以如果从秒转换(就像最初的问题一样),可能需要将timerremain乘以1000。

其他回答

我认为最普遍(也是最神秘)的解决方案可能是这样的

function hms(seconds) {
  return [3600, 60]
    .reduceRight(
      (pipeline, breakpoint) => remainder =>
        [Math.floor(remainder / breakpoint)].concat(pipeline(remainder % breakpoint)),
      r => [r]
    )(seconds)
    .map(amount => amount.toString().padStart(2, '0'))
    .join('-');
}

或者复制粘贴最短的版本

function hms(seconds) {
  return [3600, 60]
    .reduceRight(
      (p, b) => r => [Math.floor(r / b)].concat(p(r % b)),
      r => [r]
    )(seconds)
    .map(a => a.toString().padStart(2, '0'))
    .join('-');
}

一些示例输出:

> hms(0)
< "00-00-00"

> hms(5)
< "00-00-05"

> hms(60)
< "00-01-00"

> hms(3785)
< "01-03-05"

> hms(37850)
< "10-30-50"

> hms(378500)
< "105-08-20"

它是如何工作的

算法

要得到小时数,你需要用总秒数除以3600,然后取底。 要得到分钟数,你需要用余数除以60,然后取底。 要得到秒数,你只需用余数。

将单个金额保存在一个数组中也很好,以便于格式化。

例如,给定3785s的输入,输出应该是[1,3,5],即1小时3分5秒。

创建管道

将3600和60个常量命名为“断点”,您可以将此算法写成如下函数

function divideAndAppend(remainder, breakpoint, callback) {
  return [Math.floor(remainder / breakpoint)].concat(callback(remainder % breakpoint));
}

它返回一个数组,其中第一项是给定断点的数量,数组的其余部分由回调函数给出。 重用回调函数中的divideAndAppend将为您提供一个组合的divideAndAppend函数的管道。每一个 计算每个给定断点的数量,并将其附加到生成所需输出的数组中。

然后,您还需要“final”回调来结束这个管道。换句话说,您使用了所有的断点,现在只剩下其余的。 既然你已经在3)处得到了答案,你应该使用某种恒等函数,在这种情况下,remainder =>[余数]。

现在可以像这样编写管道

let pipeline = r3 => divideAndAppend(
    r3, 
    3600, 
    r2 => divideAndAppend(
        r2, 
        60, 
        r1 => [r1]));

> pipeline(3785)
< [1, 3, 5]

酷吧?

使用for-loop泛化

现在,您可以使用可变数量的断点进行泛化,并创建一个for循环,将单独的divideAndAppend函数组合到其中 管道。 您从恒等函数r1 => [r1]开始,然后使用60断点,最后使用3600断点。

let breakpoints = [60, 3600];
let pipeline = r => [r];

for (const b of breakpoints) {
  const previousPipeline = pipeline;
  pipeline = r => divideAndAppend(r, b, previousPipeline);
}

> pipeline(3785)
< [1, 3, 5]

使用Array.prototype.reduce ()

现在您可以将for循环重写为reducer,以获得更短、更实用的代码。换句话说,重写函数组合成减速器。

let pipeline = [60, 3600].reduce(
  (ppln, b) => r => divideAndAppend(r, b, ppln),
  r => [r]
);

> pipeline(3785)
< [1, 3, 5]

累加器ppln是管道,您正在使用它的以前版本来组合它。初始管道为r => [r]。

你现在可以内联函数divideAndAppend,并使用Array.prototype.reduceRight(与[].reverse().reduce(…)相同)来设置断点 定义更自然。

let pipeline = [3600, 60]
    .reduceRight(
      (ppln, b) => r => [Math.floor(r / b)].concat(ppln(r % b)),
      r => [r]
    );

这是最终形式。然后你只需appy映射到字符串与填充0的左边和连接字符串:分隔符;

更多的推广

将减速器包装成功能

function decompose(total, breakpoints) {
  return breakpoints.reduceRight(
    (p, b) => r => [Math.floor(r / b)].concat(p(r % b)),
    r => [r]
  )(total);
}

> decompose(3785, [3600, 60])
< [1, 3, 5]

你现在有了一个非常通用的算法。例如:

容易转换(奇怪的)我们的长度标准

考虑到标准

Unit Divisions
1 foot 12 inches
1 yard 3 feet
1 mile 1760 yards
> decompose(123_456, [1760 * 3 * 12, 3 * 12, 12])
< [1, 1669, 1, 0]

123456英寸= 1英里,1669码,1英尺和0英寸

或者你可以转换成十进制或二进制表示

> decompose(123_456, [100_000, 10_000, 1000, 100, 10])
< [1, 2, 3, 4, 5, 6]

> decompose(127, [128, 64, 32, 16, 8, 4, 2])
< [0, 1, 1, 1, 1, 1, 1, 1]

也适用于浮点断点

由于Javascript支持mod运算符带浮点数,你也可以这样做

> decompose(26.5, [20, 2.5])
< [1, 2, 1.5]

没有断点的边缘情况自然也被涵盖了

> decompose(123, [])
< [123]

这个函数应该这样做:

var convertTime = function (input, separator) {
    var pad = function(input) {return input < 10 ? "0" + input : input;};
    return [
        pad(Math.floor(input / 3600)),
        pad(Math.floor(input % 3600 / 60)),
        pad(Math.floor(input % 60)),
    ].join(typeof separator !== 'undefined' ?  separator : ':' );
}

在不传递分隔符的情况下,它使用:作为(默认)分隔符:

time = convertTime(13551.9941351); // --> OUTPUT = 03:45:51

如果你想使用-作为分隔符,只需将其作为第二个参数传递:

time = convertTime(1126.5135155, '-'); // --> OUTPUT = 00-18-46

看看这小提琴。

你也可以使用下面的代码:

int ss = nDur%60;
nDur   = nDur/60;
int mm = nDur%60;
int hh = nDur/60;

你也可以用Sugar。

Date.create().reset().set({seconds: 180}).format('{mm}:{ss}');

这个例子返回'03:00'。

我只是想对上面这个不错的答案做一点解释:

var totalSec = new Date().getTime() / 1000;
var hours = parseInt( totalSec / 3600 ) % 24;
var minutes = parseInt( totalSec / 60 ) % 60;
var seconds = totalSec % 60;

var result = (hours < 10 ? "0" + hours : hours) + "-" + (minutes < 10 ? "0" + minutes : minutes) + "-" + (seconds  < 10 ? "0" + seconds : seconds);

On the second line, since there are 3600 seconds in 1 hour, we divide the total number of seconds by 3600 to get the total number of hours. We use parseInt to strip off any decimal. If totalSec was 12600 (3 and half hours), then parseInt( totalSec / 3600 ) would return 3, since we will have 3 full hours. Why do we need the % 24 in this case? If we exceed 24 hours, let's say we have 25 hours (90000 seconds), then the modulo here will take us back to 1 again, rather than returning 25. It is confining the result within a 24 hour limit, since there are 24 hours in one day.

当你看到这样的东西:

25 % 24

你可以这样想:

25 mod 24 or what is the remainder when we divide 25 by 24