125

I need to convert an arbitrary amount of milliseconds into Days, Hours, Minutes Second.

For example: 10 Days, 5 hours, 13 minutes, 1 second.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
FlySwat
  • 172,459
  • 74
  • 246
  • 311
  • "The language I'm using does not have this built in, otherwise I'd use it." I find that hard to understand. What language? What OS? – S.Lott Oct 06 '08 at 18:38
  • ActionScript, any OS, it has miserable date/time support – FlySwat Oct 06 '08 at 18:40
  • 3
    I don't know of any language that has what he's asking for, nor do I see any reason why it would. Some very simple division/modulus math gets the answer just fine. – Kip Oct 06 '08 at 18:41
  • 1
    Not all years have the same number of days, so you would have to state which period was it. Or maybe, you just want it in 'standard' years (365.something)? – Milan Babuškov Oct 06 '08 at 18:42
  • @Kip: Got it -- misread the question -- was thinking of OS timestamps in milliseconds. Not delta times or intervals. Tempted to edit the question... – S.Lott Oct 06 '08 at 20:15
  • here is what i did...for e.g: you have 86400000 so in windows calc (I am using windows calc same can be achieved with unix calc using appropriate syntax) do 86400000/1000 (for seconds) and then /60 (for minutes) and then /60 (for hours) and so on and so forth.... I know this is not what you asked for...but sometimes people need to get down to quick and dirty answers...like i was trying to debug some values..it was helpful and quick... :-) – user10398 Aug 20 '09 at 06:03

22 Answers22

234

Well, since nobody else has stepped up, I'll write the easy code to do this:

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

I'm just glad you stopped at days and didn't ask for months. :)

Note that in the above, it is assumed that / represents truncating integer division. If you use this code in a language where / represents floating point division, you will need to manually truncate the results of the division as needed.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 2
    Just used that in a flash function. thanks! (upvoted for simplicity) – Makram Saleh Aug 19 '09 at 12:45
  • 2
    It does not work correctly. Should use parseInt when using the divisor otherwise you will see long float values. See my answer below for a more comprehensive solution. – Rajiv Oct 31 '12 at 05:41
  • 20
    @Greg Hewgill **I'm just glad you stopped at days and didn't ask for months. :)** haha :) – moshfiqur Nov 28 '12 at 16:06
60

Let A be the amount of milliseconds. Then you have:

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

and so on (% is the modulus operator).

Hope this helps.

dbr
  • 165,801
  • 69
  • 278
  • 343
friol
  • 6,996
  • 4
  • 44
  • 81
  • @sabbibJAVA 24 should have worked. What language are you in? If `/` does floating point division, you need to truncate the value. It is assumed in other answers that `/` is performing integer division. – Brian J Jun 13 '13 at 13:16
28

Both solutions below use javascript (I had no idea the solution was language agnostic!). Both solutions will need to be extended if capturing durations > 1 month.

Solution 1: Use the Date object

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);

Gives:

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

Libraries are helpful, but why use a library when you can re-invent the wheel! :)

Solution 2: Write your own parser

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;
};

Creates a "duration" object, with whatever fields you require. Formatting a timestamp then becomes simple...

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

Gives:

"6 days, 5 hours, 4 minutes, 3 seconds, 21 millis"
Nick Grealy
  • 24,216
  • 9
  • 104
  • 119
  • Change that line to get singular and plural `return dur[u.label] + " " + (dur[u.label]==1?u.label.slice(0,-1):u.label);` – Phillip Kamikaze Jul 31 '15 at 23:09
  • 1
    @PhillipKamikaze Thanks Phillip! I've incorporated your suggestion. – Nick Grealy Jul 31 '15 at 23:17
  • You probably do not want to show segments with zero values, so the following filter could be added... `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 Aug 08 '16 at 23:34
  • 1
    Thanks @RuslanUlanov! I've added it to the example (albeit with a slight modification to check if the number is "truthy"). – Nick Grealy Aug 09 '16 at 08:29
23

Apache Commons Lang has a DurationFormatUtils that has very helpful methods like formatDurationWords.

David Dossot
  • 33,403
  • 4
  • 38
  • 72
8

You should use the datetime functions of whatever language you're using, but, just for fun here's the code:

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
  • 26,396
  • 5
  • 54
  • 57
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
  • 2,352
  • 1
  • 22
  • 25
4

In 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)
    );
}

Gives something like this:

12h 1 min, 34 sec
Camilo Silva
  • 8,283
  • 4
  • 41
  • 61
4

This is a method I wrote. It takes an integer milliseconds value and returns a 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
  • 16,292
  • 20
  • 87
  • 132
2

I would suggest using whatever date/time functions/libraries your language/framework of choice provides. Also check out string formatting functions as they often provide easy ways to pass date/timestamps and output a human readable string format.

theraccoonbear
  • 4,283
  • 3
  • 33
  • 41
2

Your choices are simple:

  1. Write the code to do the conversion (ie, divide by milliSecondsPerDay to get days and use the modulus to divide by milliSecondsPerHour to get hours and use the modulus to divide by milliSecondsPerMinute and divide by 1000 for seconds. milliSecondsPerMinute = 60000, milliSecondsPerHour = 60 * milliSecondsPerMinute, milliSecondsPerDay = 24 * milliSecondsPerHour.
  2. Use an operating routine of some kind. UNIX and Windows both have structures that you can get from a Ticks or seconds type value.
plinth
  • 48,267
  • 11
  • 78
  • 120
2

Why just don't do something like this:

var ms = 86400;

var seconds = ms / 1000; //86.4

var minutes = seconds / 60; //1.4400000000000002

var hours = minutes / 60; //0.024000000000000004

var days = hours / 24; //0.0010000000000000002

And dealing with float precision e.g. Number(minutes.toFixed(5)) //1.44

Pavel Blagodov
  • 572
  • 5
  • 6
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
  • 682
  • 9
  • 14
1

I'm not able to comment first answer to your question, but there's a small mistake. You should use parseInt or Math.floor to convert floating point numbers to integer, 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);

Personally, I use CoffeeScript in my projects and my code looks like that:

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
  • 3,100
  • 2
  • 29
  • 31
1

This is a solution. Later you can split by ":" and take the values of the array

/**
 * 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
  • 932
  • 13
  • 10
1
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);

This should print: 0.0:1:9

Asit
  • 19
  • 1
1

Here's my solution using TimeUnit.

UPDATE: I should point out that this is written in groovy, but Java is almost identical.

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
  • 519
  • 3
  • 9
1

A flexible way to do it :
(Not made for current date but good enough for durations)

/**
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 : you could also set timeSteps as parameter if you want to control the time ranges.

how to use (copy an test):

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
  • 600
  • 5
  • 7
1

I suggest to use http://www.ocpsoft.org/prettytime/ library..

it's very simple to get time interval in human readable form like

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

it will print like "moments from now"

other example

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

then string ago = "1 hour ago"

Vishal Makasana
  • 960
  • 2
  • 7
  • 15
1

In python 3 you could achieve your goal by using the following snippet:

from datetime import timedelta

ms = 536643021
td = timedelta(milliseconds=ms)

print(str(td))
# --> 6 days, 5:04:03.021000

Timedelta documentation: https://docs.python.org/3/library/datetime.html#datetime.timedelta

Source of the __str__ method of timedelta str: https://github.com/python/cpython/blob/33922cb0aa0c81ebff91ab4e938a58dfec2acf19/Lib/datetime.py#L607

keocra
  • 613
  • 5
  • 10
0

Here is more precise method in JAVA , I have implemented this simple logic , hope this will help you:

    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);
        }
    }
Amit Shakya
  • 1,396
  • 12
  • 27
AK Joshi
  • 877
  • 6
  • 20
0

A solution using awk:

$ ms=10000001; awk -v ms=$ms 'BEGIN {x=ms/1000; 
                                     s=x%60; x/=60;
                                     m=x%60; x/=60;
                                     h=x%60;
                              printf("%02d:%02d:%02d.%03d\n", h, m, s, ms%1000)}'
02:46:40.001
bougui
  • 3,507
  • 4
  • 22
  • 27
0

This one leaves out 0 values. With tests.

const toTimeString = (value, singularName) =>
  `${value} ${singularName}${value !== 1 ? 's' : ''}`;

const readableTime = (ms) => {
  const days = Math.floor(ms / (24 * 60 * 60 * 1000));
  const daysMs = ms % (24 * 60 * 60 * 1000);
  const hours = Math.floor(daysMs / (60 * 60 * 1000));
  const hoursMs = ms % (60 * 60 * 1000);
  const minutes = Math.floor(hoursMs / (60 * 1000));
  const minutesMs = ms % (60 * 1000);
  const seconds = Math.round(minutesMs / 1000);

  const data = [
    [days, 'day'],
    [hours, 'hour'],
    [minutes, 'minute'],
    [seconds, 'second'],
  ];

  return data
    .filter(([value]) => value > 0)
    .map(([value, name]) => toTimeString(value, name))
    .join(', ');
};

// Tests
const hundredDaysTwentyHoursFiftyMinutesThirtySeconds = 8715030000;
const oneDayTwoHoursEightMinutesTwelveSeconds = 94092000;
const twoHoursFiftyMinutes = 10200000;
const oneMinute = 60000;
const fortySeconds = 40000;
const oneSecond = 1000;
const oneDayTwelveSeconds = 86412000;

const test = (result, expected) => {
  console.log(expected, '- ' + (result === expected));
};

test(readableTime(
  hundredDaysTwentyHoursFiftyMinutesThirtySeconds
), '100 days, 20 hours, 50 minutes, 30 seconds');

test(readableTime(
  oneDayTwoHoursEightMinutesTwelveSeconds
), '1 day, 2 hours, 8 minutes, 12 seconds');

test(readableTime(
  twoHoursFiftyMinutes
), '2 hours, 50 minutes');

test(readableTime(
  oneMinute
), '1 minute');

test(readableTime(
  fortySeconds
), '40 seconds');

test(readableTime(
  oneSecond
), '1 second');

test(readableTime(
  oneDayTwelveSeconds
), '1 day, 12 seconds');
Jonathan
  • 8,771
  • 4
  • 41
  • 78