How to convert Milliseconds to "X mins, x seconds" in Java?
Asked Answered
F

32

631

I want to record the time using System.currentTimeMillis() when a user begins something in my program. When he finishes, I will subtract the current System.currentTimeMillis() from the start variable, and I want to show them the time elapsed using a human readable format such as "XX hours, XX mins, XX seconds" or even "XX mins, XX seconds" because its not likely to take someone an hour.

What's the best way to do this?

Fleabitten answered 9/3, 2009 at 8:41 Comment(1)
If they take more than an hour you can still print something like; 90 mins, 53 secs.Helton
R
1331

Use the java.util.concurrent.TimeUnit class:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toMinutes(millis),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);

Note: TimeUnit is part of the Java 1.5 specification, but toMinutes was added as of Java 1.6.

To add a leading zero for values 0-9, just do:

String.format("%02d min, %02d sec", 
    TimeUnit.MILLISECONDS.toMinutes(millis),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);

If TimeUnit or toMinutes are unsupported (such as on Android before API version 9), use the following equations:

int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours   = (int) ((milliseconds / (1000*60*60)) % 24);
//etc...
Rhachis answered 9/3, 2009 at 10:1 Comment(12)
int months =(int)((float)days / 30.4368499f); int years = (int)((float)days / 365.242199f);Florez
Id suggest to use mod 60 instead of subtracting the minutes, it looks cleaner. However, one needs to know that 1 min = 60 sec to do that... =)Unequaled
Oh no ... why is this solution so much voted up? I would suggest not to use such long, explicit code. There are much better solutions (based on a single time object like new Date(ms), or similar using other libs) posted below considering SimpleDateFormat("mm 'min,' ss 'sec'") (Java native), DurationFormatUtils (famous commons-lang lib dependency), YodaTime (famous Yoda lib dependency) and String.format("%tT") (Java native) (I'll vote this one down and others up because the mentioned solutions should be prefered in general for best practice)Junko
@AndreasDietrich SimpleDateFormat doesn't work for time differences as it only return date from epoch!Boarfish
int hours = (int) ((milliseconds / (1000*60*60)) % 24) this doesn't work! instead it should be like this int hours = (int) (milliseconds / (1000*60*60)) ;Boarfish
Also could you please explain why are you using % operator?Boarfish
@MuhammadBabar: SimpleDateFormat I mentioned for the simple output formatting feature (a little independent of the difference calculation). If one wants to use it for this, of course one has to give it a Date object that is already a calculated difference added to new Date(0) with some additional ugly magic related to the underlying timezone stuff. The calculation is not pretty and I don't wanna mention it here, but my answer was intended to point to classes that help to encapsulate functionality using existing libraries/classes.Junko
@MuhammadBabar: The % operator (modulo) is needed to "throw away" everything bigger than the current "sub-time scope" (e.g. 91 s should become "31 sec" displayed as "1 min + 31 sec")Junko
as MuhammadBabar mentioned the biggest time/date part in the calculation above should not use the % (modulo) operator since it should not be divided by some factor even if it looks inconvinient if an hour may look bigger than expected, e.g. 30 days displayed as "hh:mm:ss" would look like "720:00:00" (correct) and not "00:00:00" (incorrect) (if moduloed by %) .. all these problems because its complicated and using libraries prevents such hassle!Junko
If somebody wants a format for video files (h:mm:ss): String.format("%01d:%02d:%02d", hours, minutes, seconds);Emilia
what about leap seconds? That my break some to the suggested conversions.Do
There is a problem. When milliseconds is 59999, actually it is 1 minute but it will be computed as 59 seconds and 999 milliseconds is lost.Expenditure
Q
136

Based on @siddhadev's answer, I wrote a function which converts milliseconds to a formatted string:

   /**
     * Convert a millisecond duration to a string format
     * 
     * @param millis A duration to convert to a string form
     * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
     */
    public static String getDurationBreakdown(long millis) {
        if(millis < 0) {
            throw new IllegalArgumentException("Duration must be greater than zero!");
        }

        long days = TimeUnit.MILLISECONDS.toDays(millis);
        millis -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        millis -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
        millis -= TimeUnit.MINUTES.toMillis(minutes);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);

        StringBuilder sb = new StringBuilder(64);
        sb.append(days);
        sb.append(" Days ");
        sb.append(hours);
        sb.append(" Hours ");
        sb.append(minutes);
        sb.append(" Minutes ");
        sb.append(seconds);
        sb.append(" Seconds");

        return(sb.toString());
    }
