Як перетворити мілісекунди у формат "hh: mm: ss"?


184

Я збентежений. Натрапивши на цю нитку, я спробував розібратися, як відформатувати таймер зворотного відліку, який мав формат hh:mm:ss.

Ось моя спроба -

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

Отже, коли я пробую таке значення, як 3600000ms, я отримую 01:59:00, що неправильно, оскільки воно має бути 01:00:00. Очевидно, що в моїй логіці щось не так, але на даний момент я не бачу, що це!

Хтось може допомогти?

Редагувати -

Виправлено це. Ось правильний спосіб відформатування мілісекунд hh:mm:ss-

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

Проблема була в цьому TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)). Це мало бути TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))замість цього.


1
3 600 000 мілісекунд - це 3600 секунд, або 60 хвилин, або 1 година. Не повинно бути 00:59:59, так і має бути 01:00:00.
Borealid

Відповіді:


355

Ви дійсно були поруч:

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

Ви перетворювали години на мілісекунди, використовуючи хвилини замість годин .

До речі, мені подобається використання TimeUnitAPI :)

Ось кілька тестових кодів:

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

Вихід:

01:00:00

Я зрозумів, що мій код вище можна значно спростити, використовуючи поділ модуля замість віднімання:

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

Все-таки використовується TimeUnitAPI для всіх магічних значень і дає абсолютно однаковий вихід.


2
Амінь, як те, як ви використовуєте API TimeUnit :)
Dheeraj Bhaskar

2
Не винаходити винаходити колесо! Відповідь Тритона Мана - краще рішення.
محمدباقر

5
@ محمدباقر Інша відповідь використовує зовнішню бібліотеку, тоді як мій код використовує лише основний JDK. Це залежить від ваших потреб - наприклад, ви не зможете використовувати зовнішню бібліотеку. Інша відповідь хороша, хоча.
богем

2
@Ozuf додайте .replaceAll("^00:", "")або .replaceAll("^00:(00:)?", "")видаліть хвилини, а також години, якщо обоє дорівнюють нулю.
богем

2
@Ozuf ви отримаєте "15:00"і "10:00:23"відповідно; видаляються лише провідні нулі, оскільки матч прикріплений до початку введення ^.
богем

77

Загальний метод для цього досить простий:

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

1
@ Javaman59, ти мав на увазі String.format("% 02 d:%02d:%02d", h,m,s) ?
KarenAnne

2
@KarenAnne. Це залежить від того, хочете ви, наприклад, "03:59:59" або "3:59:59".
Стівен Хоскінг

2
Час в мілісекундах, вам потрібно помножити секунди на 1000
Апурва

5
автор запитав про мілісекунди, а не секунди!
user924


26

Я використав це:

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

Див. Опис класу Форматтер .

Дивіться приклад запуску з використанням вводу 2400 мс.


Здається, це не працює, я просто тестую його через пропуск 100, 1000, 1200, і він відповідає як 05:30:00 , 05:30:01 , 05:30:01 .
CoDe

2
@CoDe, він працює для вашого часового поясу. Ви повинні знаходитись в іншому часовому поясі, ніж UTC. String.format()це тимчасова зона залежить . Однак ідеальною правильною відповіддю має бути незалежність від часового поясу .
Дерек Махар

@CoDe, це показ часу, який відповідає вашому часовому поясу, який повинен відрізнятися від UTC. String.format()це тимчасова зона залежить . Однак ідеальною правильною відповіддю має бути незалежність від часового поясу .
Дерек Махар

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

Дивіться приклад запуску, використовуючи вхід 1200 мс.


3
Це призведе до неправильних результатів протягом часу, що перевищує добу. Це може перетягнути кількість годин з 23 назад до 0, що, мабуть, тут небажано.
Кенстер

Жодного приятеля ... Я думаю, це все одно працювало б так само. спробуйте з сьогоднішньою датою
Vinay Lodha

1
SimpleDateFormat sdf = новий SimpleDateFormat ("hh: mm aa"); на випадок, якщо хтось захоче у форматі 12 годин з am / pm
Ajji

14
DateFormat df = new SimpleDateFormat("HH:mm:ss");
String formatted = df.format(aDateObject);

1
Та сама відповідь, що і stackoverflow.com/questions/9027317/… з тією ж проблемою тривалістю понад 1 день
OneWorld

