Como uso format () na duração moment.js?

211

Existe alguma maneira de usar o método moment.js format em objetos de duração? Não consigo encontrá-lo em nenhum lugar nos documentos e não parece ser um atributo nos objetos de duração.

Eu gostaria de poder fazer algo como:

var diff = moment(end).unix() - moment(start).unix();
moment.duration(diff).format('hh:mm:ss')

Além disso, se houver outras bibliotecas que possam acomodar facilmente esse tipo de funcionalidade, eu estaria interessado em recomendações.

Obrigado!

mvanveen
fonte
5
moment.utc (duration.asMilliseconds ()). format ('hh: mm: ss'); - Uma duração é um vetor. Ao colocar a cauda na origem, você pode usar a formatação de data para obter hh: mm: ss.
Paul Williams
moment.utc (moment.duration (23, 'seconds'). asMilliseconds ()). format ('hh: mm: ss') => "12:00:23" não funciona tão bem
goldenratio
Ah, eu encontrei o problema, HH:mm:ssvou dar 00:00:23no meu exemplo anterior. então apenas o invólucro errado na parte Horas
goldenratio

Respostas:

55

Estamos pensando em adicionar algum tipo de formatação às durações no momento.js. Consulte https://github.com/timrwood/moment/issues/463

Algumas outras bibliotecas que podem ajudar são http://countdownjs.org/ e https://github.com/icambron/twix.js

timrwood
fonte
4
Também estou ansioso pela formatação da duração. Olhando agora countdownjs, mas o twix parece apenas fazer formatação "inteligente", sem muita personalização.
MPEN
2
Embora o twix trabalhe duro para fazer a formatação inteligente, ele tem muitas opções de formatação, até os tokens envolvidos: github.com/icambron/twix.js/wiki/Formatting . Disclaimer: Eu sou o autor de twix.
3
O Countdown.js é excelente, e o autor é super útil (ele acabou de lançar duas versões no mesmo dia devido a algumas sugestões que eu fiz)!
Oade Schneider
5
Im down-voto porque a questão github ligada nesta resposta é apenas intermináveis opiniões stream, desejos e divertidos que não levam onde, a questão ainda está aberta após 4 anos, nada userful
bmaggi
29
Por que não pode ser idêntico ao outro formato usado em outras partes da biblioteca? Isto é loucura. 5 anos e ainda não está pronto? realmente?!
Kristopolous
164
// set up
let start = moment("2018-05-16 12:00:00"); // some random moment in time (in ms)
let end = moment("2018-05-16 12:22:00"); // some random moment after start (in ms)
let diff = end.diff(start);

// execution
let f = moment.utc(diff).format("HH:mm:ss.SSS");
alert(f);

Dê uma olhada no JSFiddle

David Glass
fonte
3
Boa abordagem. Embora não funcione se eu quiser exibir os dias também: DDD HH:mm:ss.SSS(onde DDDé o dia do ano) é exibido 1quando eu quero 0. Alguma solução rápida para isso?
Andrew Mao
1
Não é fácil. Eu fiz isso jsfiddle.net/fhdd8/14 , que provavelmente é o que você fez, mas acho que o momento não tem nada que faça isso imediatamente
David Glass
49
Não faz qualquer sentido para exibir 10 quatrilhões de milissegundos como mm: ss
Pier-Luc Gendreau
28
isso não funciona nas últimas 24 horas (ou seja, se eu quisesse exibir 117 horas). caso contrário, ótima solução!
Phil
1
@ Phil, você pode usar "D" ou "DD" se desejar mostrar os dias.
Vinay
71

converta a duração para ms e depois para o momento:

moment.utc(duration.as('milliseconds')).format('HH:mm:ss')
Sagiv Ofek
fonte
14
Portanto, isso não funcionará se a sua duração for superior a 24h. 24h está sendo redefinida para 0h #
S. Robijns 18/18
4
@ S.Robijns uma observação útil, mas apenas para enfatizar para os outros - este é o comportamento esperado de .format('HH:mm:ss'). Veja os docs
davnicwil
1
Esta é a melhor resposta!
Magico
44

Use este plug-in Moment Duration Format .

Exemplo:

moment.duration(123, "minutes").format("h:mm");
kayz1
fonte
1
Essa formatação não funciona corretamente, o lado da duração é bom, mas se eu especificar hh:mm:mme só tiver 10 segundos, será exibido em 10vez de 00:00:10(mesmo com o forcelength ativado) Se não estiver formatando ... então deve ser chamado de outra coisa, os formatos devem ser padronizado.
Piotr Kula
9
@ppumkin eu sei que isso é antigo, mas se você especificar, { trim: false }ele interromperá esse comportamento.
Carlos Martinez
3
Isto é o que eu prefiro usar: Suponha que você tenha duração, como se const duration = moment.duration(value, 'seconds');eu pudesse ser formatado usando: moment.utc(duration.as('milliseconds')).format('HH:mm:ss').toString();
Evgeny Bobkin 7/17
1
@EvgenyBobkin que não vai funcionar se a sua duração é de mais de um dia longo, a biblioteca vai lidar com isso embora
reggaeguitar
16

Use esta linha de código:

moment.utc(moment.duration(4500, "seconds").asMilliseconds()).format("HH:mm:ss")
NFpeter
fonte
8
Se a duração for> de 86400 '' (ou seja, 24h), isso não funcionará.
Lorenzo Tassone
É o mesmo no Excel, ele vai rolar às 24 horas. Essa é uma ótima solução alternativa, se você estiver ciente da limitação de 24 horas.
Eman4real
15
var diff = moment(end).unix() - moment(start).unix();
moment.utc(moment.duration(diff).asMilliseconds()).format("HH:mm:ss.SSS");
Eric Saboia
fonte
1
Geralmente, as respostas são muito mais úteis se incluem uma explicação sobre o que o código pretende fazer e por que isso resolve o problema sem a introdução de outros. (Esta mensagem foi marcado por pelo menos um usuário, presumivelmente porque eles achavam uma resposta sem explicação deve ser suprimida.)
Nathan Tuggy
1
Sem explicação ou não, foi isso que fez por mim. Obrigado :)
dmmd 17/09/2015
Explicação não é necessária. O documento Moment.js pode mostrar como essa solução foi alcançada.
Coffekid 18/05/19
2
Sem utilidade. Como a maioria das outras respostas sobre essa pergunta, retornamos horas parciais na duração e não no total de horas. Por exemplo, retorna 12:00 para a duração moment.duration ({days: 2, hours: 12})
Neutrino
1
moment.duration (diff). como Milissegundos () é excessivo. Você pode apenas usar diff, já está em milissegundos.
Kristopolous
12

O melhor cenário para meu caso de uso específico foi:

var duration = moment.duration("09:30"),
    formatted = moment.utc(duration.asMilliseconds()).format("HH:mm");

Isso melhora a resposta de @ Wilson, pois não acessa a propriedade interna privada _data.

TaeKwonJoe
fonte
Obrigado @TaeKwonJoe
Kamlesh
11

Você não precisa do formato. Use durações como esta:

const duration = moment.duration(83, 'seconds');
console.log(duration.minutes() + ':' +duration.seconds());
// output: 1:23

Encontrei esta solução aqui: https://github.com/moment/moment/issues/463

EDITAR:

E com preenchimento por segundos, minutos e horas:

const withPadding = (duration) => {
    if (duration.asDays() > 0) {
        return 'at least one day';
    } else {
        return [
            ('0' + duration.hours()).slice(-2),
            ('0' + duration.minutes()).slice(-2),
            ('0' + duration.seconds()).slice(-2),
        ].join(':')
    }
}

withPadding(moment.duration(83, 'seconds'))
// 00:01:23