Quito answered 5/10, 2011 at 15:41 Comment(2)
You should do a checking there for single/multiple, in order to avoid this kind of situation : 1 Days 1 Hours 1 Minutes 1 SecondsJerol
We could use modulus function instead of subtraction: long days = TimeUnit.MILLISECONDS.toDays(millis); long hours = TimeUnit.MILLISECONDS.toHours(millis) % 24; long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60; long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60; long milliseconds = millis % 1000; and also String.format method: return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds", days, hours, minutes, seconds, milliseconds);Faux
S
93
long time = 1536259;

return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time));

Prints:

25:36:259

Strobila answered 16/2, 2012 at 12:14 Comment(6)
I like the above approach the best if for nothing else its simplicity! Since we are dealing with times and durations I typically use Joda. An example if you have two DateTimes, start and end respectively: Duration dur = new Duration(start, end); long millis = dur.getMillis();Ornithine
I should have noted 2 ways to use Joda formatters. First variation on your theme: DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time)); Or convert the Duration to a Period that can automatically be printed using a Joda PeriodFormatter. The conversion could have a loss of precision if other than ISO chronology. Suppose a Duration represented by the variable duration. Period period = duration.toPeriod().normalizedStandard(PeriodType.time()); PeriodFormat.getDefault().print(period)) Output is awesome: 1 second and 581 milliseconds, answering the main question above.Ornithine
A bit late here :) But wouldn't you need to put simpleDateFormat.setTimezone(TimeZone.getTimeZone("GMT")) here unless that is your actual timezone?Arruda
@OlleSöderström There is indeed an issue with timezone here. But setting it to GMT or UTC causes the hour part to be 12 instead of 0 for all durations shorter than 1 hour.Walburga
Timezone isn't the only issue here... this answer is misleading and could seriously confuse Java newbies. Even ignoring the redundant outer brackets, the OP asked how to present a duration (a difference between two points in time, measured in ms). Calling that duration "time" and treating it as an offset since 1 Jan, 1970 just for the sake of formatting its smaller components is just... wrong imo. What's more, the very same approach had already been suggested 3 years earlier by this answer (see comments there for more details on timezone problems).Kopp
It builds 2 objects, one of which is very heavy (Date), depending on the amount of data to be handled, this could be slowGrus
C
38

Using the java.time package in Java 8:

Instant start = Instant.now();
Thread.sleep(63553);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

Output is in ISO 8601 Duration format: PT1M3.553S (1 minute and 3.553 seconds).

Clause answered 19/4, 2014 at 23:9 Comment(3)
See also How to format a duration in java? (e.g format H:MM:SS)Vanadous
(ANDROID) Requires API level 26Electrocute
@SomeoneSomewhere For Android under API level 26 use the backport, see How to use ThreeTenABP in Android Project.Monopetalous
D
36

Uhm... how many milliseconds are in a second? And in a minute? Division is not that hard.

int seconds = (int) ((milliseconds / 1000) % 60);
int minutes = (int) ((milliseconds / 1000) / 60);

Continue like that for hours, days, weeks, months, year, decades, whatever.

Dela answered 9/3, 2009 at 8:42 Comment(3)
Actually, doing this for anything longer than an hour is not a good idea since the results could be wrong/unintuitive when daylight savings time (days of 23 or 24 hours) or leap years are involved. If I read "X will happen in 1 year/month", I'd expect it to be the same date and time.Rochellrochella
System.currentTimeMillis() is immune against DST so this will not be confused by additional or missing hours. If you need to show the difference between two specific dates, you’re better off constructing Date objects with the given time and show the difference between those two.Dela
Beyond weeks, it is undefined, since month length is variable. So indeed, you need to compute relative to a given time reference.Condescendence
S
30

