35

I want to convert the second/milliseconds in this format "HH:mm:ss" (for esamples, from 5 seconds to 00:00:05). I tried to get that format in this way:

int millis = 5000;
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
String time = df.format(millis);

In that way, I get "01:00:05" and not "00:00:05". Where am I wrong?

Webman
  • 1,534
  • 3
  • 26
  • 48
  • possible duplicate of [How to convert Milliseconds to "X mins, x seconds" in Java?](http://stackoverflow.com/questions/625433/how-to-convert-milliseconds-to-x-mins-x-seconds-in-java) – Paulo Fidalgo Mar 04 '14 at 15:57
  • 1
    This question has better answers [here](http://stackoverflow.com/a/625624/685806) and [here](http://stackoverflow.com/a/266970/685806). – Pino May 11 '12 at 14:33
  • possible duplicate of [How to convert time in seconds to HH:MM:SS format in MySQL?](http://stackoverflow.com/questions/18911455/how-to-convert-time-in-seconds-to-hhmmss-format-in-mysql) – kapil thadani Jan 13 '15 at 09:15

8 Answers8

24

Timezones.

The long value 5000 means 5 seconds after the epoch. For the majority of timezones, 5 seconds after the epoch is not 5 seconds past midnight local time.

Java 8 update:

java.time.LocalTime will handle the idea of a wall-clock "time of day" without you having to worry about the timezones and days implicit in java.util.Date. If you can use Java 8, and your durations will always be less than a day, then a correct version of your example can be as simple as:

int millis = 5000;
int seconds = millis / 1000; // Maybe no need to divide if the input is in seconds
LocalTime timeOfDay = LocalTime.ofSecondOfDay(seconds);
String time = timeOfDay.toString();

(I guess strictly speaking, java.time.Duration is a better model of what you want, in that it represents a certain number of seconds, rather than a time-of-day. But it's a pain to format into hh:mm:ss, so if you're always dealing with sub-24hour values, TimeOfDay gives you this formatting for free and is otherwise equivalent.)


If you're stuck with Java 7 or below, then explicitly specifying a timezone of GMT in your example code should give you the output you expect.

Here's a Scala REPL session demonstrating the problem, and Java 7 solution, on my machine:

scala> val millis = 5000
millis: Int = 5000

scala> val df = new java.text.SimpleDateFormat("HH:mm:ss")
df: java.text.SimpleDateFormat = java.text.SimpleDateFormat@8140d380

scala> df.format(millis)
res0: java.lang.String = 01:00:05

scala> df.getTimeZone.getID
res1: java.lang.String = GB

scala> df.getTimeZone.getOffset(millis)
res2: Int = 3600000

scala> df.setTimeZone(java.util.TimeZone.getTimeZone("GMT"))

scala> df.format(millis)
res3: java.lang.String = 00:00:05

So you can see that my default time zone is GB, which has a 1 hour offset from GMT at the time denoted by 5000L. Setting the timezone to GMT gievs the expected output of 00:00:05.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • 1
    Are you sure this is timezone related? I'm in the GMT timezone, and calling `df.getTimeZone()` in the above code returns `id="Europe/London"` and I get the same output of "01:00:05". – dave.c Feb 09 '12 at 16:51
  • Yep, London was 1 hour ahead of GMT at the time in question (according to Java at least). See my edit for a worked example. – Andrzej Doyle Feb 09 '12 at 18:21
  • It's works. I added this `df.setTimeZone(TimeZone.getTimeZone("GMT"));` – Webman Feb 10 '12 at 09:44
  • Just to add that if you have more than 24h, the hours will show only the remainder (e.g. for 34h, it will return 10:00:00). I haven't found a solution to include days as well (using ``DD`` starts the count from 1, so 34h would be 02:10:00:00, instead of 01:10:00:00), or to show more than 24 hours (e.g. 34:00:00). – gozzilli Jan 04 '16 at 19:02
  • in most cases probably not very important but the LocalTime solution also seems to be faster than using SimpleDateFormat. I got 100 ms instead of 350 for one million runs – 1813222 May 12 '19 at 10:31
21

I wrote a simple utility function for this task which does not require any Java version nor instantiates any unnecessary objects:

/**
 * provides a String representation of the given time
 * @return {@code millis} in hh:mm:ss format
 */
public static final String formatTime(long millis) {
    long secs = millis / 1000;
    return String.format("%02d:%02d:%02d", secs / 3600, (secs % 3600) / 60, secs % 60);
}

Unlike some other solutions here, this can even deal with up to 100 hours

OASE Software GmbH
  • 152
  • 1
  • 3
  • 11
xeruf
  • 2,602
  • 1
  • 25
  • 48
15

I got this to work. Let me know if it works for you. Seems like a lot of lines to do something seemingly simple..

    int millis = 5000;
    TimeZone tz = TimeZone.getTimeZone("UTC");
    SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
    df.setTimeZone(tz);
    String time = df.format(new Date(millis));
    System.out.println(time);
B. Anderson
  • 3,079
  • 25
  • 33
  • this worked for me too. if anyone finds a better way, please let me know. p.s its good to know that java is still lacking simple Date/Time functionality. – APT Aug 28 '14 at 13:59
  • 1
    @APT - You may be sad to learn that Java 8 does have much better Date/Time functionality(!). I've updated my answer with an example using the new `java.time` package. – Andrzej Doyle Jan 13 '15 at 12:18
  • Thanks, it does seems to be nicer in java 8 :) – APT Jan 20 '15 at 16:17
5

You should get SimpleDateFormat with Locale argument.

public static String getDateFromMillis(long millis) {
    SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
    return formatter.format(new Date(millis));
}
localhost
  • 5,568
  • 1
  • 33
  • 53
1
public class HHMMSS {

        final int UUR = 3600;
        final int MINUUT = 60;

    public void converteerTijd() {

        int uren, minuten, seconden, ingave;
        System.out.print("Geef een aantal seconden: ");
        ingave = Input.readInt();
        uren = ingave / UUR;
        minuten = (ingave - uren * UUR) / MINUUT;
        seconden = ingave - uren * UUR - minuten * MINUUT;
        String nU1 = (uren < 10) ? "0" : "";
        String nM1 = (minuten < 10) ? "0" : "";
        String nS1 = (seconden < 10) ? "0" : "";
        System.out.println(nU1 + uren + "-" + nM1 + minuten + "-" + nS1 + seconden);
Ben
  • 51,770
  • 36
  • 127
  • 149
1

Java 9 answer:

    Duration dur = Duration.ofMillis(millis);
    System.out.println(String.format("%02d:%02d:%02d",
                       dur.toHours(), dur.toMinutesPart(), dur.toSecondsPart()));

(not tested yet)

The toXxPart methods are described in the API docs for Java 9.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

This example has no localization warning:

public static String getTime(int sek) {
    return String.format(Locale.US, "%02d:%02d:%02d", sek/3600, (sek%3600)/60, sek%60);
}
0

Show time duration like YouTube

String duration(int length){
    String format =String.format(Locale.US, "%02d:%02d:%02d", length/3600, (length%3600)/60, length%60);
    if (format.length()>=7 && format.startsWith("00:0"))
        format=format.replace("00:0","");
    if (format.length()>=7 && format.startsWith("00:"))
        format=format.replace("00:","");
    Log.d("seeformat",format);
    return format;
}