Кто-нибудь знает библиотеку Java, которая может печатать числа в миллисекундах так же, как это делает С#?
Например, длина 123456 мс будет напечатана как 4d1h3m5s.
Кто-нибудь знает библиотеку Java, которая может печатать числа в миллисекундах так же, как это делает С#?
Например, длина 123456 мс будет напечатана как 4d1h3m5s.
Joda Time имеет довольно хороший способ сделать это, используя PeriodFormatterBuilder.
Quick Win: 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])(?!$)", "$1 ")
.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
позволяет собирать произвольные макеты, включая ваш С#-стиль 4d1h3m5s
.
Apache commons-lang предоставляет полезный класс, чтобы сделать это также DurationFormatUtils
например.
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
= > 4: 16: 02.000 (H: m: s.millis)
DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
= > P0Y0M0DT4H16M2,000S, ср. ISO8601
С помощью Java 8 вы также можете использовать toString()
метод java.time.Duration
, чтобы отформатировать его без внешних библиотек, используя ISO 8601 секундное представление, например PT8H6M12.345S.
Вот как вы можете это сделать, используя чистый код 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"
Ява 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 с
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
Альтернативой строительному подходу Joda-Time будет шаблонное решение. Это предлагается моей библиотекой Time4J. Пример использования класса Duration.Formatter (добавлены некоторые пробелы для большей удобочитаемости - удаление пробелов приведет к желаемому стилю С#):
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 8, основанная на ответе user678573:
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.