¿Cómo convertir milisegundos en formato legible por humanos?

118

Necesito convertir una cantidad arbitraria de milisegundos en Días, Horas, Minutos Segundo.

Por ejemplo: 10 días, 5 horas, 13 minutos, 1 segundo.

FlySwat
fuente
"El idioma que estoy usando no tiene esto incorporado, de lo contrario lo usaría". Encuentro eso difícil de entender. ¿Que lenguaje? ¿Qué sistema operativo?
S.Lott
ActionScript, cualquier sistema operativo, tiene soporte de fecha / hora miserable
FlySwat
3
No conozco ningún idioma que tenga lo que está pidiendo, ni veo ninguna razón por la que lo tenga. Algunas matemáticas muy simples de división / módulo dan la respuesta muy bien.
Kip
1
No todos los años tienen la misma cantidad de días, por lo que tendría que indicar qué período fue. O tal vez, ¿solo lo quieres en años 'estándar' (365.algo)?
Milan Babuškov
@Kip: Entendido, leí mal la pregunta, estaba pensando en las marcas de tiempo del sistema operativo en milisegundos. No tiempos o intervalos delta. Tentado a editar la pregunta ...
S.Lott

Respuestas:

226

Bueno, dado que nadie más ha intensificado, escribiré el código fácil para hacer esto:

x = ms / 1000
seconds = x % 60
x /= 60
minutes = x % 60
x /= 60
hours = x % 24
x /= 24
days = x

Me alegro de que se detuviera en días y no preguntara durante meses. :)

Tenga en cuenta que en lo anterior, se supone que /representa truncar la división de enteros. Si usa este código en un idioma donde /representa la división de punto flotante, deberá truncar manualmente los resultados de la división según sea necesario.

Greg Hewgill
fuente
2
Solo usé eso en una función de flash. ¡Gracias! (voto a favor por simplicidad)
Makram Saleh
2
No funciona correctamente. Debería usar parseInt cuando use el divisor, de lo contrario verá valores flotantes largos. Vea mi respuesta a continuación para obtener una solución más completa.
Rajiv
17
@Greg Hewgill Me alegro de que se detuviera en días y no preguntara durante meses. :) jaja :)
moshfiqur
58

Sea A la cantidad de milisegundos. Entonces tiene:

seconds=(A/1000)%60
minutes=(A/(1000*60))%60
hours=(A/(1000*60*60))%24

y así sucesivamente ( %es el operador de módulo).

Espero que esto ayude.

Gabriele D'Antona
fuente
@sabbibJAVA 24 debería haber funcionado. En que idioma estas Si /realiza una división de punto flotante, debe truncar el valor. Se asume en otras respuestas que /está realizando una división de enteros.
Brian J
24

Ambas soluciones a continuación usan javascript (¡no tenía idea de que la solución era independiente del idioma!). Ambas soluciones deberán ampliarse si se capturan duraciones > 1 month.

Solución 1: use el objeto Date

var date = new Date(536643021);
var str = '';
str += date.getUTCDate()-1 + " days, ";
str += date.getUTCHours() + " hours, ";
str += date.getUTCMinutes() + " minutes, ";
str += date.getUTCSeconds() + " seconds, ";
str += date.getUTCMilliseconds() + " millis";
console.log(str);

Da:

"6 days, 5 hours, 4 minutes, 3 seconds, 21 millis"

Las bibliotecas son útiles, pero ¿por qué usar una biblioteca cuando puedes reinventar la rueda? :)

Solución 2: escriba su propio analizador

var getDuration = function(millis){
    var dur = {};
    var units = [
        {label:"millis",    mod:1000},
        {label:"seconds",   mod:60},
        {label:"minutes",   mod:60},
        {label:"hours",     mod:24},
        {label:"days",      mod:31}
    ];
    // calculate the individual unit values...
    units.forEach(function(u){
        millis = (millis - (dur[u.label] = (millis % u.mod))) / u.mod;
    });
    // convert object to a string representation...
    var nonZero = function(u){ return dur[u.label]; };
    dur.toString = function(){
        return units
            .reverse()
            .filter(nonZero)
            .map(function(u){
                return dur[u.label] + " " + (dur[u.label]==1?u.label.slice(0,-1):u.label);
            })
            .join(', ');
    };
    return dur;
};

Crea un objeto de "duración", con los campos que necesite. Dar formato a una marca de tiempo se vuelve simple ...

console.log(getDuration(536643021).toString());

Da:

"6 days, 5 hours, 4 minutes, 3 seconds, 21 millis"
Nick Grealy
fuente
Cambie esa línea para que sea singular y plural return dur[u.label] + " " + (dur[u.label]==1?u.label.slice(0,-1):u.label);
Phillip Kamikaze
1
@PhillipKamikaze ¡Gracias Phillip! He incorporado tu sugerencia.
Nick Grealy
Probablemente no desee mostrar segmentos con valores cero, por lo que se podría agregar el siguiente filtro ... var nonZero = function(u){ return !u.startsWith("0"); }; // convert object to a string representation... dur.toString = function(){ return units.reverse().map(function(u){ return dur[u.label] + " " + (dur[u.label]==1?u.label.slice(0,-1):u.label); }).filter(nonZero).join(', '); };
Ruslan Ulanov
1
¡Gracias @RuslanUlanov! Lo agregué al ejemplo (aunque con una pequeña modificación para verificar si el número es "verdadero").
Nick Grealy
7

Debe usar las funciones de fecha y hora de cualquier idioma que esté usando, pero, solo por diversión, aquí está el código:

int milliseconds = someNumber;

int seconds = milliseconds / 1000;

int minutes = seconds / 60;

seconds %= 60;

int hours = minutes / 60;

minutes %= 60;

int days = hours / 24;

hours %= 24;
albertein
fuente
4

Este es un método que escribí. Toma un integer milliseconds valuey devuelve un human-readable String:

public String convertMS(int ms) {
    int seconds = (int) ((ms / 1000) % 60);
    int minutes = (int) (((ms / 1000) / 60) % 60);
    int hours = (int) ((((ms / 1000) / 60) / 60) % 24);

    String sec, min, hrs;
    if(seconds<10)  sec="0"+seconds;
    else            sec= ""+seconds;
    if(minutes<10)  min="0"+minutes;
    else            min= ""+minutes;
    if(hours<10)    hrs="0"+hours;
    else            hrs= ""+hours;

    if(hours == 0)  return min+":"+sec;
    else    return hrs+":"+min+":"+sec;

}
iTurki
fuente
4
function convertTime(time) {        
    var millis= time % 1000;
    time = parseInt(time/1000);
    var seconds = time % 60;
    time = parseInt(time/60);
    var minutes = time % 60;
    time = parseInt(time/60);
    var hours = time % 24;
    var out = "";
    if(hours && hours > 0) out += hours + " " + ((hours == 1)?"hr":"hrs") + " ";
    if(minutes && minutes > 0) out += minutes + " " + ((minutes == 1)?"min":"mins") + " ";
    if(seconds && seconds > 0) out += seconds + " " + ((seconds == 1)?"sec":"secs") + " ";
    if(millis&& millis> 0) out += millis+ " " + ((millis== 1)?"msec":"msecs") + " ";
    return out.trim();
}
Rajiv
fuente
2

Sugeriría usar cualquier función / biblioteca de fecha / hora que proporcione su lenguaje / marco de elección. Consulte también las funciones de formato de cadena, ya que a menudo proporcionan formas fáciles de pasar las marcas de fecha / hora y generar un formato de cadena legible por humanos.

theraccoonbear
fuente
2

