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


当前回答

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

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

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

其他回答

更新(2020):

请使用@Frank的一句话解决方案:

new Date(SECONDS * 1000).toISOString().substring(11, 16)

如果SECONDS<3600并且你只想显示MM:SS,那么使用下面的代码:

new Date(SECONDS * 1000).toISOString().substring(14, 19)

这是目前为止最好的解决办法。


旧的回答:

使用Moment.js库。

下面是一个函数,根据powtac的答案将秒转换为hh-mm-ss格式

斯菲德尔

/** 
 * Convert seconds to hh-mm-ss format.
 * @param {number} totalSeconds - the total seconds to convert to hh- mm-ss
**/
var SecondsTohhmmss = function(totalSeconds) {
  var hours   = Math.floor(totalSeconds / 3600);
  var minutes = Math.floor((totalSeconds - (hours * 3600)) / 60);
  var seconds = totalSeconds - (hours * 3600) - (minutes * 60);

  // round seconds
  seconds = Math.round(seconds * 100) / 100

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

示例使用

var seconds = SecondsTohhmmss(70);
console.log(seconds);
// logs 00-01-10

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

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]

看了所有的答案,大部分都不满意,下面是我想到的。我知道我说得有点晚了,但我还是要说了。

function secsToTime(secs){
  var time = new Date(); 
  // create Date object and set to today's date and time
  time.setHours(parseInt(secs/3600) % 24);
  time.setMinutes(parseInt(secs/60) % 60);
  time.setSeconds(parseInt(secs%60));
  time = time.toTimeString().split(" ")[0];
  // time.toString() = "HH:mm:ss GMT-0800 (PST)"
  // time.toString().split(" ") = ["HH:mm:ss", "GMT-0800", "(PST)"]
  // time.toTimeString().split(" ")[0]; = "HH:mm:ss"
  return time;
}

我创建了一个新的日期对象,将时间更改为参数,将日期对象转换为时间字符串,并通过分割字符串并只返回需要的部分来删除额外的内容。

我认为我应该分享这种方法,因为它不需要正则表达式、逻辑和数学技巧来获得“HH:mm:ss”格式的结果,而是依赖于内置的方法。

您可能想看一下这里的文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

简单的函数转换秒为hh:mm:ss格式:

function getHHMMSSFromSeconds(totalSeconds) {
    if (!totalSeconds) {
      return '00:00:00';
    }
    const hours = Math.floor(totalSeconds / 3600);
    const minutes = Math.floor(totalSeconds % 3600 / 60);
    const seconds = totalSeconds % 60;
    const hhmmss = padTo2(hours) + ':' + padTo2(minutes) + ':' + padTo2(seconds);
    return hhmmss;
}

// function to convert single digit to double digit
function padTo2(value) {
    if (!value) {
      return '00';
    }
    return value < 10 ? String(value).padStart(2, '0') : value;
}