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
- Para obter horas, você divide o total de segundos por 3600 e arredonda para baixo.
- Para obter os minutos, você divide o resto por 60 e aplica o floor.
- 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
| Unidade | Divisões |
|---|---|
| 1 pé | 12 polegadas |
| 1 jarda | 3 pés |
| 1 milha | 1760 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];
}
