Как конвертировать миллисекунды в «X минут, x секунд» в Java?

573

Я хочу записать время, System.currentTimeMillis()когда пользователь начинает что-то в моей программе. Когда он закончит, я вычту ток System.currentTimeMillis()из startпеременной, и я хочу показать им, сколько времени прошло, используя читаемый человеком формат, такой как «XX часов, XX минут, XX секунд» или даже «XX минут, XX секунд», потому что его вряд ли займет у кого-то час.

Какой лучший способ сделать это?

Нажмите Upvote
источник
5
Если они занимают больше часа, вы все равно можете напечатать что-то вроде; 90 минут, 53 секунды.
Питер Лори
1
мой ответ приходит на 6 лет позже, но я думаю, что он более общий, чем принятый: stackoverflow.com/a/35082080/82609
Себастьен Лорбер
1
посмотрите простой пример для преобразования миллисекунд в дни, часы, минуты, секунды в Java
sumit kumar pradhan

Ответы:

1229

Используйте java.util.concurrent.TimeUnitкласс:

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

Замечания: TimeUnit является частью спецификации Java 1.5, но toMinutesбыло добавлено начиная с Java 1.6.

Чтобы добавить начальный ноль для значений 0-9, просто выполните:

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

Если TimeUnitили toMinutesне поддерживается (например, в Android до API версии 9), используйте следующие уравнения:

int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours   = (int) ((milliseconds / (1000*60*60)) % 24);
//etc...
siddhadev
источник
5
int months = (int) ((float) days / 30.4368499f); int years = (int) ((float) days / 365.242199f);
Натан Шверманн
7
Я бы предложил использовать мод 60 вместо того, чтобы вычитать минуты, это выглядит чище. Тем не менее, нужно знать, что 1 мин = 60 сек, чтобы сделать это ... =)
Per Alexandersson
2
@AndreasDietrich SimpleDateFormat не работает для временных разниц, так как он возвращает только дату из эпохи!
Мухаммед Бабар,
5
int hours = (int) ((milliseconds / (1000*60*60)) % 24)это не работает! вместо этого должно быть такint hours = (int) (milliseconds / (1000*60*60)) ;
Мухаммад Бабар
5
Если кто-то хочет формат для видеофайлов ( ч: мм: сс ):String.format("%01d:%02d:%02d", hours, minutes, seconds);
kazy
124

