Pesquisa de site

date - Converter segundos para HH-MM-SS com JavaScript?


Como posso converter segundos em uma string HH-MM-SS usando JavaScript?

Resposta #1

Você pode conseguir fazer isso sem nenhuma biblioteca JavaScript externa com a ajuda do método Date do JavaScript, como segue:

const date = new Date(null);
date.setSeconds(SECONDS); // specify value for SECONDS here
const result = date.toISOString().slice(11, 19);

Ou, conforme o comentário do @Frank; uma linha só:

new Date(SECONDS * 1000).toISOString().slice(11, 19);

Resposta #2

Atualizado (2020):

Por favor, use a solução de uma linha do @Frank:

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

Se SECONDS<3600 e se você quiser mostrar apenas MM:SS, então use o código abaixo:

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

É de longe a melhor solução.


Resposta antiga:

Use a biblioteca Moment.js.

Resposta #3

Eu não acho que qualquer recurso interno do objeto Date padrão fará isso para você de uma maneira que seja mais conveniente do que simplesmente fazer os cálculos você mesmo.

hours = Math.floor(totalSeconds / 3600);
totalSeconds %= 3600;
minutes = Math.floor(totalSeconds / 60);
seconds = totalSeconds % 60;

Exemplo :

let totalSeconds = 28565;
let hours = Math.floor(totalSeconds / 3600);
totalSeconds %= 3600;
let minutes = Math.floor(totalSeconds / 60);
let seconds = totalSeconds % 60;

console.log("hours: " + hours);
console.log("minutes: " + minutes);
console.log("seconds: " + seconds);

// If you want strings with leading zeroes:
minutes = String(minutes).padStart(2, "0");
hours = String(hours).padStart(2, "0");
seconds = String(seconds).padStart(2, "0");
console.log(hours + ":" + minutes + ":" + seconds);

Resposta #4

Eu sei que isso é meio antigo, mas...

ES2015:

var toHHMMSS = (secs) => {
    var sec_num = parseInt(secs, 10)
    var hours   = Math.floor(sec_num / 3600)
    var minutes = Math.floor(sec_num / 60) % 60
    var seconds = sec_num % 60

    return [hours,minutes,seconds]
        .map(v => v < 10 ? "0" + v : v)
        .filter((v,i) => v !== "00" || i > 0)
        .join(":")
}

Isso irá gerar:

toHHMMSS(129600) // 36:00:00
toHHMMSS(13545) // 03:45:45
toHHMMSS(180) // 03:00
toHHMMSS(18) // 00:18

Resposta #5

Como Cleiton apontou em sua resposta, moment.js pode ser usado para isso:

moment().startOf('day')
        .seconds(15457)
        .format('H:mm:ss');

Resposta #6

Aqui está uma função simples para converter horários que pode ajudar

function formatSeconds(seconds) {
    var date = new Date(1970,0,1);
    date.setSeconds(seconds);
    return date.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");
}

Resposta #7

Isso resolve o problema:

function secondstotime(secs)
{
    var t = new Date(1970,0,1);
    t.setSeconds(secs);
    var s = t.toTimeString().substr(0,8);
    if(secs > 86399)
        s = Math.floor((t - Date.parse("1/1/70")) / 3600000) + s.substr(2);
    return s;
}

(Obtido daqui)

Resposta #8

var  timeInSec = "661"; //even it can be string

String.prototype.toHHMMSS = function () { 
   /* extend the String by using prototypical inheritance */
    var seconds = parseInt(this, 10); // don't forget the second param
    var hours   = Math.floor(seconds / 3600);
    var minutes = Math.floor((seconds - (hours * 3600)) / 60);
    seconds = seconds - (hours * 3600) - (minutes * 60);

    if (hours   < 10) {hours   = "0"+hours;}
    if (minutes < 10) {minutes = "0"+minutes;}
    if (seconds < 10) {seconds = "0"+seconds;}
    var time    = hours+':'+minutes+':'+seconds;
    return time;
}

alert("5678".toHHMMSS());   // "01:34:38"
console.log(timeInSec.toHHMMSS());   //"00:11:01"

Podemos tornar essa função muito mais curta e direta, mas isso diminui a legibilidade, então a escreveremos o mais simples possível e o mais estável possível.

ou você pode verificar este funcionamento aqui:

Resposta #9

Acho que a solução mais geral (e criptografada) poderia ser esta

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('-');
}

Ou para copiar e colar a versão mais curta

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('-');
}

Alguns exemplos de resultados:

> 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"

Como funciona

Algoritmo

  1. Para obter horas, você divide o total de segundos por 3600 e arredonda para baixo.
  2. Para obter os minutos, você divide o resto por 60 e aplica o floor.
  3. Para obter os segundos, você apenas usa o resto.

Também seria bom manter os valores individuais em um array para facilitar a formatação.

Por exemplo, dado o input de 3785s, o output deve ser [1, 3, 5], ou seja, 1 hora, 3 minutos e 5 segundos.

Criando pipeline

Nomeando as constantes 3600 e 60 como "pontos de quebra", você pode escrever este algoritmo em uma função assim

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

Ele retorna um array onde o primeiro item é a quantidade para o ponto de interrupção dado e o resto do array é fornecido pelo callback. Reutilizar o divideAndAppend na função callback irá fornecer um pipeline de funções compostas divideAndAppend. Cada uma delas calcula a quantidade por ponto de interrupção dado e a adiciona ao array, criando sua saída desejada.

Então você também precisa do callback "final" que encerra este pipeline. Em outras palavras, você usou todos os pontos de interrupção e agora só tem o restante. Como você já tem a resposta no item 3), você deve usar algum tipo de função identidade, neste caso remainder => [remainder].

Agora você pode escrever o pipeline assim

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

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

Legal, né?

Generalizando usando loop for

Agora você pode generalizar com uma quantidade variável de pontos de interrupção e criar um loop for que irá compor funções individuais divideAndAppend no pipeline. Você começa com a função identidade r1 => [r1], depois usa o ponto de interrupção 60 e, finalmente, usa o ponto de interrupção 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]

Usando Array.prototype.reduce()

Agora você pode reescrever este laço for em um reducer para um código mais curto e funcional. Em outras palavras, reescreva a composição de funções no reducer.

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

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

O acumulador ppln é o pipeline e você está compondo-o usando a versão anterior dele. O pipeline inicial é r => [r].

Você agora pode inserir a função divideAndAppend diretamente e usar Array.prototype.reduceRight, que é o mesmo que [].reverse().reduce(...), para tornar as definições de pontos de interrupção mais naturais.

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

Que é a forma final. Então você apenas aplica o mapeamento para a string com zeros preenchidos à esquerda e junta as strings com o separador :;

Mais generalizações

Envolvendo o redutor em função

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]

você agora tem um algoritmo muito geral com o qual pode trabalhar. Por exemplo:

Converta facilmente os padrões de comprimento (estranhos) dos EUA

Dado os padrões

UnidadeDivisões
1 pé12 polegadas
1 jarda3 pés
1 milha1760 jardas
> decompose(123_456, [1760 * 3 * 12, 3 * 12, 12])
< [1, 1669, 1, 0]

123456 pol=1 mi, 1669 jardas, 1 pé e 0 pol

Ou você pode de certa forma converter para representações decimais ou binárias

> 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]

Funciona também com pontos de interrupção de ponto flutuante

Como o Javascript suporta o operador mod com números de ponto flutuante, você também pode fazer

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

O caso extremo de não haver pontos de interrupção também é naturalmente coberto

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

Resposta #10

Tente isto:

function toTimeString(seconds) {
  return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0];
}

Artigos relacionados