Bagaimana cara mengubah milidetik ke format "hh: mm: ss"?

184

Saya bingung. Setelah menemukan utas ini , saya mencoba mencari tahu cara memformat penghitung waktu mundur yang memiliki format hh:mm:ss.

Inilah usaha saya -

//hh:mm:ss
String.format("%02d:%02d:%02d", 
    TimeUnit.MILLISECONDS.toHours(millis),
    TimeUnit.MILLISECONDS.toMinutes(millis) - 
    TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));   

Jadi, ketika saya mencoba nilai seperti 3600000ms, saya dapatkan 01:59:00, yang salah karena seharusnya 01:00:00. Jelas ada yang salah dengan logika saya, tetapi saat ini, saya tidak dapat melihat apa itu!

Adakah yang bisa membantu?

Edit -

Memperbaikinya. Berikut cara yang tepat untuk memformat milidetik ke hh:mm:ssformat -

//hh:mm:ss
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))));

Masalahnya adalah ini TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)). Seharusnya ini yang terjadi TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)).

mre
sumber
1
3.600.000 milidetik adalah 3.600 detik, atau 60 menit, atau 1 jam. Seharusnya tidak 00:59:59, seharusnya 01:00:00.
Borealid

Jawaban:

355

Anda benar - benar dekat:

String.format("%02d:%02d:%02d", 
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) -  
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), // The change is in this line
TimeUnit.MILLISECONDS.toSeconds(millis) - 
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));   

Anda mengonversi jam menjadi milidetik menggunakan menit, bukan jam .

BTW, saya suka Anda menggunakan TimeUnit API :)

Berikut ini beberapa kode uji:

public static void main(String[] args) throws ParseException {
    long millis = 3600000;
    String hms = 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)));
    System.out.println(hms);
}

Keluaran:

01:00:00

Saya menyadari bahwa kode saya di atas dapat sangat disederhanakan dengan menggunakan divisi modulus alih-alih pengurangan:

String hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
    TimeUnit.MILLISECONDS.toMinutes(millis) % TimeUnit.HOURS.toMinutes(1),
    TimeUnit.MILLISECONDS.toSeconds(millis) % TimeUnit.MINUTES.toSeconds(1));

Masih menggunakan TimeUnitAPI untuk semua nilai ajaib, dan memberikan output yang persis sama.

Bohemian
sumber
2
Amin, seperti cara Anda menggunakan TimeUnit API :)
Dheeraj Bhaskar
2
Ini bukan ide yang baik untuk menemukan kembali roda! Jawaban Triton Man adalah solusi yang lebih baik.
محمدباقر
5
@ محمدباقر Tetapi jawaban lain menggunakan perpustakaan eksternal, sedangkan kode saya hanya menggunakan JDK inti. Itu tergantung pada apa kebutuhan Anda - misalnya Anda mungkin tidak dapat menggunakan perpustakaan eksternal. Namun jawaban yang lain bagus.
Bohemian
2
@ Ozuf menambah .replaceAll("^00:", "")atau .replaceAll("^00:(00:)?", "")menghapus menit dan juga jam jika keduanya nol.
Bohemian
2
@ Ozuf Anda dapatkan "15:00"dan "10:00:23"masing - masing; hanya terkemuka nol dihilangkan, karena pertandingan yang berlabuh untuk memulai input oleh ^.
Bohemian
77

Metode generik untuk ini cukup sederhana:

public static String convertSecondsToHMmSs(long seconds) {
    long s = seconds % 60;
    long m = (seconds / 60) % 60;
    long h = (seconds / (60 * 60)) % 24;
    return String.format("%d:%02d:%02d", h,m,s);
}
Arets Paeglis
sumber
1
@ Javaman59, maksudmu String.format("% 02 d:%02d:%02d", h,m,s) ?
KarenAnne
2
@ KarenAnne. Itu tergantung pada apakah Anda ingin, misalnya, "03:59:59" atau "3:59:59".
Stephen Hosking
2
Waktu dalam milidetik, Anda perlu melipatgandakan detik dengan 1000
Apurva
5
penulis bertanya tentang milidetik, bukan detik!
user924
59

