Как я могу "красиво напечатать" Duration в Java? - PullRequest
71 голосов
/ 12 августа 2010

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

Например, длина 123456 мс будет напечатана как 4d1h3m5s.

Ответы [ 11 ]

85 голосов
/ 12 августа 2010

Joda Time имеет довольно хороший способ сделать это, используя PeriodFormatterBuilder .

Быстрый выигрыш: PeriodFormat.getDefault().print(duration.toPeriod());

1010 *, например *

//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);
47 голосов
/ 08 ноября 2016

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

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

Результат будет выглядеть следующим образом:

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

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

9 голосов
/ 25 апреля 2013

Apache commons-lang также предоставляет полезный класс для этого * DurationFormatUtils

например. DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) ) => 4: 16: 02.000 (Ч: м: с.миллис) DurationFormatUtils.formatDurationISO( 15362 * 1000 ) ) => P0Y0M0DT4H16M2.000S, ср. ISO8601

9 голосов
/ 12 августа 2010

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

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

Если этот формат не тот, который вам нужен, тогда PeriodFormatterBuilder позволяет вам собирать произвольные макеты, включая ваш C # -стиль 4d1h3m5s.

8 голосов
/ 20 марта 2014

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

6 голосов
/ 01 мая 2013

Вот как вы можете сделать это, используя чистый код 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()); 
4 голосов
/ 08 августа 2018

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 д 1 ч 6 м 4 с

4 голосов
/ 01 мая 2013

Я понимаю, что это может не совсем соответствовать вашему варианту использования, но 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”
3 голосов
/ 19 апреля 2019

org.threeten.extra.AmountFormats.wordBased

Проект ThreeTen-Extra , который поддерживается Стивеном Колебурном, автором JSR 310, java.time и Joda-Time , имеет класс AmountFormats, который работает со стандартными классами даты и времени Java 8. Хотя это довольно многословно, без возможности более компактного вывода.

Duration d = Duration.ofMinutes(1).plusSeconds(9).plusMillis(86);
System.out.println(AmountFormats.wordBased(d, Locale.getDefault());

1 minute, 9 seconds and 86 milliseconds

3 голосов
/ 28 января 2015

Альтернативой подходу Joda-Time для строителей было бы решение на основе шаблонов . Это предложено моей библиотекой Time4J . Пример использования класса Duration.Formatter (добавлены некоторые пробелы для большей читабельности - удаление пробелов приведет к желаемому стилю 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
...