¿Cómo uso format () en una duración moment.js?

211

¿Hay alguna forma de usar el método moment.js format en objetos de duración? No puedo encontrarlo en ningún lugar de los documentos y no parece ser un atributo en los objetos de duración.

Me gustaría poder hacer algo como:

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

Además, si hay otras bibliotecas que pueden acomodar fácilmente este tipo de funcionalidad, me interesarían las recomendaciones.

¡Gracias!

mvanveen
fuente
55
moment.utc (Duration.asMilliseconds ()). format ('hh: mm: ss'); - Una duración es un vector. Al poner su cola en el origen, puede usar el formato de fecha para obtener hh: mm: ss.
Paul Williams
moment.utc (moment.duration (23, 'segundos'). asMilliseconds ()). format ('hh: mm: ss') => "12:00:23" no funciona tan bien
goldenratio
Ah, encontré el problema, HH:mm:ssdaré 00:00:23en mi ejemplo anterior. así que la carcasa equivocada por parte de las horas
goldenratio

Respuestas:

55

Estamos buscando agregar algún tipo de formato a las duraciones en moment.js. Ver https://github.com/timrwood/moment/issues/463

Un par de otras bibliotecas que podrían ayudar son http://countdownjs.org/ y https://github.com/icambron/twix.js

Timrwood
fuente
44
Estoy ansioso por el formato de duración también. Echando un vistazo countdownjs ahora, pero twix solo parece tener un formato "inteligente", no mucha personalización.
mpen
2
Si bien twix trabaja duro para formatear de manera inteligente, tiene muchas opciones de formateo, hasta los tokens involucrados: github.com/icambron/twix.js/wiki/Formatting . Descargo de responsabilidad: soy el autor de twix.
3
Countdown.js es excelente, y el autor es muy útil (acaba de lanzar 2 versiones en el mismo día debido a algunas sugerencias que hice).
Ohad Schneider
55
Im abajo a voto porque el tema github vinculado en esta respuesta se encuentra a interminables opiniones corriente, deseos y diatribas que no conducen en donde, el tema sigue abierto después de 4 años, nada Userful
bmaggi
29
¿Por qué no puede ser idéntico al otro .format utilizado en otra parte de la biblioteca? Esto es una locura. ¿5 años y todavía no está hecho? ¡¿De Verdad?!
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);

Echa un vistazo a JSFiddle

David Glass
fuente
3
Buen enfoque. Aunque no funciona si quiero mostrar días también: DDD HH:mm:ss.SSS(donde DDDes el día del año) aparece 1cuando quiero 0. ¿Alguna solución rápida para eso?
Andrew Mao
1
No hay manera fácil. Hice esto jsfiddle.net/fhdd8/14 , que es probablemente lo que hiciste, pero no creo que el momento tenga nada que haga esto fuera de la caja
David Glass
49
No tiene ningún sentido mostrar 10 billones de milisegundos como mm: ss
Pier-Luc Gendreau
28
esto no funciona más allá de las 24 horas (es decir, si quisiera mostrar 117 horas). De lo contrario, una gran solución!
Phil
1
@ Phil puedes usar "D" o "DD" si deseas mostrar días.
Vinay
71

convertir duración a ms y luego a momento:

moment.utc(duration.as('milliseconds')).format('HH:mm:ss')
Sagiv Ofek
fuente
14
Por lo tanto, esto no funciona si su duración es superior a 24 h. 24 h se restablece a 0 h
S. Robijns
44
@ S.Robijns es una observación útil pero solo para enfatizar para otros: este es el comportamiento esperado de .format('HH:mm:ss'). Ver los documentos
davnicwil
1
¡Esta es la mejor respuesta!
Magico
44

Utilice este complemento Formato de duración de momento .

Ejemplo:

moment.duration(123, "minutes").format("h:mm");
kayz1
fuente
1
Ese formato no funciona correctamente, el lado de la duración es bueno, pero si especifico hh:mm:mmy solo tengo 10 segundos, se muestra en 10lugar de 00:00:10(incluso con fuerza de longitud activada) Si no está formateando ... entonces debería llamarse de otra manera, los formatos deberían ser estandarizado.
Piotr Kula
9
@ppumkin, sé que esto es antiguo, pero si lo especifica { trim: false }, detendrá ese comportamiento.
Carlos Martinez
3
Esto es lo que prefiero usar: suponga que tiene una duración, como la const duration = moment.duration(value, 'seconds');que puedo formatear usando: moment.utc(duration.as('milliseconds')).format('HH:mm:ss').toString();
Evgeny Bobkin el
1
@EvgenyBobkin que no funcionará si su duración es más larga que un día, la biblioteca lo manejará
reggaeguitar
16