Jika Anda menggunakan apache commons:

DurationFormatUtils.formatDuration(timeInMS, "HH:mm:ss,SSS");
Manusia Triton
sumber
4
Jalan Pintas:DurationFormatUtils.formatDurationHMS(timeInMS);
Aroniaina
@ Jorgesys Mengapa mereka usang?
Piovezan
mereka tidak usang.
Triton Man
26

Saya menggunakan ini:

String.format("%1$tH:%1$tM:%1$tS.%1$tL", millis);

Lihat deskripsi class Formatter .

Lihat contoh runnable menggunakan input 2400 ms.

ZuluM
sumber
Tampaknya tidak berfungsi, saya cukup mengujinya dengan lulus 100, 1000, 1200 dan merespons sebagai 05:30:00 , 05:30:01 , 05:30:01 .
CoDe
2
@ CoDe, ini berfungsi untuk zona waktu Anda. Anda harus berada di zona waktu yang berbeda dari UTC. tergantungString.format() zona waktu . Namun, jawaban yang benar dan ideal harus independen dari zona waktu .
Derek Mahar
@CoDe, ini menunjukkan waktu yang sesuai dengan zona waktu Anda yang harus berbeda dari UTC. tergantungString.format() zona waktu . Namun, jawaban yang benar dan ideal harus independen dari zona waktu .
Derek Mahar
25
// New date object from millis
Date date = new Date(millis);
// formattter 
SimpleDateFormat formatter= new SimpleDateFormat("HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
// Pass date object
String formatted = formatter.format(date );

Lihat contoh runnable menggunakan input 1200 ms.

Vinay Lodha
sumber
3
Ini akan menghasilkan hasil yang salah untuk jumlah waktu lebih dari satu hari. Itu akan membungkus jumlah jam dari 23 kembali ke 0, yang mungkin tidak diinginkan di sini.
Kenster
Tidak sobat ... Saya pikir itu masih akan bekerja sama. coba dengan kencan hari ini
Vinay Lodha
1
SimpleDateFormat sdf = new SimpleDateFormat ("hh: mm aa"); dalam kasus seseorang ingin dalam format 12 jam dengan am / pm
Ajji
14
DateFormat df = new SimpleDateFormat("HH:mm:ss");
String formatted = df.format(aDateObject);
Gabriel Belingueres
sumber
1
Jawaban yang sama dengan stackoverflow.com/questions/9027317/… dengan masalah yang sama untuk durasi di atas 1 hari
OneWorld
Ini juga tergantung pada zona waktu yang berarti hasilnya akan berbeda ketika dijalankan di zona waktu yang berbeda.
Derek Mahar
10

Hasil tes untuk 4 implementasi

Setelah melakukan banyak pemformatan untuk data besar, diperlukan kinerja terbaik, jadi inilah hasilnya (mengejutkan):

untuk (int i = 0; i <1000000; i ++) {FUNCTION_CALL}

Durasi:

  • kombinasiFormatter: 196 juta
  • formatDurasi: 272 juta
  • apacheFormat: 754 milis
  • formatTimeUnit: 2216 mili

    public static String apacheFormat(long millis) throws ParseException {
        return DurationFormatUtils.formatDuration(millis, "HH:mm:ss");
    }
    
    public static String formatTimeUnit(long millis) throws ParseException {
    String formatted = 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)));
        return formatted;
    }
    
    public static String formatDuration(final long millis) {
        long seconds = (millis / 1000) % 60;
        long minutes = (millis / (1000 * 60)) % 60;
        long hours = millis / (1000 * 60 * 60);
    
        StringBuilder b = new StringBuilder();
        b.append(hours == 0 ? "00" : hours < 10 ? String.valueOf("0" + hours) : 
        String.valueOf(hours));
        b.append(":");
        b.append(minutes == 0 ? "00" : minutes < 10 ? String.valueOf("0" + minutes) :     
        String.valueOf(minutes));
        b.append(":");
        b.append(seconds == 0 ? "00" : seconds < 10 ? String.valueOf("0" + seconds) : 
        String.valueOf(seconds));
        return b.toString();
    }
    
    public static String combinationFormatter(final long millis) {
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis)
                - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis));
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis)
                - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis));
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
    
        StringBuilder b = new StringBuilder();
        b.append(hours == 0 ? "00" : hours < 10 ? String.valueOf("0" + hours) : 
        String.valueOf(hours));
        b.append(":");
        b.append(minutes == 0 ? "00" : minutes < 10 ? String.valueOf("0" + minutes) : 
        String.valueOf(minutes));
            b.append(":");
        b.append(seconds == 0 ? "00" : seconds < 10 ? String.valueOf("0" + seconds) : 
        String.valueOf(seconds));
        return b.toString(); 
     }