I would not pull in the extra dependency just for that (division is not that hard, after all), but if you are using Commons Lang anyway, there are the DurationFormatUtils.

Example Usage (adapted from here):

import org.apache.commons.lang3.time.DurationFormatUtils

public String getAge(long value) {
    long currentTime = System.currentTimeMillis();
    long age = currentTime - value;
    String ageString = DurationFormatUtils.formatDuration(age, "d") + "d";
    if ("0d".equals(ageString)) {
        ageString = DurationFormatUtils.formatDuration(age, "H") + "h";
        if ("0h".equals(ageString)) {
            ageString = DurationFormatUtils.formatDuration(age, "m") + "m";
            if ("0m".equals(ageString)) {
                ageString = DurationFormatUtils.formatDuration(age, "s") + "s";
                if ("0s".equals(ageString)) {
                    ageString = age + "ms";
                }
            }
        }
    }
    return ageString;
}   

Example:

long lastTime = System.currentTimeMillis() - 2000;
System.out.println("Elapsed time: " + getAge(lastTime)); 

//Output: 2s

Note: To get millis from two LocalDateTime objects you can use:

long age = ChronoUnit.MILLIS.between(initTime, LocalDateTime.now())
Swearword answered 9/3, 2009 at 8:48 Comment(2)
Great, I was just asking myself if there was a robust library that included this sort of things.Beamon
As a link is generally not very useful, I added an example on how can it be used.Lithoid
B
28

Either hand divisions, or use the SimpleDateFormat API.

long start = System.currentTimeMillis();
// do your work...
long elapsed = System.currentTimeMillis() - start;
DateFormat df = new SimpleDateFormat("HH 'hours', mm 'mins,' ss 'seconds'");
df.setTimeZone(TimeZone.getTimeZone("GMT+0"));
System.out.println(df.format(new Date(elapsed)));

Edit by Bombe: It has been shown in the comments that this approach only works for smaller durations (i.e. less than a day).

Bernina answered 9/3, 2009 at 8:45 Comment(6)
Wow. That is an evil, timezone-dependent hack. It will break mercilessly when you have a timezone offset that is not a multiple of 60 minutes (and we have a couple of those pesky 30-minute offset timezones in the world).Dela
Also, it will break just as bad as soon as you include the hours in the format string and are not at GMT+0, for the same reasons.Dela
We do? Really? Where? Not doubting you, just never heard of it before - some new pitfall to consider ;-)Geology
Yes. Check “List of time zones” on Wikipedia, e.g. Nepal is at GMT+05:45.Dela
Yeah, and Hyderabad is GMT+5.5 :\Bonni
cadrian, now it will only work for durations less than a day. The number of hours will always be between 0 and 23, inclusive.Dela
U
24

Just to add more info if you want to format like: HH:mm:ss

0 <= HH <= infinite

0 <= mm < 60

0 <= ss < 60

use this:

int h = (int) ((startTimeInMillis / 1000) / 3600);
int m = (int) (((startTimeInMillis / 1000) / 60) % 60);
int s = (int) ((startTimeInMillis / 1000) % 60);

I just had this issue now and figured this out

Untangle answered 25/5, 2011 at 16:52 Comment(1)
Best answer here. Why does everyone want to make things so complicated? This is simple math, folks.Aguayo
C
14

Shortest solution:

Here's probably the shortest which also deals with time zones.

System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());

Which outputs for example:

00:18:32

Explanation:

%tT is the time formatted for the 24-hour clock as %tH:%tM:%tS.

%tT also accepts longs as input, so no need to create a Date. printf() will simply print the time specified in milliseconds, but in the current time zone therefore we have to subtract the raw offset of the current time zone so that 0 milliseconds will be 0 hours and not the time offset value of the current time zone.