Tus elecciones son simples:

  1. Escriba el código para hacer la conversión (es decir, divida por milisegundos por día para obtener días y use el módulo para dividir por milisegundos por hora para obtener horas y use el módulo para dividir por milisegundos por minuto y divida por 1000 por segundos. Milisegundos por minuto = 60000, milisegundos por hora = 60 * milliSecondsPerMinute, milliSecondsPerDay = 24 * milliSecondsPerHour.
  2. Utilice una rutina operativa de algún tipo. Tanto UNIX como Windows tienen estructuras que puede obtener de un valor de tipo Ticks o segundos.
pedestal
fuente
2
Long serverUptimeSeconds = 
    (System.currentTimeMillis() - SINCE_TIME_IN_MILLISECONDS) / 1000;


String serverUptimeText = 
String.format("%d days %d hours %d minutes %d seconds",
serverUptimeSeconds / 86400,
( serverUptimeSeconds % 86400) / 3600 ,
((serverUptimeSeconds % 86400) % 3600 ) / 60,
((serverUptimeSeconds % 86400) % 3600 ) % 60
);
Krolique
fuente
2
Long expireTime = 69l;
Long tempParam = 0l;

Long seconds = math.mod(expireTime, 60);
tempParam = expireTime - seconds;
expireTime = tempParam/60;
Long minutes = math.mod(expireTime, 60);
tempParam = expireTime - minutes;
expireTime = expireTime/60;
Long hours = math.mod(expireTime, 24);
tempParam = expireTime - hours;
expireTime = expireTime/24;
Long days = math.mod(expireTime, 30);

system.debug(days + '.' + hours + ':' + minutes + ':' + seconds);

Esto debería imprimir: 0.0: 1: 9

Como lo
fuente
2

¿Por qué no haces algo como esto?

var ms = 86400;

var segundos = ms / 1000; //86.4

var minutos = segundos / 60; //1.4400000000000002

var horas = minutos / 60; //0.024000000000000004

var días = horas / 24; //0.0010000000000000002

Y lidiar con la precisión flotante, por ejemplo, Number (minutes.toFixed (5)) //1.44

Pavel Blagodov
fuente
2

En java

public static String formatMs(long millis) {
    long hours = TimeUnit.MILLISECONDS.toHours(millis);
    long mins = TimeUnit.MILLISECONDS.toMinutes(millis);
    long secs = TimeUnit.MILLISECONDS.toSeconds(millis);
    return String.format("%dh %d min, %d sec",
            hours,
            mins - TimeUnit.HOURS.toMinutes(hours),
            secs - TimeUnit.MINUTES.toSeconds(mins)
    );
}

Da algo como esto:

12h 1 min, 34 sec
Camilo Silva
fuente
1

No puedo comentar la primera respuesta a su pregunta, pero hay un pequeño error. Debe usar parseInt o Math.floor para convertir números de punto flotante a enteros, i

var days, hours, minutes, seconds, x;
x = ms / 1000;
seconds = Math.floor(x % 60);
x /= 60;
minutes = Math.floor(x % 60);
x /= 60;
hours = Math.floor(x % 24);
x /= 24;
days = Math.floor(x);

Personalmente, uso CoffeeScript en mis proyectos y mi código se ve así:

getFormattedTime : (ms)->
        x = ms / 1000
        seconds = Math.floor x % 60
        x /= 60
        minutes = Math.floor x % 60
        x /= 60
        hours = Math.floor x % 24
        x /= 24
        days = Math.floor x
        formattedTime = "#{seconds}s"
        if minutes then formattedTime = "#{minutes}m " + formattedTime
        if hours then formattedTime = "#{hours}h " + formattedTime
        formattedTime 
Rafal Pastuszak
fuente
1

Esta es una solucion. Más tarde, puede dividir por ":" y tomar los valores de la matriz

/**
 * Converts milliseconds to human readeable language separated by ":"
 * Example: 190980000 --> 2:05:3 --> 2days 5hours 3min
 */
function dhm(t){
    var cd = 24 * 60 * 60 * 1000,
        ch = 60 * 60 * 1000,
        d = Math.floor(t / cd),
        h = '0' + Math.floor( (t - d * cd) / ch),
        m = '0' + Math.round( (t - d * cd - h * ch) / 60000);
    return [d, h.substr(-2), m.substr(-2)].join(':');
}

var delay = 190980000;                   
var fullTime = dhm(delay);
console.log(fullTime);
ssamuel68
fuente
1

Aquí está mi solución usando TimeUnit.

ACTUALIZACIÓN: Debo señalar que esto está escrito en groovy, pero Java es casi idéntico.

def remainingStr = ""

/* Days */
int days = MILLISECONDS.toDays(remainingTime) as int
remainingStr += (days == 1) ? '1 Day : ' : "${days} Days : "
remainingTime -= DAYS.toMillis(days)

/* Hours */
int hours = MILLISECONDS.toHours(remainingTime) as int
remainingStr += (hours == 1) ? '1 Hour : ' : "${hours} Hours : "
remainingTime -= HOURS.toMillis(hours)

/* Minutes */
int minutes = MILLISECONDS.toMinutes(remainingTime) as int
remainingStr += (minutes == 1) ? '1 Minute : ' : "${minutes} Minutes : "
remainingTime -= MINUTES.toMillis(minutes)

/* Seconds */
int seconds = MILLISECONDS.toSeconds(remainingTime) as int
remainingStr += (seconds == 1) ? '1 Second' : "${seconds} Seconds"
dafunker
fuente
1

Una forma flexible de hacerlo:
(no está hecho para la fecha actual, pero lo suficientemente bueno para duraciones)

/**
convert duration to a ms/sec/min/hour/day/week array
@param {int}        msTime              : time in milliseconds 
@param {bool}       fillEmpty(optional) : fill array values even when they are 0.
@param {string[]}   suffixes(optional)  : add suffixes to returned values.
                                        values are filled with missings '0'
@return {int[]/string[]} : time values from higher to lower(ms) range.
*/
var msToTimeList=function(msTime,fillEmpty,suffixes){
    suffixes=(suffixes instanceof Array)?suffixes:[];   //suffixes is optional
    var timeSteps=[1000,60,60,24,7];    // time ranges : ms/sec/min/hour/day/week
    timeSteps.push(1000000);    //add very big time at the end to stop cutting
    var result=[];
    for(var i=0;(msTime>0||i<1||fillEmpty)&&i<timeSteps.length;i++){
        var timerange = msTime%timeSteps[i];
        if(typeof(suffixes[i])=="string"){
            timerange+=suffixes[i]; // add suffix (converting )
            // and fill zeros :
            while(  i<timeSteps.length-1 &&
                    timerange.length<((timeSteps[i]-1)+suffixes[i]).length  )
                timerange="0"+timerange;
        }
        result.unshift(timerange);  // stack time range from higher to lower
        msTime = Math.floor(msTime/timeSteps[i]);
    }
    return result;
};

NB: también puede establecer timeSteps como parámetro si desea controlar los rangos de tiempo.

cómo usar (copiar una prueba):

var elsapsed = Math.floor(Math.random()*3000000000);

console.log(    "elsapsed (labels) = "+
        msToTimeList(elsapsed,false,["ms","sec","min","h","days","weeks"]).join("/")    );

console.log(    "half hour : "+msToTimeList(elsapsed,true)[3]<30?"first":"second"   );

console.log(    "elsapsed (classic) = "+
        msToTimeList(elsapsed,false,["","","","","",""]).join(" : ")    );
yorg
fuente
1

Sugiero usar http://www.ocpsoft.org/prettytime/ library ..

es muy simple obtener el intervalo de tiempo en forma legible por humanos como

PrettyTime p = new PrettyTime(); System.out.println(p.format(new Date()));

se imprimirá como "momentos a partir de ahora"

otro ejemplo

PrettyTime p = new PrettyTime()); Date d = new Date(System.currentTimeMillis()); d.setHours(d.getHours() - 1); String ago = p.format(d);