Основываясь на ответе @ siddhadev, я написал функцию, которая преобразует миллисекунды в форматированную строку:

   /**
     * 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());
    }
Брент пишет код
источник
2
Вы должны сделать там проверку для одного / нескольких, чтобы избежать такой ситуации:1 Days 1 Hours 1 Minutes 1 Seconds
Даниэль
7
Мы могли бы использовать функцию модуля вместо вычитания: 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; а также метод String.format:return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds", days, hours, minutes, seconds, milliseconds);
Хосе Тепедино
78
long time = 1536259;

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

Печать:

25: 36: 259

Damien
источник
1
Мне нравится вышеупомянутый подход лучше всего, если ни для чего еще его простота! Поскольку мы имеем дело со временем и продолжительностью, я обычно использую Joda. Например, если у вас есть два DateTimes, соответственно начинайте и заканчивайте:Duration dur = new Duration(start, end); long millis = dur.getMillis();
TechTrip
1
Я должен был отметить 2 способа использования форматировщиков Joda. Первый вариант вашей темы: DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time)); Или конвертируйте Длительность в Период, который может автоматически печататься с использованием Joda PeriodFormatter. Преобразование может иметь потерю точности, если отличается от хронологии ISO. Предположим, Duration представлен переменной duration. Period period = duration.toPeriod().normalizedStandard(PeriodType.time()); PeriodFormat.getDefault().print(period)) Вывод потрясающий: 1 секунда и 581 миллисекунда, отвечая на главный вопрос выше.
TechTrip
2
Немного поздно здесь :) Но разве вам не нужно помещать simpleDateFormat.setTimezone (TimeZone.getTimeZone ("GMT")) здесь, если только это не ваш фактический часовой пояс?
Olle Söderström
@ OlleSöderström Здесь действительно есть проблема с часовым поясом. Но установка его на GMT или UTC приводит к тому, что часовая часть будет 12 вместо 0 для всех длительностей менее 1 часа.
Episodex
2
Часовой пояс не единственная проблема здесь ... этот ответ вводит в заблуждение и может серьезно запутать новичков в Java. Даже игнорируя избыточные внешние скобки, ОП спросил, как представить продолжительность (разница между двумя моментами времени, измеренная в мс). Назвать эту длительность «временем» и рассматривать ее как смещение с 1 января 1970 года только для форматирования ее меньших компонентов - это просто ... неправильно, с моей точки зрения. Более того, тот же самый подход уже был предложен 3 годами ранее этим ответом (см. Комментарии там для более подробной информации о проблемах с часовым поясом).
Амос М. Карпентер
36

Хм ... сколько миллисекунд в секунду? А через минуту? Деление не так сложно.

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

Продолжайте так часами, днями, неделями, месяцами, годом, десятилетиями, чем угодно.

Бомбы
источник
2
На самом деле, делать это дольше, чем час, не очень хорошая идея, так как результаты могут быть неверными / неинтуитивными, если речь идет о летнем времени (дни 23 или 24 часа) или високосных годах. Если я прочитаю «X произойдет через 1 год / месяц», я ожидаю, что это будут те же дата и время.
Майкл Боргвардт
5
System.currentTimeMillis () невосприимчив к DST, поэтому его не следует путать с дополнительными или отсутствующими часами. Если вам нужно показать разницу между двумя конкретными датами, лучше построить объекты Date с заданным временем и показать разницу между этими двумя.
Бомба
1
За неделями он не определен, так как длина месяца является переменной. Так что, действительно, вам нужно вычислить относительно заданной временной привязки.
PhiLho
31

Используя пакет java.time в Java 8:

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

Вывод в формате ISO 8601 Продолжительность : PT1M3.553S(1 минута и 3,553 секунды).

Виталий Федоренко
источник
1
(ANDROID) Требуется уровень API 26
Кто-то где-то
1
@SomeoneSomewhere Для Android под API уровня 26 используйте backport, смотрите Как использовать ThreeTenABP в Android Project .
Оле В.В.
1
Это круто :) спасибо за хедз-ап!
Кто-то где-то
27

Я бы не стал использовать дополнительную зависимость только для этого (в конце концов, деление не так уж сложно), но если вы все равно используете Commons Lang, есть DurationFormatUtils .

Пример использования (адаптировано отсюда ):

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

Пример:

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

//Output: 2s

Примечание . Чтобы получить миллис из двух объектов LocalDateTime, вы можете использовать:

long age = ChronoUnit.MILLIS.between(initTime, LocalDateTime.now())
Тило
источник
1
Отлично, я просто спрашивал себя, существует ли надежная библиотека, включающая в себя такие вещи.
Лайчик
Поскольку ссылка, как правило, не очень полезна, я добавил пример ее использования.
Леп
26

Либо деление рук, либо используйте 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)));

Редактировать Bombe : в комментариях было показано, что этот подход работает только в течение меньших периодов времени (т. Е. Менее суток).

cadrian
источник
Ух ты. Это злой взлом, зависящий от часового пояса. Он безжалостно сломается, если у вас есть смещение часового пояса, не кратное 60 минутам (и у нас есть пара этих надоедливых 30-минутных часовых поясов со смещением в мире).
Бомба
Кроме того, он сломается так же плохо, как только вы включите часы в строку формата и не в GMT + 0, по тем же причинам.
Бомба
Мы делаем? В самом деле? Куда? Не сомневаюсь, просто никогда не слышал об этом раньше - какая-то новая ловушка для рассмотрения ;-)
Треб
Да. Проверьте «Список часовых поясов» в Википедии, например, Непал в GMT + 05: 45.
Бомба
2
Кадриан, теперь он будет работать только в течение менее одного дня. Количество часов всегда будет от 0 до 23 включительно.
Бомба
21

Просто чтобы добавить больше информации, если вы хотите отформатировать как: ЧЧ: мм: сс

0 <= ЧЧ <= бесконечно

0 <= мм <60

0 <= сс <60

использовать этот:

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

Я только что имел эту проблему сейчас и понял это

fredcrs
источник
1
Лучший ответ здесь. Почему все хотят усложнить ситуацию? Это простая математика, ребята.
Ламбарт
11

Я думаю, что лучший способ это:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toSeconds(length)/60,
    TimeUnit.MILLISECONDS.toSeconds(length) % 60 );
Xtera
источник
в течение нескольких минут вы можете использовать TimeUnit.MILLISECONDS.toMinutes (длина)
EminenT
11

Кратчайшее решение:

Вот, вероятно, самый короткий, который также касается часовых поясов.

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

Какие выводы, например:

00:18:32

Объяснение:

%tTвремя, отформатированное для 24-часовых часов как %tH:%tM:%tS.

%tTтакже принимает long в качестве входных данных, поэтому нет необходимости создавать Date.printf()просто напечатает время, указанное в миллисекундах, но в текущем часовом поясе, поэтому мы должны вычесть необработанное смещение текущего часового пояса, так что 0 миллисекунд будут 0 часов, а не значение смещения времени текущего часового пояса.

Примечание # 1: Если вам нужен результат как String, вы можете получить его , как это:

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

Примечание № 2: Это дает правильный результат, только если millisоно меньше дня, потому что часть дня не включена в выходные данные.

icza
источник
Это такой отличный способ, но когда я его использую, я не получаю ожидаемых результатов. Итак, у меня есть: long millis = 8398;и когда я String.format("%tT", millis)передаю это на мой выходной 19:00:08. Откуда 19?
Nelda.techspiress
1
@ Nelda.techspiress Это смещение вашего часового пояса. Вы должны вычесть TimeZone.getDefault().getRawOffset()из него точно так, как написано в ответе:String.format("%tT", millis-TimeZone.getDefault().getRawOffset())
icza
это позаботилось об этом. Спасибо за разъяснения.
Nelda.techspiress
8

Joda времени

Использование 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));
кендырь
источник
1
Нет необходимости PeriodFormatв последней строке. Просто позвоните, Period::toStringчтобы получить строку длительности ISO 8601 по умолчанию.
Базилик Бурк
8

Возвращаясь к вкладу @ brent-nash, мы можем использовать функцию модуля вместо вычитаний и использовать метод String.format для строки результата:

  /**
   * 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);
   }
Хосе Тепедино
источник
6

для Android ниже 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)) 
Прадип
источник
5

Для небольших времен, менее часа, я предпочитаю:

long millis = ...

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

для более длинных интервалов:

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);
}
user85421
источник
Это очень полезный совет. Существует много таких возможностей для даты и времени с API Java Formatter ( docs.oracle.com/javase/8/docs/api/java/util/Formatter.html )! Вы также можете получить результат условия else с: System.out.printf ("% 1 $ tH:% 1 $ tM:% 1 $ tS% n", миллис); или даже System.out.printf ("% 1 $ tT% n", миллис);
Хосе Тепедино
@JoseTepedino, но вы знаете, что показывает %tH только от 0 до 23 часов? Это означает, что, например, 24 часа будут отображаться как 00, 25 часов как 01... те же самые действительные в течение %tT- дней будут молча отбрасываться. Конечно, могут также отображаться дни, но это будет излишним для той проблемы, которая возникла у меня, когда я писал это (в далеком 2011 году) [:-)
user85421
Понятно ... это действительно сработало бы только раз меньше суток (24 часа). Спасибо.
Хосе Тепедино,
5

Мой простой расчет:

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

Удачного кодирования :)

Шохан Ахмед Сиян
источник
Я полагаю, что long больше подходит для этой функции, поскольку System.currentTimeMillis () возвращает длинное значение.
Апродан
Это не правильно, вы проверили вывод?
Jorgesys
4

Вот ответ, основанный на ответе Брента Нэша, надеюсь, это поможет!

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());
}
Реда Буаичи
источник
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
Фатх Рехман П
источник
3
Формула в строке 6 неверна. diff=diff-(hours*60*1000);должно бытьdiff=diff-(hours*60*60*1000); . Я попытался отредактировать его, но раздражающая политика редактирования StackOverflow говорит, что для редактирования недостаточно символов.
quux00
4

Во-первых, System.currentTimeMillis()и Instant.now()не идеальны по срокам. Они оба сообщают время настенных часов, которое компьютер не знает точно, и которое может двигаться хаотично, в том числе возвращаться назад, если, например, демон NTP корректирует системное время. Если ваш тайминг происходит на одной машине, вы должны вместо этого использовать System.nanoTime () .

Во-вторых, с Java 8 и выше java.time.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"
MikeFHay
источник
3

Если вы знаете, что разница во времени будет меньше часа, вы можете использовать следующий код:

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

Это приведет к: 51:00

Гурав Сингла
источник
3

Этот ответ похож на некоторые ответы выше. Тем не менее, я чувствую, что это было бы полезно, потому что, в отличие от других ответов, это удалит лишние запятые или пробелы и обрабатывает аббревиатуру.

/**
 * 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);
}
Джаред Раммлер
источник
3

Существует проблема. Когда миллисекунды равны 59999, фактически это 1 минута, но она будет вычислена как 59 секунд, и 999 миллисекунд будут потеряны.

Вот модифицированная версия, основанная на предыдущих ответах, которая может решить эту потерю:

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
источник
2

Это проще в Java 9:

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

Это производит строку как 0 hours, 39 mins, 9 seconds.

Если вы хотите округлить до целых секунд перед форматированием:

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

Чтобы оставить часы, если они 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());
    }

Теперь мы можем иметь, например, 39 mins, 9 seconds.

Чтобы напечатать минуты и секунды с нулем в начале, чтобы они всегда были двумя цифрами, просто вставьте 02в соответствующие спецификаторы формата, таким образом:

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

Теперь мы можем иметь, например 0 hours, 39 mins, 09 seconds.

Оле В.В.
источник
Любое форматирование для удаления часов / минут / секунд, когда предыдущее число равно 0? Я имею в виду, что это достижимо с условием if else, но как насчет существования такого форматирования String или чего-то близкого, есть ли такое?
Фарид
1
Нет, извини, @FARID, тебе нужно if- elseтам.
Оле В.В.
1

для правильных строк («1 час, 3 секунды», «3 минуты», но не «0 часов, 0 минут, 3 секунды») я пишу этот код:

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";
Джон
источник
1

Я изменил ответ @MyKuLLSKI и добавил поддержку плюрилизации. Я взял секунды, потому что они мне не нужны, хотя можете смело добавлять их заново, если они вам нужны.

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" : "");
}
битовый поток
источник
int intervalMins vs long millis
Kiquenet
1

Я рассмотрел это в другом ответе, но вы можете сделать:

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

Вывод примерно такой Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}, с заказанными единицами.

Вам решать, как интернационализировать эти данные в соответствии с целевым языковым стандартом.

Себастьян Лорбер
источник
1

Используйте java.util.concurrent.TimeUnit и используйте этот простой метод:

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

Например:

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));
Арамис Родригес Бланко
источник