Note #1: If you need the result as a String, you can get it like this:

String t = String.format("%tT", millis-TimeZone.getDefault().getRawOffset());

Note #2: This only gives correct result if millis is less than a day because the day part is not included in the output.

Clown answered 17/7, 2014 at 9:34 Comment(3)
This is such a great short cut, but when I use it I don't get the expected results. So I have: long millis = 8398; and when I pass that to String.format("%tT", millis) my output is 19:00:08. Where does the 19 come from?Scream
@Scream That's the offset of your timezone. You have to subtract TimeZone.getDefault().getRawOffset() from it, exactly as written in the answer: String.format("%tT", millis-TimeZone.getDefault().getRawOffset())Clown
that took care of it. Thank you for clarifying.Scream
F
13

Revisiting @brent-nash contribution, we could use modulus function instead of subtractions and use String.format method for the result string:

  /**
   * Convert a millisecond duration to a string format
   * 
   * @param millis A duration to convert to a string form
   * @return A string of the form "X Days Y Hours Z Minutes A Seconds B Milliseconds".
   */
   public static String getDurationBreakdown(long millis) {
       if (millis < 0) {
          throw new IllegalArgumentException("Duration must be greater than zero!");
       }

       long days = TimeUnit.MILLISECONDS.toDays(millis);
       long hours = TimeUnit.MILLISECONDS.toHours(millis) % 24;
       long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60;
       long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;
       long milliseconds = millis % 1000;

       return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds",
                            days, hours, minutes, seconds, milliseconds);
   }
Faux answered 13/8, 2016 at 9:48 Comment(0)
M
11

I think the best way is:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toSeconds(length)/60,
    TimeUnit.MILLISECONDS.toSeconds(length) % 60 );
Macswan answered 5/4, 2011 at 15:4 Comment(1)
for minutes you can use TimeUnit.MILLISECONDS.toMinutes(length)Height
B
9

Joda-Time

Using Joda-Time:

DateTime startTime = new DateTime();

// do something

DateTime endTime = new DateTime();
Duration duration = new Duration(startTime, endTime);
Period period = duration.toPeriod().normalizedStandard(PeriodType.time());
System.out.println(PeriodFormat.getDefault().print(period));
Bipod answered 13/11, 2013 at 14:24 Comment(1)
No need for that PeriodFormat in the last line. Simply call Period::toString to get an ISO 8601 Duration string by default.Selfsupporting
B
9

For those who looking for Kotlin code:

fun converter(millis: Long): String =
        String.format(
            "%02d : %02d : %02d",
            TimeUnit.MILLISECONDS.toHours(millis),
            TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(
                TimeUnit.MILLISECONDS.toHours(millis)
            ),
            TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(
                TimeUnit.MILLISECONDS.toMinutes(millis)
            )
        )

Sample output: 09 : 10 : 26

Burkey answered 5/1, 2021 at 11:26 Comment(0)
H
8

Firstly, System.currentTimeMillis() and Instant.now() are not ideal for timing. They both report the wall-clock time, which the computer doesn't know precisely, and which can move erratically, including going backwards if for example the NTP daemon corrects the system time. If your timing happens on a single machine then you should instead use System.nanoTime().

Secondly, from Java 8 onwards java.time.Duration is the best way to represent a duration:

long start = System.nanoTime();
// do things...
long end = System.nanoTime();
Duration duration = Duration.ofNanos(end - start);
System.out.println(duration); // Prints "PT18M19.511627776S"
System.out.printf("%d Hours %d Minutes %d Seconds%n",
        duration.toHours(), duration.toMinutes() % 60, duration.getSeconds() % 60);
// prints "0 Hours 18 Minutes 19 Seconds"
Hillman answered 13/9, 2019 at 15:17 Comment(1)
It's one of the first results, when you google it in combination of "android".Jubilee
H
6

My simple calculation:

String millisecToTime(int millisec) {
    int sec = millisec/1000;
    int second = sec % 60;
    int minute = sec / 60;
    if (minute >= 60) {
        int hour = minute / 60;
        minute %= 60;
        return hour + ":" + (minute < 10 ? "0" + minute : minute) + ":" + (second < 10 ? "0" + second : second);
    }
    return minute + ":" + (second < 10 ? "0" + second : second);
}

Happy coding :)

Hydrophyte answered 10/1, 2017 at 7:16 Comment(1)
I suppose long is more appropriate for this function as System.currentTimeMillis() returns a long value.Urochrome
C
5

for Android below API 9

(String.format("%d hr %d min, %d sec", millis/(1000*60*60), (millis%(1000*60*60))/(1000*60), ((millis%(1000*60*60))%(1000*60))/1000)) 
Coadjutrix answered 6/7, 2012 at 6:39 Comment(0)
S
4

For small times, less than an hour, I prefer:

long millis = ...

System.out.printf("%1$TM:%1$TS", millis);
// or
String str = String.format("%1$TM:%1$TS", millis);

for longer intervalls:

private static final long HOUR = TimeUnit.HOURS.toMillis(1);
...
if (millis < HOUR) {
    System.out.printf("%1$TM:%1$TS%n", millis);
} else {
    System.out.printf("%d:%2$TM:%2$TS%n", millis / HOUR, millis % HOUR);
}
Stater answered 5/4, 2011 at 15:49 Comment(3)
That's a precious hint, there are many such possibilities for date and time with Java Formatter API (docs.oracle.com/javase/8/docs/api/java/util/Formatter.html)! You could also have the else condition result with: System.out.printf("%1$tH:%1$tM:%1$tS%n", millis); or even System.out.printf("%1$tT%n", millis);Faux
@JoseTepedino but you are aware that %tH only shows from 0 up to 23 hours ? That means that for example 24 hours would be displayed as 00, 25 hours as 01... same valid for %tT - days will be silently discarded. Sure, could also have days displayed, but that would be an overkill for the problem I had when I wrote this (back in 2011) [:-)Stater
I see... that would really only work for times less than a day (24h). Thank you.Faux
F
4
    long startTime = System.currentTimeMillis();
    // do your work...
    long endTime=System.currentTimeMillis();
    long diff=endTime-startTime;       
    long hours=TimeUnit.MILLISECONDS.toHours(diff);
    diff=diff-(hours*60*60*1000);
    long min=TimeUnit.MILLISECONDS.toMinutes(diff);
    diff=diff-(min*60*1000);
    long seconds=TimeUnit.MILLISECONDS.toSeconds(diff);
    //hour, min and seconds variables contains the time elapsed on your work
Footlight answered 19/4, 2012 at 8:14 Comment(1)
The formula on line 6 is wrong. diff=diff-(hours*60*1000); should be diff=diff-(hours*60*60*1000);. I tried editing it but StackOverflow's annoying edit policy says it's not enough characters for an edit.Bassoon
T
4

Here is an answer based on Brent Nash answer, Hope that helps !

public static String getDurationBreakdown(long millis)
{
    String[] units = {" Days ", " Hours ", " Minutes ", " Seconds "};
    Long[] values = new Long[units.length];
    if(millis < 0)
    {
        throw new IllegalArgumentException("Duration must be greater than zero!");
    }

    values[0] = TimeUnit.MILLISECONDS.toDays(millis);
    millis -= TimeUnit.DAYS.toMillis(values[0]);
    values[1] = TimeUnit.MILLISECONDS.toHours(millis);
    millis -= TimeUnit.HOURS.toMillis(values[1]);
    values[2] = TimeUnit.MILLISECONDS.toMinutes(millis);
    millis -= TimeUnit.MINUTES.toMillis(values[2]);
    values[3] = TimeUnit.MILLISECONDS.toSeconds(millis);

    StringBuilder sb = new StringBuilder(64);
    boolean startPrinting = false;
    for(int i = 0; i < units.length; i++){
        if( !startPrinting && values[i] != 0)
            startPrinting = true;
        if(startPrinting){
            sb.append(values[i]);
            sb.append(units[i]);
        }
    }

    return(sb.toString());
}
Tweedsmuir answered 25/6, 2013 at 15:12 Comment(0)
M
4

