Bagaimana cara mengubah milidetik ke "X menit, x detik" di Jawa?

573

Saya ingin merekam waktu menggunakan System.currentTimeMillis()ketika pengguna memulai sesuatu di program saya. Ketika dia selesai, saya akan mengurangi arus System.currentTimeMillis()dari startvariabel, dan saya ingin menunjukkan kepada mereka waktu berlalu menggunakan format yang dapat dibaca manusia seperti "XX jam, XX menit, XX detik" atau bahkan "XX menit, XX detik" karena ini tidak mungkin membawa seseorang satu jam.

Apa cara terbaik untuk melakukan ini?

Klik Upvote
sumber
5
Jika mereka membutuhkan waktu lebih dari satu jam Anda masih dapat mencetak sesuatu seperti; 90 menit, 53 detik.
Peter Lawrey
1
jawaban saya datang terlambat 6 tahun tapi saya pikir ini lebih umum daripada yang diterima: stackoverflow.com/a/35082080/82609
Sebastien Lorber
1
lihat contoh sederhana untuk Mengubah Milidetik ke Hari, Jam, Menit, Detik di Jawa
sumit kumar pradhan

Jawaban:

1229

Gunakan java.util.concurrent.TimeUnitkelas:

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

Catatan: TimeUnitadalah bagian dari spesifikasi Java 1.5, tetapi toMinutesditambahkan sebagai Java 1.6.

Untuk menambahkan nol awal untuk nilai 0-9, lakukan saja:

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

Jika TimeUnitatau toMinutestidak didukung (seperti pada Android sebelum API versi 9), gunakan persamaan berikut:

int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours   = (int) ((milliseconds / (1000*60*60)) % 24);
//etc...
siddhadev
sumber
5
int bulan = (int) ((float) hari / 30.4368499f); int tahun = (int) ((float) hari / 365.242199f);
Nathan Schwermann
7
Id menyarankan untuk menggunakan mod 60 bukannya mengurangi menit, itu terlihat lebih bersih. Namun, kita perlu tahu bahwa 1 mnt = 60 dtk untuk melakukan itu ... =)
Per Alexandersson
2
@AndreasDietrich SimpleDateFormat tidak berfungsi untuk perbedaan waktu karena hanya mengembalikan tanggal dari zaman!
Muhammad Babar
5
int hours = (int) ((milliseconds / (1000*60*60)) % 24)ini tidak berhasil! sebaliknya harus seperti iniint hours = (int) (milliseconds / (1000*60*60)) ;
Muhammad Babar
5
Jika seseorang menginginkan format untuk file video ( h: mm: dd ):String.format("%01d:%02d:%02d", hours, minutes, seconds);
kazy
124

