Как отформатировать продолжительность в Java? (например, формат H: MM: SS) - PullRequest
135 голосов
/ 06 ноября 2008

Я хотел бы отформатировать длительность в секундах, используя шаблон типа H: MM: SS. Текущие утилиты в Java предназначены для форматирования времени, но не продолжительности.

Ответы [ 17 ]

180 голосов
/ 06 ноября 2008

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

  String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
85 голосов
/ 05 сентября 2013

Я использую Apache Common's DurationFormatUtils примерно так:

DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);
74 голосов
/ 06 ноября 2008

Если вы используете версию Java до 8 ... вы можете использовать Joda Time и PeriodFormatter. Если у вас действительно есть длительность (то есть истекшее количество времени, без ссылки на систему календаря), то вам, вероятно, следует использовать Duration по большей части - тогда вы можете позвонить toPeriod (указав любое значение PeriodType вы хотите отразить, станет ли 25 часов 1 днем ​​и 1 часом и т. д.), чтобы получить Period, который вы можете отформатировать.

Если вы используете Java 8 или более позднюю версию: обычно я рекомендую использовать java.time.Duration для представления продолжительности. Затем вы можете позвонить getSeconds() или тому подобное, чтобы получить целое число для стандартного форматирования строки в соответствии с ответом Бобинса, если вам нужно - хотя вы должны быть осторожны с ситуацией, когда длительность отрицательна, поскольку вы, вероятно, хотите сингл отрицательный знак в выходной строке. Так что-то вроде:

public static String formatDuration(Duration duration) {
    long seconds = duration.getSeconds();
    long absSeconds = Math.abs(seconds);
    String positive = String.format(
        "%d:%02d:%02d",
        absSeconds / 3600,
        (absSeconds % 3600) / 60,
        absSeconds % 60);
    return seconds < 0 ? "-" + positive : positive;
}

Форматировать таким способом достаточно просто, если надоедливо вручную. Для разбора это становится сложнее в общем ... Вы все равно можете использовать Joda Time даже с Java 8, если хотите, конечно.

24 голосов
/ 22 мая 2011
long duration = 4 * 60 * 60 * 1000;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
log.info("Duration: " + sdf.format(new Date(duration - TimeZone.getDefault().getRawOffset())));
18 голосов
/ 03 июня 2017

Это будет проще с Java 9. A Duration по-прежнему не форматируется (что я знаю), но добавлены методы для получения часов, минут и секунд, что делает задачу несколько более простой:

        Duration diff = // ...;
        String hms = String.format("%d:%02d:%02d", 
                                   diff.toHoursPart(),
                                   diff.toMinutesPart(), 
                                   diff.toSecondsPart());
7 голосов
/ 25 января 2015

Это может показаться хакерским, но это хорошее решение, если кто-то захочет выполнить это с помощью Java 8 java.time:

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.time.temporal.UnsupportedTemporalTypeException;

public class TemporalDuration implements TemporalAccessor {
    private static final Temporal BASE_TEMPORAL = LocalDateTime.of(0, 1, 1, 0, 0);

    private final Duration duration;
    private final Temporal temporal;

    public TemporalDuration(Duration duration) {
        this.duration = duration;
        this.temporal = duration.addTo(BASE_TEMPORAL);
    }

    @Override
    public boolean isSupported(TemporalField field) {
        if(!temporal.isSupported(field)) return false;
        long value = temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
        return value!=0L;
    }

    @Override
    public long getLong(TemporalField field) {
        if(!isSupported(field)) throw new UnsupportedTemporalTypeException(new StringBuilder().append(field.toString()).toString());
        return temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
    }

    public Duration getDuration() {
        return duration;
    }

    @Override
    public String toString() {
        return dtf.format(this);
    }

    private static final DateTimeFormatter dtf = new DateTimeFormatterBuilder()
            .optionalStart()//second
            .optionalStart()//minute
            .optionalStart()//hour
            .optionalStart()//day
            .optionalStart()//month
            .optionalStart()//year
            .appendValue(ChronoField.YEAR).appendLiteral(" Years ").optionalEnd()
            .appendValue(ChronoField.MONTH_OF_YEAR).appendLiteral(" Months ").optionalEnd()
            .appendValue(ChronoField.DAY_OF_MONTH).appendLiteral(" Days ").optionalEnd()
            .appendValue(ChronoField.HOUR_OF_DAY).appendLiteral(" Hours ").optionalEnd()
            .appendValue(ChronoField.MINUTE_OF_HOUR).appendLiteral(" Minutes ").optionalEnd()
            .appendValue(ChronoField.SECOND_OF_MINUTE).appendLiteral(" Seconds").optionalEnd()
            .toFormatter();

}
6 голосов
/ 06 сентября 2016

Вот еще один пример, как отформатировать длительность. Обратите внимание, что этот образец показывает как положительную, так и отрицательную продолжительность как положительную продолжительность.

import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.HOURS;
import static java.time.temporal.ChronoUnit.MINUTES;
import static java.time.temporal.ChronoUnit.SECONDS;

import java.time.Duration;

public class DurationSample {
    public static void main(String[] args) {
        //Let's say duration of 2days 3hours 12minutes and 46seconds
        Duration d = Duration.ZERO.plus(2, DAYS).plus(3, HOURS).plus(12, MINUTES).plus(46, SECONDS);

        //in case of negative duration
        if(d.isNegative()) d = d.negated();

        //format DAYS HOURS MINUTES SECONDS 
        System.out.printf("Total duration is %sdays %shrs %smin %ssec.\n", d.toDays(), d.toHours() % 24, d.toMinutes() % 60, d.getSeconds() % 60);

        //or format HOURS MINUTES SECONDS 
        System.out.printf("Or total duration is %shrs %smin %sec.\n", d.toHours(), d.toMinutes() % 60, d.getSeconds() % 60);

        //or format MINUTES SECONDS 
        System.out.printf("Or total duration is %smin %ssec.\n", d.toMinutes(), d.getSeconds() % 60);

        //or format SECONDS only 
        System.out.printf("Or total duration is %ssec.\n", d.getSeconds());
    }
}
6 голосов
/ 06 ноября 2008

Это будет одна из новых функций в Java 7

JSR-310

3 голосов
/ 01 апреля 2014

Это рабочий вариант.

public static String showDuration(LocalTime otherTime){          
    DateTimeFormatter df = DateTimeFormatter.ISO_LOCAL_TIME;
    LocalTime now = LocalTime.now();
    System.out.println("now: " + now);
    System.out.println("otherTime: " + otherTime);
    System.out.println("otherTime: " + otherTime.format(df));

    Duration span = Duration.between(otherTime, now);
    LocalTime fTime = LocalTime.ofNanoOfDay(span.toNanos());
    String output = fTime.format(df);

    System.out.println(output);
    return output;
}

Вызовите метод с помощью

System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));

Производит что-то вроде:

otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463
2 голосов
/ 28 июня 2017

Как насчет следующей функции, которая возвращает либо + Н: ММ: СС или же + H: MM: СС.ссс

public static String formatInterval(final long interval, boolean millisecs )
{
    final long hr = TimeUnit.MILLISECONDS.toHours(interval);
    final long min = TimeUnit.MILLISECONDS.toMinutes(interval) %60;
    final long sec = TimeUnit.MILLISECONDS.toSeconds(interval) %60;
    final long ms = TimeUnit.MILLISECONDS.toMillis(interval) %1000;
    if( millisecs ) {
        return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
    } else {
        return String.format("%02d:%02d:%02d", hr, min, sec );
    }
}
...