This is easier in Java 9:

    Duration elapsedTime = Duration.ofMillis(millisDiff );
    String humanReadableElapsedTime = String.format(
            "%d hours, %d mins, %d seconds",
            elapsedTime.toHours(),
            elapsedTime.toMinutesPart(),
            elapsedTime.toSecondsPart());

This produces a string like 0 hours, 39 mins, 9 seconds.

If you want to round to whole seconds before formatting:

    elapsedTime = elapsedTime.plusMillis(500).truncatedTo(ChronoUnit.SECONDS);

To leave out the hours if they are 0:

    long hours = elapsedTime.toHours();
    String humanReadableElapsedTime;
    if (hours == 0) {
        humanReadableElapsedTime = String.format(
                "%d mins, %d seconds",
                elapsedTime.toMinutesPart(),
                elapsedTime.toSecondsPart());

    } else {
        humanReadableElapsedTime = String.format(
                "%d hours, %d mins, %d seconds",
                hours,
                elapsedTime.toMinutesPart(),
                elapsedTime.toSecondsPart());
    }

Now we can have for example 39 mins, 9 seconds.

To print minutes and seconds with leading zero to make them always two digits, just insert 02 into the relevant format specifiers, thus:

    String humanReadableElapsedTime = String.format(
            "%d hours, %02d mins, %02d seconds",
            elapsedTime.toHours(),
            elapsedTime.toMinutesPart(),
            elapsedTime.toSecondsPart());

Now we can have for example 0 hours, 39 mins, 09 seconds.

Monopetalous answered 14/11, 2017 at 15:59 Comment(4)
Any formatting to remove hours/mins/seconds when a preceding number is 0? I mean it is achievable with if else condition, but what about existence of such String formatting or something close, is there any?Ballard
No, sorry, @FARID, you need if-else there.Monopetalous
for Android you will need (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)Firebrand
@MostafaImani It works for lower level Android too. For versions before Oreo (APi level 26) with coreLibraryDesugaring you can use java.time directly.Monopetalous
L
3

for correct strings ("1hour, 3sec", "3 min" but not "0 hour, 0 min, 3 sec") i write this code:

int seconds = (int)(millis / 1000) % 60 ;
int minutes = (int)((millis / (1000*60)) % 60);
int hours = (int)((millis / (1000*60*60)) % 24);
int days = (int)((millis / (1000*60*60*24)) % 365);
int years = (int)(millis / 1000*60*60*24*365);

ArrayList<String> timeArray = new ArrayList<String>();

if(years > 0)   
    timeArray.add(String.valueOf(years)   + "y");

if(days > 0)    
    timeArray.add(String.valueOf(days) + "d");

if(hours>0)   
    timeArray.add(String.valueOf(hours) + "h");

if(minutes>0) 
    timeArray.add(String.valueOf(minutes) + "min");

if(seconds>0) 
    timeArray.add(String.valueOf(seconds) + "sec");

String time = "";
for (int i = 0; i < timeArray.size(); i++) 
{
    time = time + timeArray.get(i);
    if (i != timeArray.size() - 1)
        time = time + ", ";
}

if (time == "")
  time = "0 sec";
Load answered 8/2, 2012 at 15:57 Comment(0)
A
3

If you know the time difference would be less than an hour, then you can use following code:

    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();

    c2.add(Calendar.MINUTE, 51);

    long diff = c2.getTimeInMillis() - c1.getTimeInMillis();

    c2.set(Calendar.MINUTE, 0);
    c2.set(Calendar.HOUR, 0);
    c2.set(Calendar.SECOND, 0);

    DateFormat df = new SimpleDateFormat("mm:ss");
    long diff1 = c2.getTimeInMillis() + diff;
    System.out.println(df.format(new Date(diff1)));