MariusA
sumber
seberapa andal metrik seperti ini? Saya tidak pernah benar-benar memahami prosesnya.
mre
Dalam situasi saya di mana ribuan objek diciptakan secara berurutan, tes ini menurut saya cukup berguna. Oke tidak hanya mengatur beberapa string, tetapi membuat objek yang memiliki satu bidang string yang diformat.
MariusA
@Marius Anda pergi ke masalah untuk menggunakan StringBuilderkemudian membuat kesalahan dengan menggunakan "0" + nomor jenis "reruntuhan" itu. @re, JVM's GC sangat bagus dalam mengalokasikan dan mengumpulkan banyak objek yang berumur pendek, tidak perlu khawatir. Saya pergi String.formattanpa logika nol untuk menangani.
escape-llc
7

ini bekerja untuk saya, dengan kotlin

fun formatToDigitalClock(miliSeconds: Long): String {
        val hours = TimeUnit.MILLISECONDS.toHours(miliSeconds).toInt() % 24
        val minutes = TimeUnit.MILLISECONDS.toMinutes(miliSeconds).toInt() % 60
        val seconds = TimeUnit.MILLISECONDS.toSeconds(miliSeconds).toInt() % 60
        return when {
            hours > 0 -> String.format("%d:%02d:%02d", hours, minutes, seconds)
            minutes > 0 -> String.format("%02d:%02d", minutes, seconds)
            seconds > 0 -> String.format("00:%02d", seconds)
            else -> {
                "00:00"
            }
        }
    }
Devix
sumber
Bekerja dengan sempurna untuk saya. Ini harus menjadi jawaban terbaik karena menangani nol jam
vNext
6

Pergi dengan jawaban Bohemian kita tidak perlu menggunakan TimeUnit untuk menemukan nilai yang diketahui. Akan jauh lebih optimal

String hms = String.format("%02d:%02d:%02d", millisLeft/(3600*1000),
                    millisLeft/(60*1000) % 60,
                    millisLeft/1000 % 60);

Semoga ini bisa membantu

Aalin
sumber
Sukai jawaban Anda! Matematika sederhana. Btw dalam kasus saya, saya menambahkan milidetik hingga akhir millisLeft%1000/10jadi kami mendapatkan formatnyahour:minutes:seconds:milliseconds
Lê Quang Duy
@ LêQuangDuy saya butuh milidetik dalam 3 digit seperti 01: 24: 51,123 tetapi akhirnya Anda memotong 3 apa yang harus dilakukan?
naanu
@naanu cukup gunakanmillisLeft%1000
Lê Quang Duy
6
 public String millsToDateFormat(long mills) {

    Date date = new Date(mills);
    DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
    String dateFormatted = formatter.format(date);
    return dateFormatted; //note that it will give you the time in GMT+0
}
ctu
sumber
Jawaban tergantung pada zona waktu yang berarti hasilnya akan berbeda ketika dijalankan di zona waktu yang berbeda.
Derek Mahar
6

Jawa 9

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

Ini mencetak:

01:00:00