Berdasarkan jawaban @ siddhadev, saya menulis sebuah fungsi yang mengubah milidetik menjadi string yang diformat:

   /**
     * 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());
    }
Brent Menulis Kode
sumber
2
Anda harus melakukan pengecekan di sana untuk lajang / ganda, untuk menghindari situasi seperti ini:1 Days 1 Hours 1 Minutes 1 Seconds
Daniel
7
Kita dapat menggunakan fungsi modulus alih-alih pengurangan: 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; dan juga metode String.format:return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds", days, hours, minutes, seconds, milliseconds);
Jose Tepedino
78
long time = 1536259;

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

Cetakan:

25:36: 259

Damien
sumber
1
Saya suka pendekatan di atas yang terbaik jika tidak lain kesederhanaannya! Karena kita berurusan dengan waktu dan jangka waktu saya biasanya menggunakan Joda. Contoh jika Anda memiliki dua DateTimes, mulailah dan akhiri masing-masing:Duration dur = new Duration(start, end); long millis = dur.getMillis();
TechTrip
1
Saya seharusnya mencatat 2 cara untuk menggunakan formator Joda. Variasi pertama pada tema Anda: DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time)); Atau konversi Durasi ke Periode yang dapat secara otomatis dicetak menggunakan Joda PeriodFormatter. Konversi bisa kehilangan presisi jika selain kronologi ISO. Misalkan Durasi diwakili oleh variabel duration. Period period = duration.toPeriod().normalizedStandard(PeriodType.time()); PeriodFormat.getDefault().print(period)) Output luar biasa: 1 detik dan 581 milidetik, menjawab pertanyaan utama di atas.
TechTrip
2
Agak terlambat di sini :) Tapi bukankah Anda harus meletakkan simpleDateFormat.setTimezone (TimeZone.getTimeZone ("GMT")) di sini kecuali itu zona waktu Anda yang sebenarnya?
Olle Söderström
@ OlleSöderström Memang ada masalah dengan zona waktu di sini. Tetapi pengaturan ke GMT atau UTC menyebabkan bagian jam menjadi 12 bukannya 0 untuk semua durasi lebih pendek dari 1 jam.
Episodex
2
Timezone bukan satu-satunya masalah di sini ... jawaban ini menyesatkan dan serius dapat membingungkan pemula Jawa. Bahkan mengabaikan kurung luar yang berlebihan, OP bertanya bagaimana menyajikan durasi (perbedaan antara dua titik waktu, diukur dalam ms). Menyebut durasi itu "waktu" dan memperlakukannya sebagai offset sejak 1 Jan, 1970 hanya untuk memformat komponen yang lebih kecil hanyalah ... salah imo. Terlebih lagi, pendekatan yang sama telah disarankan 3 tahun sebelumnya oleh jawaban ini (lihat komentar di sana untuk detail lebih lanjut tentang masalah zona waktu).
Amos M. Carpenter
36

Uhm ... berapa milidetik dalam sedetik? Dan sebentar lagi? Divisi tidak terlalu sulit.

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

Terus seperti itu selama berjam-jam, berhari-hari, berminggu-minggu, berbulan-bulan, setahun, berpuluh-puluh tahun, apa pun.

Bombe
sumber
2
Sebenarnya, melakukan ini selama lebih dari satu jam bukan ide yang baik karena hasilnya bisa salah / tidak intuitif ketika waktu musim panas (hari 23 atau 24 jam) atau tahun kabisat terlibat. Jika saya membaca "X akan terjadi dalam 1 tahun / bulan", saya berharap itu akan menjadi tanggal dan waktu yang sama.
Michael Borgwardt
5
System.currentTimeMillis () kebal terhadap DST sehingga ini tidak akan bingung dengan jam tambahan atau hilang. Jika Anda perlu menunjukkan perbedaan antara dua tanggal tertentu, Anda lebih baik membuat objek Tanggal dengan waktu yang diberikan dan menunjukkan perbedaan antara keduanya.
Bombe
1
Di luar minggu, itu tidak terdefinisi, karena panjang bulan adalah variabel. Jadi memang, Anda perlu menghitung relatif terhadap referensi waktu yang diberikan.
PhiLho
31

Menggunakan paket java.time di Java 8:

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

Output dalam format Durasi ISO 8601 : PT1M3.553S(1 menit dan 3,553 detik).

Vitalii Fedorenko
sumber
1
(ANDROID) Membutuhkan API level 26
Seseorang Di Suatu Tempat
1
@SomeoneSomewhere Untuk Android di bawah API level 26 gunakan backport, lihat Cara menggunakan ThreeTenABP di Android Project .
Ole VV
1
Itu luar biasa :) terima kasih untuk head-up!
Seseorang di suatu tempat
27

Saya tidak akan menarik ketergantungan ekstra hanya untuk itu (pembagian tidak sulit, setelah semua), tetapi jika Anda menggunakan Commons Lang pula, ada DurationFormatUtils .

Contoh Penggunaan (diadaptasi dari sini ):

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

Contoh:

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

//Output: 2s

Catatan : Untuk mendapatkan millis dari dua objek LocalDateTime Anda dapat menggunakan:

long age = ChronoUnit.MILLIS.between(initTime, LocalDateTime.now())
Thilo
sumber
1
Hebat, saya hanya bertanya pada diri sendiri apakah ada perpustakaan yang kuat yang mencakup hal-hal semacam ini.
Lajcik
Karena tautan pada umumnya tidak terlalu bermanfaat, saya menambahkan contoh bagaimana cara menggunakannya.
lepe
26

Entah pembagian tangan, atau gunakan API SimpleDateFormat .

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

Sunting oleh Bombe : Telah ditunjukkan di komentar bahwa pendekatan ini hanya berfungsi untuk durasi yang lebih kecil (yaitu kurang dari sehari).

cadrian
sumber
Wow. Itu adalah peretasan yang jahat, tergantung zona waktu. Ini akan pecah tanpa ampun ketika Anda memiliki zona waktu offset yang bukan kelipatan 60 menit (dan kami memiliki beberapa zona waktu offset 30 menit sial di dunia).
Bombe
Juga, itu akan rusak begitu Anda memasukkan jam dalam format string dan tidak pada GMT + 0, untuk alasan yang sama.
Bombe
Kita lakukan? Betulkah? Dimana? Tidak meragukan Anda, hanya belum pernah mendengarnya sebelumnya - beberapa perangkap baru untuk dipertimbangkan ;-)
Treb
Iya. Periksa “Daftar zona waktu” di Wikipedia, misalnya Nepal pada GMT + 05:45.
Bombe
2
cadrian, sekarang hanya akan bekerja untuk jangka waktu kurang dari sehari. Jumlah jam akan selalu antara 0 dan 23, inklusif.
Bombe
21

Hanya untuk menambahkan lebih banyak info jika Anda ingin memformat seperti: HH: mm: ss

0 <= HH <= tak terbatas

0 <= mm <60

0 <= dtk <60

Gunakan ini:

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

Saya baru saja mengalami masalah ini sekarang dan menemukan jawabannya

fredcrs
sumber
1
Jawaban terbaik di sini. Mengapa semua orang ingin membuat segalanya jadi rumit? Ini matematika sederhana, kawan.
Lambart
11

Saya pikir cara terbaik adalah:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toSeconds(length)/60,
    TimeUnit.MILLISECONDS.toSeconds(length) % 60 );
Xtera
sumber
selama beberapa menit Anda dapat menggunakan TimeUnit.MILLISECONDS.toMinutes (panjang)
EminenT
11

Solusi terpendek:

Ini mungkin yang terpendek yang juga berkaitan dengan zona waktu.

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

Output mana misalnya:

00:18:32

Penjelasan:

%tTadalah waktu yang diformat untuk jam 24 jam sebagai %tH:%tM:%tS.

%tTjuga menerima rindu sebagai input, jadi tidak perlu membuat Date. printf()hanya akan mencetak waktu yang ditentukan dalam milidetik, tetapi dalam zona waktu saat ini karena itu kita harus mengurangi offset mentah dari zona waktu saat ini sehingga 0 milidetik akan menjadi 0 jam dan bukan nilai offset waktu dari zona waktu saat ini.

Catatan # 1: Jika Anda membutuhkan hasilnya sebagai String, Anda bisa mendapatkannya seperti ini:

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

Catatan # 2: Ini hanya memberikan hasil yang benar jika milliskurang dari satu hari karena bagian hari tidak termasuk dalam output.

icza
sumber
Ini adalah jalan pintas yang sangat bagus, tetapi ketika saya menggunakannya saya tidak mendapatkan hasil yang diharapkan. Jadi saya punya: long millis = 8398;dan ketika saya meneruskannya ke String.format("%tT", millis)output saya adalah 19:00:08. Dari mana 19 berasal?
Nelda.techspiress
1
@ Nelda.techspiress Itulah offset zona waktu Anda. Anda harus mengurangi TimeZone.getDefault().getRawOffset()itu, persis seperti yang tertulis dalam jawaban:String.format("%tT", millis-TimeZone.getDefault().getRawOffset())
icza
yang mengurusnya. Terima kasih telah mengklarifikasi.
Nelda.techspiress
8

Joda-Time

Menggunakan 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));
dogbane
sumber
1
Tidak perlu untuk itu PeriodFormatdi baris terakhir. Cukup panggil Period::toStringuntuk mendapatkan string Durasi ISO 8601 secara default.
Basil Bourque
8

Meninjau kembali kontribusi @ brent-nash, kita dapat menggunakan fungsi modulus alih-alih pengurangan dan menggunakan metode String.format untuk string hasil:

  /**
   * 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);
   }
Jose Tepedino
sumber
6

untuk Android di bawah 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)) 
Pradeep
sumber
5

Untuk waktu kecil, kurang dari satu jam, saya lebih suka:

long millis = ...

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

untuk interferensi yang lebih lama:

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);
}
pengguna85421
sumber
Itu petunjuk yang berharga, ada banyak kemungkinan untuk tanggal dan waktu dengan Java Formatter API ( docs.oracle.com/javase/8/docs/api/java/util/Formatter.html )! Anda juga dapat memiliki hasil kondisi selain dengan: System.out.printf ("% 1 $ tH:% 1 $ tM:% 1 $ tS% n", millis); atau bahkan System.out.printf ("% 1 $ tT% n", milis);
Jose Tepedino
@JoseTepedino tetapi Anda sadar bahwa %tH hanya tampil dari 0 hingga 23 jam? Itu berarti bahwa misalnya 24 jam akan ditampilkan sebagai 00, 25 jam sebagai 01... valid yang sama untuk %tT- hari akan secara diam-diam dibuang. Tentu, bisa juga ada hari-hari yang ditampilkan, tetapi itu akan menjadi kesalahan besar untuk masalah yang saya miliki ketika saya menulis ini (kembali pada tahun 2011) [:-)
user85421
Saya mengerti ... itu hanya akan bekerja untuk waktu kurang dari sehari (24 jam). Terima kasih.
Jose Tepedino
5

Perhitungan sederhana saya:

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

Selamat coding :)

Shohan Ahmed Sijan
sumber
Saya kira panjang lebih tepat untuk fungsi ini karena System.currentTimeMillis () mengembalikan nilai panjang.
aprodan
Ini tidak benar, sudahkah Anda memeriksa hasilnya?
Jorgesys
4

Ini jawaban berdasarkan jawaban Brent Nash, Semoga itu membantu!

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());
}
Reda Bouaichi
sumber
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
Fathah Rehman P
sumber
3
Rumus pada baris 6 salah. diff=diff-(hours*60*1000);seharusnya diff=diff-(hours*60*60*1000);. Saya mencoba mengeditnya tetapi kebijakan edit yang menjengkelkan StackOverflow mengatakan itu tidak cukup karakter untuk diedit.
quux00
4

Pertama, System.currentTimeMillis()dan Instant.now()tidak ideal untuk penentuan waktu. Keduanya melaporkan waktu jam dinding, yang tidak diketahui oleh komputer dengan tepat, dan mana yang dapat bergerak tidak menentu, termasuk mundur jika misalnya daemon NTP mengoreksi waktu sistem. Jika waktu Anda terjadi pada satu mesin, Anda harus menggunakan System.nanoTime () .

Kedua, dari Java 8 dan seterusnya java.time.Duration adalah cara terbaik untuk mewakili durasi:

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"
MikeFHay
sumber
3

Jika Anda tahu perbedaan waktu akan kurang dari satu jam, maka Anda dapat menggunakan kode berikut:

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

Ini akan menghasilkan: 51:00

Gourav Singla
sumber
3

Jawaban ini mirip dengan beberapa jawaban di atas. Namun, saya merasa itu akan bermanfaat karena, tidak seperti jawaban lain, ini akan menghilangkan koma atau spasi tambahan dan menangani singkatan.

/**
 * 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);
}
Jared Rummler
sumber
3

Ada masalah. Ketika milidetik 59999, sebenarnya itu 1 menit tetapi akan dihitung sebagai 59 detik dan 999 milidetik hilang.

Berikut adalah versi yang dimodifikasi berdasarkan jawaban sebelumnya, yang dapat mengatasi kehilangan ini:

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);
}
Hexise
sumber
2

Ini lebih mudah di Java 9:

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

Ini menghasilkan string seperti 0 hours, 39 mins, 9 seconds.

Jika Anda ingin membulatkan seluruh detik sebelum memformat:

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

Untuk meninggalkan jam jika mereka 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());
    }

Sekarang kita bisa punya contoh 39 mins, 9 seconds.

Untuk mencetak menit dan detik dengan nol di depan untuk membuatnya selalu dua digit, cukup masukkan 02ke penentu format yang relevan, dengan demikian:

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

Sekarang kita bisa punya contoh 0 hours, 39 mins, 09 seconds.

Ole VV
sumber
Adakah pemformatan untuk menghapus jam / menit / detik ketika angka sebelumnya adalah 0? Maksud saya ini dapat dicapai dengan kondisi if else, tetapi bagaimana dengan keberadaan pemformatan String atau sesuatu yang dekat, apakah ada?
Farid
1
Tidak, maaf, @FARID, Anda perlu if- di elsesana.
Ole VV
1

untuk string yang benar ("1 jam, 3 dtk", "3 mnt" tetapi tidak "0 jam, 0 mnt, 3 dtk") saya menulis kode ini:

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";
John
sumber
1

Saya memodifikasi jawaban @MyKuLLSKI dan menambahkan dukungan plurlisasi. Saya mengambil detik karena saya tidak membutuhkannya, meskipun merasa bebas untuk menambahkannya kembali jika Anda membutuhkannya.

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" : "");
}
bitstream
sumber
int intervalMins vs long millis
Kiquenet
1

Saya telah membahas ini dalam jawaban lain tetapi Anda dapat melakukannya:

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

Outputnya seperti Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}, dengan unit yang dipesan.

Terserah kepada Anda untuk mengetahui cara menginternasionalkan data ini sesuai dengan target lokal.

Sebastien Lorber
sumber
1

Gunakan java.util.concurrent.TimeUnit, dan gunakan metode sederhana ini:

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

Sebagai contoh:

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));
Aramis Rodríguez Blanco
sumber