It will result to: 51:00

Aftmost answered 22/9, 2014 at 11:34 Comment(0)
U
3

This answer is similar to some answers above. However, I feel that it would be beneficial because, unlike other answers, this will remove any extra commas or whitespace and handles abbreviation.

/**
 * Converts milliseconds to "x days, x hours, x mins, x secs"
 * 
 * @param millis
 *            The milliseconds
 * @param longFormat
 *            {@code true} to use "seconds" and "minutes" instead of "secs" and "mins"
 * @return A string representing how long in days/hours/minutes/seconds millis is.
 */
public static String millisToString(long millis, boolean longFormat) {
    if (millis < 1000) {
        return String.format("0 %s", longFormat ? "seconds" : "secs");
    }
    String[] units = {
            "day", "hour", longFormat ? "minute" : "min", longFormat ? "second" : "sec"
    };
    long[] times = new long[4];
    times[0] = TimeUnit.DAYS.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[0], TimeUnit.DAYS);
    times[1] = TimeUnit.HOURS.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[1], TimeUnit.HOURS);
    times[2] = TimeUnit.MINUTES.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[2], TimeUnit.MINUTES);
    times[3] = TimeUnit.SECONDS.convert(millis, TimeUnit.MILLISECONDS);
    StringBuilder s = new StringBuilder();
    for (int i = 0; i < 4; i++) {
        if (times[i] > 0) {
            s.append(String.format("%d %s%s, ", times[i], units[i], times[i] == 1 ? "" : "s"));
        }
    }
    return s.toString().substring(0, s.length() - 2);
}

/**
 * Converts milliseconds to "x days, x hours, x mins, x secs"
 * 
 * @param millis
 *            The milliseconds
 * @return A string representing how long in days/hours/mins/secs millis is.
 */
public static String millisToString(long millis) {
    return millisToString(millis, false);
}
Uniformitarian answered 18/3, 2015 at 4:20 Comment(0)
E
3

There is a problem. When milliseconds is 59999, actually it is 1 minute but it will be computed as 59 seconds and 999 milliseconds is lost.

Here is a modified version based on previous answers, which can solve this loss:

public static String formatTime(long millis) {
    long seconds = Math.round((double) millis / 1000);
    long hours = TimeUnit.SECONDS.toHours(seconds);
    if (hours > 0)
        seconds -= TimeUnit.HOURS.toSeconds(hours);
    long minutes = seconds > 0 ? TimeUnit.SECONDS.toMinutes(seconds) : 0;
    if (minutes > 0)
        seconds -= TimeUnit.MINUTES.toSeconds(minutes);
    return hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d", minutes, seconds);
}
Expenditure answered 23/9, 2018 at 14:6 Comment(0)
V
2

I have covered this in another answer but you can do:

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {
    long diffInMillies = date2.getTime() - date1.getTime();
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;
    for ( TimeUnit unit : units ) {
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;
        result.put(unit,diff);
    }
    return result;
}

The output is something like Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}, with the units ordered.

It's up to you to figure out how to internationalize this data according to the target locale.

Vanny answered 29/1, 2016 at 10:23 Comment(0)
B
2

DurationFormatUtils.formatDurationHMS(long)

Bhang answered 15/5, 2019 at 7:42 Comment(0)
M
2

This topic has been well covered, I just wanted to share my functions perhaps you can make use of these rather than importing an entire library.

    public long getSeconds(long ms) {
        return (ms/1000%60);
    }
    public long getMinutes(long ms) {
        return (ms/(1000*60)%60);
    }
    public long getHours(long ms) {
        return ((ms/(1000*60*60))%24);
    }
Mombasa answered 6/5, 2022 at 5:47 Comment(0)
A
1

I modified @MyKuLLSKI 's answer and added plurlization support. I took out seconds because I didn't need them, though feel free to re-add it if you need it.

