web-dev-qa-db-ja.com

JavaでDurationを「きれいに印刷」するにはどうすればよいですか?

C#と同じようにミリ秒単位で数字をきれいに出力できるJavaライブラリを知っている人はいますか?

たとえば、123456ミリ秒は4d1h3m5sとして印刷されます。

72
phatmanace

Joda Time には 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);
86
Rob Hruska

Java 8のDuration.toString()と少しの正規表現を使用して、簡単なソリューションを構築しました。

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を削除してください。

49
lucasls

JodaTime には Period があり、そのような量を表すことができ、レンダリングできます( IsoPeriodFormat を使用) ISO8601 形式、たとえばPT4D1H3M5S、例:.

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

その形式が必要な形式でない場合、 PeriodFormatterBuilder を使用すると、C#スタイル4d1h3m5sを含む任意のレイアウトを組み立てることができます。

10
skaffman

Apache commons-langは、これを行うための便利なクラスを提供します DurationFormatUtils

例えばDurationFormatUtils.formatDurationHMS( 15362 * 1000 ) ) => 4:16:02.000(H:m:s.millis)DurationFormatUtils.formatDurationISO( 15362 * 1000 ) ) => P0Y0M0DT4H16M2.000S、cf。 ISO8601

10
noleto

Java 8を使用すると、 toString() メソッドの Java.time.DurationISO 8601秒ベースの表現 PT8H6M12.345Sなどを使用して、外部ライブラリなしでフォーマットします。

8
Konrad Höffner

純粋な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()); 
6
user678573

私はこれがあなたのユースケースに正確に適合しないかもしれないことを理解していますが、ここでは 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”
4
Nick

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

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
3
Meno Hochschild

Java 8バージョンに基づいた ser678573の回答

    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。

3
Torsten