Anda melakukan hal yang benar dalam membiarkan metode perpustakaan melakukan konversi yang terlibat untuk Anda. java.time, API tanggal dan waktu Java modern, atau lebih tepatnya, Durationkelasnya melakukannya dengan lebih elegan dan dengan cara yang tidak terlalu banyak kesalahan daripadaTimeUnit .

The toMinutesPartdantoSecondsPart yang saya gunakan diperkenalkan di Jawa 9.

Java 6, 7 dan 8

    long hours = timeLeft.toHours();
    timeLeft = timeLeft.minusHours(hours);
    long minutes = timeLeft.toMinutes();
    timeLeft = timeLeft.minusMinutes(minutes);
    long seconds = timeLeft.toSeconds();
    String hhmmss = String.format("%02d:%02d:%02d", hours, minutes, seconds);
    System.out.println(hhmmss);

Outputnya sama seperti di atas.

Pertanyaan: Bagaimana cara kerjanya di Java 6 dan 7?

  • Di Java 8 dan yang lebih baru dan di perangkat Android yang lebih baru (dari API level 26, saya diberitahu) java.time bawaan.
  • Di Java 6 dan 7 dapatkan ThreeTen Backport, backport dari kelas modern (ThreeTen untuk JSR 310; lihat tautan di bagian bawah).
  • Pada (yang lebih tua) Android menggunakan ThreeTen Backport edisi Android. Itu disebut ThreeTenABP. Dan pastikan Anda mengimpor kelas tanggal dan waktu dari org.threeten.bpdengan subpackages.

Tautan

Ole VV
sumber
5

Kode di bawah melakukan konversi dengan kedua cara

23: 59: 58: 999 hingga 86398999

dan dari

86398999 hingga 23: 59: 58: 999


import java.util.concurrent.TimeUnit;

public class TimeUtility {

    public static void main(String[] args) {

        long currentDateTime = System.currentTimeMillis();

        String strTest = "23:59:58:999";
        System.out.println(strTest);

        long l = strToMilli(strTest);
        System.out.println(l);
        l += 1;
        String str = milliToString(l);
        System.out.println(str);
    }

    /**
     * convert a time string into the equivalent long milliseconds
     *
     * @param strTime string fomratted as HH:MM:SS:MSMS i.e. "23:59:59:999"
     * @return long integer like 86399999
     */
    public static long strToMilli(String strTime) {
        long retVal = 0;
        String hour = strTime.substring(0, 2);
        String min = strTime.substring(3, 5);
        String sec = strTime.substring(6, 8);
        String milli = strTime.substring(9, 12);
        int h = Integer.parseInt(hour);
        int m = Integer.parseInt(min);
        int s = Integer.parseInt(sec);
        int ms = Integer.parseInt(milli);

        String strDebug = String.format("%02d:%02d:%02d:%03d", h, m, s, ms);
        //System.out.println(strDebug);
        long lH = h * 60 * 60 * 1000;
        long lM = m * 60 * 1000;
        long lS = s * 1000;

        retVal = lH + lM + lS + ms;
        return retVal;
    }

