Как я могу" красиво распечатать " продолжительность в Java?


кто-нибудь знает библиотеку Java, которая может довольно печатать число в миллисекундах так же, как и C#?

например, 123456 МС как долго будет печататься как 4d1h3m5s.

10 59

10 ответов:

Джода Времени есть хороший способ сделать это с помощью PeriodFormatterBuilder.

Быстрая Победа: PeriodFormat.getDefault().print(duration.toPeriod());

например

//import org.joda.time.format.PeriodFormatter;
//import org.joda.time.format.PeriodFormatterBuilder;
//import org.joda.time.Duration;

Duration duration = new Duration(123456); // in milliseconds
PeriodFormatter formatter = new PeriodFormatterBuilder()
     .appendDays()
     .appendSuffix("d")
     .appendHours()
     .appendSuffix("h")
     .appendMinutes()
     .appendSuffix("m")
     .appendSeconds()
     .appendSuffix("s")
     .toFormatter();
String formatted = formatter.print(duration.toPeriod());
System.out.println(formatted);

Я создал простое решение, используя Java 8 по Duration.toString() и немного регулярных выражений:

public static String humanReadableFormat(Duration duration) {
    return duration.toString()
            .substring(2)
            .replaceAll("(\d[HMS])(?!$)", " ")
            .toLowerCase();
}

результат будет выглядеть так:

- 5h
- 7h 15m
- 6h 50m 15s
- 2h 5s
- 0.1s

если вы не хотите пробелов между ними, просто удалите replaceAll.

JodaTime есть Period класс, который может представлять такие величины и может быть отображен (через IsoPeriodFormat) в в формате iso8601, например,PT4D1H3M5S, например,

Period period = new Period(millis);
String formatted = ISOPeriodFormat.standard().print(period);

если этот формат не тот, который вы хотите, затем PeriodFormatterBuilder позволяет собирать произвольные макеты, в том числе C#-style 4d1h3m5s.

С Java 8, вы также можете использовать toString() метод java.time.Duration чтобы отформатировать его без внешних библиотек с помощью ISO 8601 секунд на основе представления такие как PT8H6M12.345S.

Apache commons-lang предоставляет полезный класс, чтобы сделать это, а также DurationFormatUtils

например, DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) ) => 4:16:02.000 (H:m:s.millis) DurationFormatUtils.formatDurationISO( 15362 * 1000 ) ) => P0Y0M0DT4H16M2.000С, ср. В формате iso8601

вот как вы можете сделать это с помощью чистого кода JDK:

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;

long diffTime = 215081000L;
Duration duration = DatatypeFactory.newInstance().newDuration(diffTime);

System.out.printf("%02d:%02d:%02d", duration.getDays() * 24 + duration.getHours(), duration.getMinutes(), duration.getSeconds()); 

Я понимаю, что это может не соответствовать вашему случаю использования точно, но PrettyTime может быть полезным здесь.

PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
//prints: “right now”

System.out.println(p.format(new Date(1000*60*10)));
//prints: “10 minutes from now”

альтернативой подходу строителя Джоды-времени было бы решение на основе шаблонов. Это предлагает Моя библиотека Time4J. Пример использования класса длительность.Форматер (добавлено несколько пробелов для большей читаемости-удаление пробелов даст желаемый стиль C#):

IsoUnit unit = ClockUnit.MILLIS;
Duration<IsoUnit> dur = Duration.of(123456, unit).with(Duration.STD_PERIOD);
String s = Duration.Formatter.ofPattern("D'd' h'h' m'm' s.fff's'").format(dur);
System.out.println(s); // output: 0d 0h 2m 3.456s

другой способ-это использование класса net.time4j.PrettyTime (что также хорошо для локализованного вывода и печати относительного времени):

s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.NARROW);
System.out.println(s); // output: 2m 3s 456ms

Java 9

Duration d1 = Duration.ofDays(0);
        d1 = d1.plusHours(47);
        d1 = d1.plusMinutes(124);
        d1 = d1.plusSeconds(124);
System.out.println(String.format("%s d %sh %sm %ss", 
                d1.toDaysPart(), 
                d1.toHoursPart(), 
                d1.toMinutesPart(), 
                d1.toSecondsPart()));

2 d 1h 6m 4s

A Java 8 версия, основанная на ответ пользователя 678573:

    private static String humanReadableFormat(Duration duration) {
    return String.format("%s days and %sh %sm %ss", duration.toDays(),
            duration.toHours() - TimeUnit.DAYS.toHours(duration.toDays()),
            duration.toMinutes() - TimeUnit.HOURS.toMinutes(duration.toHours()),
            duration.getSeconds() - TimeUnit.MINUTES.toSeconds(duration.toMinutes()));
}

... поскольку в Java 8 нет PeriodFormatter и нет таких методов, как getHours, getMinutes,...

Я был бы рад увидеть лучшую версию для Java 8.