withPadding(moment.duration(6048000, 'seconds'))
// at least one day
ni-ko-o-kin
fonte
2
Isto não inclui zeros à esquerda se duration.seconds () é inferior a 10, embora ...
carpiediem
O que acontecerá se você tiver mais segundos do que uma hora? Tudo bem que você tenha mais de 60 segundos?
22618 shaedrich
Os zeros à esquerda funcionam, mas duration = moment.duration(7200, 'seconds'); withPadding(duration);dirão "00:00".
21818 shaedrich #
@ shaedrich Atualizei minha resposta novamente para incluir horas; se você precisar de dias, semanas, também poderá adicioná-los à matriz
ni-ko-o-kin
1
if (duration.asDays() > 0) { return 'at least one day';- estou lendo isso corretamente?
Stephen Paul
8

Eu uso:

var duration = moment.duration("09:30");
var str = moment(duration._data).format("HH:mm");

E eu recebo "09:30" em var str.

Wilson
fonte
Ótimo! Isso simplesmente funciona ... como diabos você surgiu com isso :)
vanthome
4
Evite esta solução, _dataé uma propriedade interna e pode mudar sem aviso prévio.
Druska
1
Infelizmente, nem sempre funcionará conforme o esperado: moment(moment.duration(1200000)._data).format('hh:mm:ss')retornará 12:20 em vez de 00:20 #
Anna R
2
O @AnnaR hestá no intervalo de 1 a 12, portanto é bastante esperado. Utilizar Hem vez docs - fichas horas
barbsan
Isso está errado, não apenas porque você ignora DAYS, como 1 dia e 1 hora serão mostrados como 01:00. Além disso, você está ignorando completamente Time Zones, uma solução melhor, mas também não é uma completa um será moment.utc(...).format("HH:mm");
Gil Epshtain
5

se diff é um momento

var diff = moment(20111031) - moment(20111010);
var formated1 = moment(diff).format("hh:mm:ss");
console.log("format 1: "+formated1);
Kieran
fonte
Isso não parece confiável diante dos fusos horários e tal. Você usa isso na produção?
Keith
a pergunta não menciona fusos horários.
Kieran
3
Todo mundo vive em um fuso horário. O momento (0) sempre é registrado como 00:00 em todos os fusos horários?
21313 Keith
Estou simplesmente perguntando se o código na sua resposta funciona ou não porque sou cético. Eu escrevi muito código que funciona com datas, em muitas linguagens de programação. Com base na minha experiência, parece que seu código funcionaria apenas em determinados fusos horários - mas estou perguntando, porque talvez haja algo que eu não saiba sobre como o Javascript representa datas próximas à época do Unix.
21413 Keith
1
a segunda linha criará um momento desde o início dos tempos (1970). Isso não serve.
kumarharsh
5

Se você deseja usar uma biblioteca javascript diferente, o numeral.js pode formatar segundos da seguinte maneira (o exemplo é por 1000 segundos):

var string = numeral(1000).format('00:00');
// '00:16:40'
GChorn
fonte
definitivamente o caminho a percorrer. como esperado.
Piotr Kula
4

Eu uso a função de formato clássico nesses casos:

var diff = moment(end).unix() - moment(start).unix();

//use unix function instead of difference
moment.unix(diff).format('hh:mm:ss')

Isso é um hack, porque a diferença de horário é tratada como uma data de momento padrão, uma data de época inicial, mas isso não importa para o nosso objetivo e você não precisa de nenhum plugin

Correias
fonte
4

Se todas as horas tiverem que ser exibidas (mais de 24) e se '0' antes das horas não for necessário, a formatação poderá ser feita com uma pequena linha de código:

Math.floor(duration.as('h')) + moment.utc(duration.as('ms')).format(':mm:ss')
ov
fonte
4

Com base na resposta de ni-ko-o-kin :

meassurements = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"];
withPadding = (duration) => {
    var step = null;
    return meassurements.map((m) => duration[m]()).filter((n,i,a) => {
        var nonEmpty = Boolean(n);
        if (nonEmpty || step || i >= a.length - 2) {
            step = true;
        }
        return step;
    }).map((n) => ('0' + n).slice(-2)).join(':')
}

duration1 = moment.duration(1, 'seconds');
duration2 = moment.duration(7200, 'seconds');
duration3 = moment.duration(604800, 'seconds');

withPadding(duration1); // 00:01
withPadding(duration2); // 02:00:00
withPadding(duration3); // 01:07:00:00:00
Shaedrich
fonte
Eu não acho muito legível. Que problema você quer resolver aqui? Qual é o seu caso?
Ni-ko-o-kin
Atualizei minha resposta novamente para lidar com mais de um dia. Funciona bem para o meu caso de uso.
Ni-ko-o-kin
2
O problema é que, na maioria dos casos, sua solução não é ideal porque contém muitos zeros à esquerda. Quem quer que "00: 00: 00: 00: 01" retorne? Minha solução é "escalável" e adiciona os zeros à esquerda necessários.
22618 shaedrich #
Funciona perfeitamente. Saída muito simples. Se não houver dias, não haverá zeros para os dias exibidos etc.
Hasan Sefa Ozalp
3