luego cadena hace = "hace 1 hora"

DroidDev
fuente
0

Aquí hay un método más preciso en JAVA, he implementado esta lógica simple, espero que esto te ayude:

    public String getDuration(String _currentTimemilliSecond)
    {
        long _currentTimeMiles = 1;         
        int x = 0;
        int seconds = 0;
        int minutes = 0;
        int hours = 0;
        int days = 0;
        int month = 0;
        int year = 0;

        try 
        {
            _currentTimeMiles = Long.parseLong(_currentTimemilliSecond);
            /**  x in seconds **/   
            x = (int) (_currentTimeMiles / 1000) ; 
            seconds = x ;

            if(seconds >59)
            {
                minutes = seconds/60 ;

                if(minutes > 59)
                {
                    hours = minutes/60;

                    if(hours > 23)
                    {
                        days = hours/24 ;

                        if(days > 30)
                        {
                            month = days/30;

                            if(month > 11)
                            {
                                year = month/12;

                                Log.d("Year", year);
                                Log.d("Month", month%12);
                                Log.d("Days", days % 30);
                                Log.d("hours ", hours % 24);
                                Log.d("Minutes ", minutes % 60);
                                Log.d("Seconds  ", seconds % 60);   

                                return "Year "+year + " Month "+month%12 +" Days " +days%30 +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
                            }
                            else
                            {
                                Log.d("Month", month);
                                Log.d("Days", days % 30);
                                Log.d("hours ", hours % 24);
                                Log.d("Minutes ", minutes % 60);
                                Log.d("Seconds  ", seconds % 60);   

                                return "Month "+month +" Days " +days%30 +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
                            }

                        }
                        else
                        {
                            Log.d("Days", days );
                            Log.d("hours ", hours % 24);
                            Log.d("Minutes ", minutes % 60);
                            Log.d("Seconds  ", seconds % 60);   

                            return "Days " +days +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
                        }

                    }
                    else
                    {
                        Log.d("hours ", hours);
                        Log.d("Minutes ", minutes % 60);
                        Log.d("Seconds  ", seconds % 60);

                        return "hours "+hours+" Minutes "+minutes %60+" Seconds "+seconds%60;
                    }
                }
                else
                {
                    Log.d("Minutes ", minutes);
                    Log.d("Seconds  ", seconds % 60);

                    return "Minutes "+minutes +" Seconds "+seconds%60;
                }
            }
            else
            {
                Log.d("Seconds ", x);
                return " Seconds "+seconds;
            }
        }
        catch (Exception e) 
        {
            Log.e(getClass().getName().toString(), e.toString());
        }
        return "";
    }

    private Class Log
    {
        public static void d(String tag , int value)
        {
            System.out.println("##### [ Debug ]  ## "+tag +" :: "+value);
        }
    }
AK Joshi
fuente