    /**
     * convert time in milliseconds to the corresponding string, in case of day
     * rollover start from scratch 23:59:59:999 + 1 = 00:00:00:000
     *
     * @param millis the number of milliseconds corresponding to tim i.e.
     *               34137999 that can be obtained as follows;
     *               <p>
     *               long lH = h * 60 * 60 * 1000; //hour to milli
     *               <p>
     *               long lM = m * 60 * 1000; // minute to milli
     *               <p>
     *               long lS = s * 1000; //seconds to milli
     *               <p>
     *               millis = lH + lM + lS + ms;
     * @return a string formatted as HH:MM:SS:MSMS i.e. "23:59:59:999"
     */
    private static String milliToString(long millis) {

        long hrs = TimeUnit.MILLISECONDS.toHours(millis) % 24;
        long min = TimeUnit.MILLISECONDS.toMinutes(millis) % 60;
        long sec = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;
        //millis = millis - (hrs * 60 * 60 * 1000); //alternative way
        //millis = millis - (min * 60 * 1000);
        //millis = millis - (sec * 1000);
        //long mls = millis ;
        long mls = millis % 1000;
        String toRet = String.format("%02d:%02d:%02d:%03d", hrs, min, sec, mls);
        //System.out.println(toRet);
        return toRet;
    }
}
Menzio Luca Fabrizio
sumber
Saya membatalkan solusi ini. Cukup beri titik di antara detik dan ml. Dan saya tidak tahu mengapa pengaturan waktu dan tanggal sangat sulit di Jawa. Fungsi yang paling banyak digunakan harus sudah tersedia dan bagian dari kelas.
Baruch Atta
5
        String string = String.format("%02d:%02d:%02d.%03d",
            TimeUnit.MILLISECONDS.toHours(millisecend), TimeUnit.MILLISECONDS.toMinutes(millisecend) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisecend)),
            TimeUnit.MILLISECONDS.toSeconds(millisecend) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisecend)), millisecend - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(millisecend)));

Format: 00: 00: 00.000

Contoh: 615605 Milidetik

00: 10: 15.605

Omid Naji
sumber
5

Jawaban yang ditandai benar memiliki sedikit kesalahan,

String myTime = String.format("%02d:%02d:%02d",
            TimeUnit.MILLISECONDS.toHours(millis),
            TimeUnit.MILLISECONDS.toMinutes(millis) -
                    TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), // The change is in this line
            TimeUnit.MILLISECONDS.toSeconds(millis) -
                    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

misalnya ini adalah contoh dari nilai yang saya dapatkan:

417474:44:19

Ini solusi untuk mendapatkan format yang tepat adalah:

String myTime =  String.format("%02d:%02d:%02d",
                //Hours
                TimeUnit.MILLISECONDS.toHours(millis) -
                        TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(millis)),
                //Minutes
                TimeUnit.MILLISECONDS.toMinutes(millis) -
                        TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                //Seconds
                TimeUnit.MILLISECONDS.toSeconds(millis) -
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

mendapatkan format yang benar:

18:44:19

Pilihan lain untuk mendapatkan format hh:mm:ssadalah:

   Date myDate = new Date(timeinMillis);
   SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
   String myTime = formatter.format(myDate);
Jorgesys
sumber
4

Saya mencoba seperti yang ditunjukkan pada jawaban pertama. Ini bekerja, tetapi minus membawa saya ke dalam kebingungan. Jawaban saya oleh Groovy:

import static java.util.concurrent.TimeUnit.*

...

private static String formatElapsedTime(long millis) {

    int hrs = MILLISECONDS.toHours(millis) % 24
    int min = MILLISECONDS.toMinutes(millis) % 60
    int sec = MILLISECONDS.toSeconds(millis) % 60
    int mls = millis % 1000

    sprintf( '%02d:%02d:%02d (%03d)', [hrs, min, sec, mls])
}
leonov
sumber
3

Untuk Kotlin

val hours = String.format("%02d", TimeUnit.MILLISECONDS.toHours(milSecs))
val minutes = String.format("%02d",
                        TimeUnit.MILLISECONDS.toMinutes(milSecs) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milSecs)))
val seconds = String.format("%02d",
                        TimeUnit.MILLISECONDS.toSeconds(milSecs) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milSecs)))

di mana, milSecsadalah milidetik

Kishan Solanki
sumber
1

Anda dapat mencoba sesuatu seperti ini:

public String getElapsedTimeHoursMinutesSecondsString() {       
     long elapsedTime = getElapsedTime();  
     String format = String.format("%%0%dd", 2);  
     elapsedTime = elapsedTime / 1000;  
     String seconds = String.format(format, elapsedTime % 60);  
     String minutes = String.format(format, (elapsedTime % 3600) / 60);  
     String hours = String.format(format, elapsedTime / 3600);  
     String time =  hours + ":" + minutes + ":" + seconds;  
     return time;  
 }  

untuk mengkonversi milidetik ke nilai waktu

anonim
sumber