Це також залежить від часового поясу, а значить, результат буде відрізнятися при запуску в різних часових поясах.
Дерек Махар

10

Результати тестування для 4-х реалізацій

Потрібно зробити багато форматування для величезних даних, потрібна найкраща продуктивність, тому ось (дивовижні) результати:

для (int i = 0; i <1000000; i ++) {FUNCTION_CALL}

Тривалість:

  • комбінаціяФормат: 196 млн
  • Форматзапису: 272 млн
  • apacheFormat: 754 млн
  • formatTimeUnit: 2216 млн

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

наскільки надійні такі показники? Я ніколи не розумів цього процесу.
мереж

У моїй ситуації, коли кілька тисяч об'єктів створюються послідовно, цей тест я вважаю досить корисним. Гаразд не встановлення лише деяких рядків, а створення об'єктів, які мають одне поле відформатованого рядка.
МаріусА

@marius Ви зіткнулися з проблемою, StringBuilderа потім зробите помилку, використовуючи "0" + номер типу "руїни". @mre JVM's GC надзвичайно хороший у розподілі та збиранні безлічі короткочасних об’єктів, ніяких турбот. Я пішов, String.formatне маючи жодної логіки провідних нулів.
escape-llc

6

Йдучи за відповідь Богема, нам не потрібно використовувати TimeUnit, щоб знайти відоме значення. Набагато оптимальніший був би код

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

Сподіваюся, це допомагає


Найбільше подобається ваша відповідь! Просто проста математика. До речі, в моєму випадку я додав мілісекунди до кінця, millisLeft%1000/10щоб ми отримали форматhour:minutes:seconds:milliseconds
Lê Quang Duy

@ LêQuangDuy мені потрібні мілісекунди в 3 цифри, як 01: 24: 51,123, але твій нарезає 3 нарешті, що робити?
naanu

@naanu просто використовуйтеmillisLeft%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
}

Відповідь залежить від часового поясу, що означає, що результат буде відрізнятися при виконанні в різних часових поясах.
Дерек Махар

6

це працювало для мене, з котліном

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

Для мене прекрасно працювали. Це має бути найкращою відповіддю, оскільки він обробляє нульову годину
vNext

6

Java 9

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

Це відбитки:

01:00:00

Ви робите правильно, дозволяючи бібліотечним методам робити перетворення, що стосуються вас. java.time, сучасний API дати та часу Java, а точніше, його Durationклас робить це більш елегантно і менш схильним до помилок, ніж TimeUnit.

Методи toMinutesPartта toSecondsPartметоди, які я використовував, були представлені в Java 9.

Java 6, 7 і 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);

Вихід такий же, як і вище.

Питання: Як це може працювати в Java 6 і 7?

  • У Java 8 і новіших пристроях Android (з рівня API 26, мені кажуть) java.timeвбудований.
  • У Java 6 та 7 отримайте ThreeTen Backport, опору сучасних класів (ThreeTen для JSR 310; див. Посилання внизу).
  • На (старшому) Android використовують Android-версію ThreeTen Backport. Це називається ThreeTenABP. І переконайтесь, що ви імпортуєте дати та часові класи org.threeten.bpз підпакетів.

Посилання


5

Код нижче робить перетворення в обох напрямках

23: 59: 58: 999 до 86398999

і ніж

86398999 до 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;
    }
}

Я підтримав це рішення. Просто поставте крапку між сек і mls. І я не знаю, чому обробка часу та дати складно на Java. Найбільш використовувані функції повинні бути вже доступними та входити до класу.
Барух Атта

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

Формат: 00: 00: 00.000

Приклад: 615605 Millisecend

00: 10: 15.605


5

Відповідь, позначена правильною, має невелику помилку,

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

наприклад, це приклад значення, яке я отримую:

417474:44:19

Це рішення для отримання потрібного формату:

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

отримання в результаті правильного формату:

18:44:19

Інший варіант отримання формату hh:mm:ss:

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

4

Я спробував, як показано в першій відповіді. Це працює, але мінус ввів мене в замішання. Моя відповідь 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])
}

3

Для Котліна

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

де, milSecsє мілісекундами


1

Ну, ви можете спробувати щось подібне:

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

для перетворення мілісекунд у значення часу

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.