Para formatar a duração do momento para string

var duration = moment.duration(86400000); //value in milliseconds
var hours = duration.hours();
var minutes = duration.minutes();
var seconds = duration.seconds();
var milliseconds = duration.milliseconds();

var date = moment().hours(hours).minutes(minutes).seconds(seconds).millisecond(milliseconds);
if (is12hr){
    return date.format("hh:mm:ss a");
}else{
    return date.format("HH:mm:ss");
}
Dineshkani
fonte
3

se você usa angular, adicione isso aos seus filtros:

.filter('durationFormat', function () {
    return function (value) {
        var days = Math.floor(value/86400000);
        value = value%86400000;
        var hours = Math.floor(value/3600000);
        value = value%3600000;
        var minutes = Math.floor(value/60000);
        value = value%60000;
        var seconds = Math.floor(value/1000);
        return (days? days + ' days ': '') + (hours? hours + ' hours ': '') + (minutes? minutes + ' minutes ': '') + (seconds? seconds + ' seconds ': '')
    }
})

exemplo de uso

<div> {{diff | durationFormat}} </div>
Hai Alaluf
fonte
Muito bom mesmo. Eu estava procurando por um 'formato bonito' como este. Obrigado!
Riketscience
3

Minha solução que não envolve nenhuma outra biblioteca e funciona com diff> 24h

var momentInSeconds = moment.duration(n,'seconds')
console.log(("0" + Math.floor(momentInSeconds.asHours())).slice(-2) + ':' + ("0" + momentInSeconds.minutes()).slice(-2) + ':' + ("0" + momentInSeconds.seconds()).slice(-2))
Lorenzo Tassone
fonte
1

E o javascript nativo?

var formatTime = function(integer) {
    if(integer < 10) {
        return "0" + integer; 
    } else {
        return integer;
    }
}

function getDuration(ms) {
    var s1 = Math.floor(ms/1000);
    var s2 = s1%60;
    var m1 = Math.floor(s1/60);
    var m2 = m1%60;
    var h1 = Math.floor(m1/60);
    var string = formatTime(h1) +":" + formatTime(m2) + ":" + formatTime(s2);
    return string;
}
J. Allen
fonte
1

Use o formato momento-duração .

Estrutura do Cliente (ex: React)

import moment from 'moment';
import momentDurationFormatSetup from 'moment-duration-format';
momentDurationFormatSetup(moment);

const breakLengthInMinutes = moment.duration(breakLengthInSeconds, 's').format('m');

Servidor (node.js)

const moment = require("moment-timezone");
const momentDurationFormatSetup = require("moment-duration-format");

momentDurationFormatSetup(moment);

const breakLengthInMinutes = moment.duration(breakLengthInSeconds, 's').format('m');
AryanJ-NYC
fonte
0
const duration = moment.duration(62, 'hours');
const n = 24 * 60 * 60 * 1000;
const days = Math.floor(duration / n);
const str = moment.utc(duration % n).format('H [h] mm [min] ss [s]');
console.log(`${days > 0 ? `${days} ${days == 1 ? 'day' : 'days'} ` : ''}${str}`);

Impressões:

2 dias 14 h 00 min 00 s

davidhq
fonte
0
import * as moment from 'moment'
var sleep = require('sleep-promise');

(async function () {
    var t1 = new Date().getTime();
    await sleep(1000); 
    var t2 = new Date().getTime();
    var dur = moment.duration(t2-t1); 
    console.log(`${dur.hours()}h:${dur.minutes()}m:${dur.seconds()}s`);
})();
0h:0m:1s
Kit de ferramentas
fonte
0

Você pode usar o numeral.js para formatar sua duração:

numeral(your_duration.asSeconds()).format('00:00:00') // result: hh:mm:ss
João Paulo
fonte
0

Isso pode ser usado para obter os dois primeiros caracteres como horas e os dois últimos como minutos. A mesma lógica pode ser aplicada a segundos.