Use esta línea de código:

moment.utc(moment.duration(4500, "seconds").asMilliseconds()).format("HH:mm:ss")
NFpeter
fuente
8
Si la duración es> de 86400 '' (es decir, 24 h), esto no funcionará.
Lorenzo Tassone
Es lo mismo en Excel, se trasladará a las 24 horas. Esta es una gran solución si conoce la limitación 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
fuente
1
En general, las respuestas son mucho más útiles si incluyen una explicación de lo que el código pretende hacer y por qué eso resuelve el problema sin introducir otros. (Esta publicación fue marcada por al menos un usuario, presumiblemente porque pensaron que debería eliminarse una respuesta sin explicación).
Nathan Tuggy
1
Sin explicación o no, esto es lo que hizo por mí. Gracias :)
dmmd
La explicación no es necesaria. El documento Moment.js puede mostrar cómo se logró esta solución.
coffekid
2
Inútil. Como la mayoría de las otras respuestas a esta pregunta, devuelve horas parciales en la duración, no horas totales. Por ejemplo, regresa a las 12:00 para el momento de duración. Duración ({días: 2, horas: 12})
Neutrino
1
moment.duration (diff) .asMilliseconds () es excesivo. Puedes usar diff, ya está en milisegundos.
kristopolous
12

El mejor escenario para mi caso de uso particular fue:

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

Esto mejora la respuesta de @ Wilson ya que no accede a la propiedad interna privada _data.

TaeKwonJoe
fuente
Gracias @TaeKwonJoe
Kamlesh
11

No necesita formato. Use duraciones como esta:

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

Encontré esta solución aquí: https://github.com/moment/moment/issues/463

EDITAR:

Y con relleno para segundos, minutos y 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
fuente
2
Esto no incluirá ceros a la izquierda si la duración
Segundos
¿Qué pasará si tienes más segundos que una hora? ¿Está bien que tengas más de 60 segundos?
shaedrich
Los ceros iniciales funcionan, pero duration = moment.duration(7200, 'seconds'); withPadding(duration);dirán "00:00".
shaedrich
@shaedrich Actualicé mi respuesta nuevamente para incluir horas; si necesita días, semanas y también puede agregarlos a la matriz
ni-ko-o-kin
1
if (duration.asDays() > 0) { return 'at least one day';- ¿Estoy leyendo eso correctamente?
Stephen Paul
8

Yo suelo:

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

Y me sale "09:30" en var str.

Wilson
fuente
¡Excelente! Esto simplemente funciona ... ¿cómo se te ocurrió esto :)
vanthome
44
Evite esta solución, _dataes una propiedad interna y puede cambiar sin previo aviso.
Druska
1
Desafortunadamente, no funcionará siempre como se esperaba: moment(moment.duration(1200000)._data).format('hh:mm:ss')devolverá 12:20 en lugar de 00:20
Anna R
2
@AnnaR hestá en el rango 1-12, por lo que es bastante previsible. Utilice en su Hlugar documentos - fichas de hora
barbsan
Esto está mal, no solo que ignoras DÍAS, por lo que 1 día y 1 hora se mostrarán como 01:00. Además están ignorando por completo las zonas horarias, una solución mejor, pero tampoco es una completa uno será moment.utc(...).format("HH:mm");
Gil Epshtain
5

si diff es un momento

var diff = moment(20111031) - moment(20111010);
var formated1 = moment(diff).format("hh:mm:ss");
console.log("format 1: "+formated1);
Kieran
fuente
Esto no parece confiable frente a las zonas horarias y demás. ¿Usas esto en producción?
Keith
La pregunta no menciona las zonas horarias.
Kieran
3
Todos viven en una zona horaria. ¿El momento (0) siempre se registra como 12:00 AM en cada zona horaria?
Keith
Simplemente pregunto si el código en su respuesta funciona o no porque soy escéptico. He escrito mucho código que funciona con fechas, en muchos lenguajes de programación. Según mi experiencia, parece que su código solo funcionaría en ciertas zonas horarias, pero lo pregunto porque tal vez hay algo que no sé sobre cómo Javascript representa fechas cercanas a la época de Unix.
Keith
1
La segunda línea creará un momento desde el comienzo de los tiempos (1970). Esto no servirá
kumarharsh
5

Si está dispuesto a usar una biblioteca javascript diferente, numeral.js puede formatear segundos de la siguiente manera (el ejemplo es por 1000 segundos):

