Czy ktoś zna bibliotekę Java, która może całkiem wydrukować liczbę w milisekundach w taki sam sposób, jak robi to C #?
Np. 123456 ms jako długość byłoby wydrukowane jako 4d1h3m5s.
Czy ktoś zna bibliotekę Java, która może całkiem wydrukować liczbę w milisekundach w taki sam sposób, jak robi to C #?
Np. 123456 ms jako długość byłoby wydrukowane jako 4d1h3m5s.
%
i /
podzielić numer na części. Niemal łatwiejsze niż niektóre z proponowanych odpowiedzi.
/
i %
.
Odpowiedzi:
Joda Time ma całkiem niezły sposób na zrobienie tego za pomocą PeriodFormatterBuilder .
Szybkie zwycięstwo: PeriodFormat.getDefault().print(duration.toPeriod());
na przykład
//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);
PeriodType.daysTime()
lub .standard()
nie pomogło
Zbudowałem proste rozwiązanie, używając Java 8 Duration.toString()
i trochę wyrażenia regularnego:
public static String humanReadableFormat(Duration duration) {
return duration.toString()
.substring(2)
.replaceAll("(\\d[HMS])(?!$)", "$1 ")
.toLowerCase();
}
Wynik będzie wyglądał następująco:
- 5h
- 7h 15m
- 6h 50m 15s
- 2h 5s
- 0.1s
Jeśli nie chcesz między nimi spacji, po prostu usuń replaceAll
.
Duration::toString
są sformatowane zgodnie z dobrze zdefiniowaną i znaną normą ISO 8601 .
.replaceAll("\\.\\d+", "")
przed wywołaniem toLowerCase()
.
Apache commons-lang zapewnia użyteczną klasę do wykonania tego zadania DurationFormatUtils
np.
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
=> 4: 16: 02.000 (H: m: s.millis)
DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
=> P0Y0M0DT4H16M2.000S, por. ISO8601
JodaTime ma Period
klasę, która może reprezentować takie wielkości i może być renderowana (przez IsoPeriodFormat
) w formacie ISO8601PT4D1H3M5S
, np.
Period period = new Period(millis);
String formatted = ISOPeriodFormat.standard().print(period);
Jeśli ten format nie jest tym, którego potrzebujesz, PeriodFormatterBuilder
umożliwia tworzenie dowolnych układów, w tym stylu C # 4d1h3m5s
.
new Period(millis).toString()
używa ISOPeriodFormat.standard()
.
W Javie 8 można również użyć toString()
metody java.time.Duration
formatowania bez bibliotek zewnętrznych, używając reprezentacji sekundowej ISO 8601, takiej jak PT8H6M12.345S.
Oto, jak możesz to zrobić, używając czystego kodu 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());
org.threeten.extra.AmountFormats.wordBased
Projekt ThreeTen-Extra , który jest prowadzony przez Stephena Colebourne'a, autora JSR 310, java.time i Joda-Time , ma AmountFormats
klasę, która współpracuje ze standardowymi klasami daty i czasu Java 8. Jest jednak dość rozwlekły, bez opcji na bardziej kompaktowe wyjście.
Duration d = Duration.ofMinutes(1).plusSeconds(9).plusMillis(86);
System.out.println(AmountFormats.wordBased(d, Locale.getDefault()));
1 minute, 9 seconds and 86 milliseconds
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
Alternatywą dla podejścia konstruktora w Joda-Time byłoby rozwiązanie oparte na wzorcach . To jest oferowane przez moją bibliotekę Time4J . Przykład użycia klasy Duration.Formatter (dodano kilka spacji dla większej czytelności - usunięcie spacji da pożądany styl C #):
IsoUnit unit = ClockUnit.MILLIS;
Duration<IsoUnit> dur = // normalized duration with multiple components
Duration.of(123456, unit).with(Duration.STD_PERIOD);
Duration.Formatter<IsoUnit> f = // create formatter/parser with optional millis
Duration.Formatter.ofPattern("D'd' h'h' m'm' s[.fff]'s'");
System.out.println(f.format(dur)); // output: 0d 0h 2m 3.456s
Ten program formatujący może również drukować czasy trwania java.time
-API (jednak funkcje normalizacji tego typu są mniej wydajne):
System.out.println(f.format(java.time.Duration.ofMillis(123456))); // output: 0d 0h 2m 3.456s
Oczekiwanie OP, że „123456 ms jako długość zostanie wydrukowane jako 4d1h3m5s” jest obliczane w oczywiście nieprawidłowy sposób. Za powód przyjmuję niechlujstwo. Ten sam program formatujący czas trwania zdefiniowany powyżej może być również używany jako parser. Poniższy kod pokazuje, że „4d1h3m5s” odpowiada raczej 349385000 = 1000 * (4 * 86400 + 1 * 3600 + 3 * 60 + 5)
:
System.out.println(
f.parse("4d 1h 3m 5s")
.toClockPeriodWithDaysAs24Hours()
.with(unit.only())
.getPartialAmount(unit)); // 349385000
Innym sposobem jest użycie klasy net.time4j.PrettyTime
(co jest również dobre w przypadku zlokalizowanych wyników i drukowania względnych czasów, takich jak „wczoraj”, „następna niedziela”, „4 dni temu” itp.):
String s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.NARROW);
System.out.println(s); // output: 2m 3s 456ms
s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.WIDE);
System.out.println(s); // output: 2 minutes, 3 seconds, and 456 milliseconds
s = PrettyTime.of(Locale.UK).print(dur, TextWidth.WIDE);
System.out.println(s); // output: 2 minutes, 3 seconds and 456 milliseconds
Szerokość tekstu określa, czy używane są skróty, czy nie. Format listy można również kontrolować, wybierając odpowiednie ustawienie regionalne. Na przykład standardowy angielski używa przecinka Oxform, podczas gdy w Wielkiej Brytanii nie. Najnowsza wersja v5.5 Time4J obsługuje ponad 90 języków i wykorzystuje tłumaczenia oparte na repozytorium CLDR (standard branżowy).
Wersja Java 8 oparta na odpowiedzi użytkownika678573 :
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()));
}
... ponieważ w Javie 8 nie ma PeriodFormatter ani metod takich jak getHours, getMinutes, ...
Byłbym szczęśliwy, mogąc zobaczyć lepszą wersję dla Java 8.
Zdaję sobie sprawę, że może to nie pasować dokładnie do twojego przypadku użycia, ale PrettyTime może być tutaj przydatne.
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”
Duration
zdefiniowany w rozsądnym standardzie ISO 8601 :PnYnMnDTnHnMnS
gdzieP
oznacza „Okres” i oznacza początek,T
oddziela część daty od części czasu, a pomiędzy nimi są opcjonalne wystąpienia liczby z pojedynczym -skrót liter. Na przykładPT4H30M
= cztery i pół godziny.