/**
     * PT1H30M -> 0130
     * @param {ISO String} isoString
     * @return {string} absolute 4 digit number HH:mm
     */

    const parseIsoToAbsolute = (isoString) => {
    
      const durations = moment.duration(isoString).as('seconds');
      const momentInSeconds = moment.duration(durations, 'seconds');
    
      let hours = momentInSeconds.asHours().toString().length < 2
        ? momentInSeconds.asHours().toString().padStart(2, '0') : momentInSeconds.asHours().toString();
        
      if (!Number.isInteger(Number(hours))) hours = '0'+ Math.floor(hours);
    
      const minutes = momentInSeconds.minutes().toString().length < 2
        ? momentInSeconds.minutes().toString().padEnd(2, '0') : momentInSeconds.minutes().toString();
    
      const absolute = hours + minutes;
      return absolute;
    };
    
    console.log(parseIsoToAbsolute('PT1H30M'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

José Luis Raffalli
fonte
Se você inserir o código como um trecho, poderá testar o método e mostrar alguma saída para o console.
DJDaveMark
Coisa certa! Apenas atualizado com o snippet para testes rápidos.
José Luis Raffalli 09/02
0

moment.duration(x).format()foi descontinuado. Você pode usar moment.utc(4366589).format("HH:mm:ss")para obter a resposta desejada.

console.log(moment.utc(4366589).format("HH:mm:ss"))
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

kindacoder
fonte
0

Como usar corretamente as durações de moment.js? | Use moment.duration () no código

Primeiro você precisa importar momente moment-duration-format.

import moment from 'moment';
import 'moment-duration-format';

Então, use a função duration. Vamos aplicar o exemplo acima: 28800 = 8 da manhã.

moment.duration(28800, "seconds").format("h:mm a");

,Bem, você não possui um erro de tipo acima. GetVocê obtém o valor certo às 8:00 da manhã? Não…, o valor que você recebe é 8:00 a. O formato Moment.js não está funcionando como deveria.

SolutionA solução é transformar segundos em milissegundos e usar o horário UTC.

moment.utc(moment.duration(value, 'seconds').asMilliseconds()).format('h:mm a')

Tudo bem, temos 8:00 agora. Se você quer 8 da manhã em vez das 8 da manhã por tempo integral, precisamos fazer o RegExp

const time = moment.utc(moment.duration(value, 'seconds').asMilliseconds()).format('h:mm a');
time.replace(/:00/g, '')
Farrukh Malik
fonte
0

Eu precisava fazer isso para trabalhar como requisito para exibir as horas neste formato. No começo eu tentei isso.

moment.utc(totalMilliseconds).format("HH:mm:ss")

No entanto, qualquer coisa acima de 24 horas e as horas são redefinidas para 0. Mas os minutos e segundos foram precisos. Então eu usei apenas essa parte pelos minutos e segundos.

var minutesSeconds = moment.utc(totalMilliseconds).format("mm:ss")

Agora tudo que eu preciso é o total de horas.

var hours = moment.duration(totalMilliseconds).asHours().toFixed()

E para obter o formato que todos queremos, basta colá-lo.

var formatted = hours + ":" + minutesSeconds

se totalMillisecondsfor 894600000isso retornará 249:30:00.

Espero que tenha ajudado. Deixe qualquer dúvida nos comentários. ;)

Zach Dyer
fonte
-1

Se você usa Angular> 2, criei um Pipe inspirado na resposta @ hai-alaluf.

import {Pipe, PipeTransform} from "@angular/core";

@Pipe({
  name: "duration",
})

export class DurationPipe implements PipeTransform {

  public transform(value: any, args?: any): any {

    // secs to ms
    value = value * 1000;
    const days = Math.floor(value / 86400000);
    value = value % 86400000;
    const hours = Math.floor(value / 3600000);
    value = value % 3600000;
    const minutes = Math.floor(value / 60000);
    value = value % 60000;
    const seconds = Math.floor(value / 1000);
    return (days ? days + " days " : "") +
      (hours ? hours + " hours " : "") +
      (minutes ? minutes + " minutes " : "") +
      (seconds ? seconds + " seconds " : "") +
      (!days && !hours && !minutes && !seconds ? 0 : "");
  }
}
0x29A
fonte
-3

Isso funciona para mim:

moment({minutes: 150}).format('HH:mm') // 01:30
Natan Augusto
fonte
Retornar "Data inválida"
themadmax 12/06/19
3
150 minutos não é 1 hora e 30 minutos.
Mark Brown