var string = numeral(1000).format('00:00');
// '00:16:40'
GChorn
fuente
Definitivamente el camino a seguir. como se esperaba.
Piotr Kula
4

Utilizo la función de formato clásico en estos casos:

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

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

Este es un truco porque la diferencia de tiempo se trata como una fecha de momento estándar, una fecha de fecha temprana, pero no importa para nuestro objetivo y no necesita ningún complemento

Correas
fuente
4

Si se deben mostrar todas las horas (más de 24) y si '0' antes de las horas no es necesario, entonces se puede formatear con una línea corta de código:

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

Basado en la respuesta 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
fuente
No creo que sea muy legible. ¿Qué problema quieres resolver aquí? ¿Cuál es tu caso de uso?
ni-ko-o-kin
Actualicé mi respuesta nuevamente para tratar con más de un día. Funciona bien para mi caso de uso.
ni-ko-o-kin
2
El problema es que en la mayoría de los casos su solución no es ideal porque contiene demasiados ceros a la izquierda. ¿Quién quiere que se devuelva "00: 00: 00: 00: 01"? Mi solución es "escalable" y agrega tantos ceros iniciales como sea necesario.
shaedrich
Funciona perfectamente. Salida muy simple. Si no hay días, no habrá ceros para los días que se muestran, etc.
Hasan Sefa Ozalp
3

Para formatear la duración del momento en una cadena

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
fuente
3

si usa angular, agregue esto a sus 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 ': '')
    }
})

ejemplo de uso

<div> {{diff | durationFormat}} </div>
Hai Alaluf
fuente
Muy bueno de verdad. Estaba buscando un 'formato bonito' como este. ¡Gracias!
riketscience
3

Mi solución que no involucra ninguna otra biblioteca y funciona con 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
fuente
1

¿Qué tal 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
fuente
1

Use el formato momento-duración .

Marco del cliente (ej .: Reaccionar)

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
fuente
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}`);

Huellas dactilares:

2 días 14 h 00 min 00 s

davidhq
fuente
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 herramientas
fuente
0

Puede usar numeral.js para formatear su duración:

numeral(your_duration.asSeconds()).format('00:00:00') // result: hh:mm:ss
Joao Paulo
fuente
0

Esto se puede usar para obtener los dos primeros caracteres como horas y los dos últimos como minutos. Se puede aplicar la misma lógica a los 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
fuente
Si inserta el código como un fragmento, podrá probar el método y mostrar algunos resultados a la consola.
DJDaveMark
¡Cosa segura! Recién actualizado con fragmento para pruebas rápidas.
José Luis Raffalli
0

moment.duration(x).format()ha quedado en desuso Puede usar moment.utc(4366589).format("HH:mm:ss")para obtener la respuesta deseada.

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>

un poco codificador
fuente
0

¿Cómo usar correctamente las duraciones de moment.js? El | Use moment.duration () en el código

Primero necesitas importar momenty moment-duration-format.

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

Luego, use la función de duración. Apliquemos el ejemplo anterior: 28800 = 8 am.

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

🎉Bueno, no tienes el error de tipo anterior. 🤔 ¿Obtiene un valor correcto a las 8:00 am? No ..., el valor que obtienes es 8:00 a. El formato Moment.js no funciona como debería.

SolutionLa solución es transformar segundos a milisegundos y usar el tiempo UTC.

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

Muy bien, tenemos las 8:00 am ahora. Si desea las 8 am en lugar de las 8:00 am para el tiempo integral, necesitamos hacer RegExp

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

Necesitaba hacer esto para trabajar como requisito para mostrar las horas en este formato. Al principio probé esto.

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

Sin embargo, nada más de 24 horas y las horas se restablecen a 0. Pero los minutos y segundos fueron precisos. Así que usé solo esa parte para los minutos y segundos.

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

Ahora todo lo que necesito es el total de horas.

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

Y para obtener ese formato que todos queremos, simplemente lo pegamos.

var formatted = hours + ":" + minutesSeconds

si totalMillisecondses 894600000esto volverá 249:30:00.

Espero que haya ayudado. Deja cualquier pregunta en los comentarios. ;)

Zach Dyer
fuente
-1

Si usa Angular> 2, hice una pipa inspirada en la respuesta @ 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
fuente
-3

Esto funciona para mi:

moment({minutes: 150}).format('HH:mm') // 01:30
Natan Augusto
fuente
Volver "Fecha inválida"
themadmax
3
150 minutos no son 1 hora y 30 minutos.
Mark Brown