public static String intervalToHumanReadableTime(int intervalMins) {

    if(intervalMins <= 0) {
        return "0";
    } else {

        long intervalMs = intervalMins * 60 * 1000;

        long days = TimeUnit.MILLISECONDS.toDays(intervalMs);
        intervalMs -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(intervalMs);
        intervalMs -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(intervalMs);

        StringBuilder sb = new StringBuilder(12);

        if (days >= 1) {
            sb.append(days).append(" day").append(pluralize(days)).append(", ");
        }

        if (hours >= 1) {
            sb.append(hours).append(" hour").append(pluralize(hours)).append(", ");
        }

        if (minutes >= 1) {
            sb.append(minutes).append(" minute").append(pluralize(minutes));
        } else {
            sb.delete(sb.length()-2, sb.length()-1);
        }

        return(sb.toString());          

    }

}

public static String pluralize(long val) {
    return (Math.round(val) > 1 ? "s" : "");
}
Augur answered 13/7, 2015 at 18:40 Comment(1)
int intervalMins vs long millisClearly
E
1

Use java.util.concurrent.TimeUnit, and use this simple method:

private static long timeDiff(Date date, Date date2, TimeUnit unit) {
    long milliDiff=date2.getTime()-date.getTime();
    long unitDiff = unit.convert(milliDiff, TimeUnit.MILLISECONDS);
    return unitDiff; 
}

For example:

SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm:ss");  
Date firstDate = sdf.parse("06/24/2017 04:30:00");
Date secondDate = sdf.parse("07/24/2017 05:00:15");
Date thirdDate = sdf.parse("06/24/2017 06:00:15");

System.out.println("days difference: "+timeDiff(firstDate,secondDate,TimeUnit.DAYS));
System.out.println("hours difference: "+timeDiff(firstDate,thirdDate,TimeUnit.HOURS));
System.out.println("minutes difference: "+timeDiff(firstDate,thirdDate,TimeUnit.MINUTES));
System.out.println("seconds difference: "+timeDiff(firstDate,thirdDate,TimeUnit.SECONDS));
Edva answered 4/6, 2018 at 8:59 Comment(0)
C
0

@Brent Writes Code's code clarified a bit more:



    public static String humanReadableTimeSpent(long millis) {
        if (millis < 0) {
            throw new IllegalArgumentException("Something is not right, time can't be negative!");
        }

        long days = TimeUnit.MILLISECONDS.toDays(millis);
        millis -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        millis -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
        millis -= TimeUnit.MINUTES.toMillis(minutes);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
        millis -= TimeUnit.SECONDS.toMillis(seconds);
        long millisecs = TimeUnit.MILLISECONDS.toMillis(millis);

        StringBuilder sb = new StringBuilder(64);
        if (days > 0) {
            sb.append(days);
            sb.append(" days ");
        }
        if (hours > 0) {
            sb.append(hours);
            sb.append(" hrs ");
        }
        if (minutes > 0) {
            sb.append(minutes);
            sb.append(" mins ");
        }
        if (seconds > 0) {
            sb.append(seconds);
            sb.append(" secs ");
        }
        if (millisecs > 0) {
            sb.append(millisecs);
            sb.append(" mills");
        }

        return (sb.toString());
    }

and call as follows:

humanReadableTimeSpent(endTimeMills - startTimeMills)
Condon answered 26/10, 2023 at 5:41 Comment(0)
W
0

java.time.LocalDateTime has until method:

LocalDateTime.now().minusMinutes(5).until(LocalDateTime.now(), MINUTES)

returns 5

Wellfed answered 5/1 at 13:35 Comment(1)
it is simple & efficient but the biggest issue is that it require API Level 26 & aboveTyronetyrosinase
R
0

Use this function

private fun Int.secondsToTime(): String {
    val second = this % 60
    var minute = this / 60
    if (minute >= 60) {
        val hour = minute / 60
        minute %= 60
        return "$hour hours $minute minutes $second seconds"
    }
    return "$minute minutes $second seconds"
}
Retard answered 27/3 at 13:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.