Хтось знає про бібліотеку Java, яка може надрукувати число за мілісекунди так само, як це робить C #?
Наприклад, довжина 123456 мс надрукується як 4d1h3m5s.
Хтось знає про бібліотеку Java, яка може надрукувати число за мілісекунди так само, як це робить C #?
Наприклад, довжина 123456 мс надрукується як 4d1h3m5s.
%
та, /
щоб розділити число на частини. Майже простіше, ніж деякі із запропонованих відповідей.
/
і %
.
Відповіді:
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);
PeriodType.daysTime()
або .standard()
не допомогло
Я створив просте рішення, використовуючи 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
.
Duration::toString
відформатовані відповідно до чітко визначеного та зношеного стандарту ISO 8601 .
.replaceAll("\\.\\d+", "")
перед викликом до toLowerCase()
.
Apache commons-lang надає корисний клас, щоб це зробити, а також DurationFormatUtils
напр.
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
=> 4: 16: 02.000 (В: м: с.millis)
DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
=> P0Y0M0DT4H16M2.000S, пор. ISO8601
JodaTime має Period
клас, який може представляти такі величини, і може бути відтворений (через IsoPeriodFormat
) у форматі ISO8601 , наприклад PT4D1H3M5S
, напр.
Period period = new Period(millis);
String formatted = ISOPeriodFormat.standard().print(period);
Якщо цей формат не той, який ви бажаєте, то PeriodFormatterBuilder
дозволяє збирати довільні макети, включаючи ваш стиль C # 4d1h3m5s
.
new Period(millis).toString()
використовується параметр ISOPeriodFormat.standard()
.
З 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());
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
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 с
Альтернативою будівельному підходу Joda-Time було б рішення на основі шаблону . Це пропонує моя бібліотека Time4J . Приклад використання класу Duration.Formatter (додано кілька пробілів для більшої читабельності - видалення пробілів дасть бажаний стиль 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
Цей форматор може також друкувати тривалість java.time
-API (однак, функції нормалізації цього типу менш потужні):
System.out.println(f.format(java.time.Duration.ofMillis(123456))); // output: 0d 0h 2m 3.456s
Очікування OP, що "123456 мс буде надруковано як 4d1h3m5s", обчислюється очевидно неправильно. Я вважаю недбалість причиною. Той самий форматтер тривалості, визначений вище, також може бути використаний як парсер. Наступний код показує, що "4d1h3m5s" швидше відповідає 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
Інший спосіб - використання класу net.time4j.PrettyTime
(що також добре для локалізованого виводу та друку відносного часу, наприклад "вчора", "наступної неділі", "4 дні тому" тощо):
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
Ширина тексту визначає, використовуються скорочення чи ні. Форматом списку можна також керувати, вибравши відповідний регіон. Наприклад, у стандартній англійській мові використовується кома Oxform, тоді як у Великобританії - ні. Остання версія v5.5 Time4J підтримує понад 90 мов і використовує переклади на основі репозиторію CLDR (галузевий стандарт).
Версія 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.
Я розумію, що це може не відповідати вашому випадку використання, але 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”
Duration
визначений розумним стандартом ISO 8601 :PnYnMnDTnHnMnS
деP
означає "Період" і позначає початок,T
відокремлює дату від часової частини, а між ними - необов'язкові випадки зустрічальності числа з одним -буквене скорочення. Наприклад,PT4H30M
= чотири з половиною години.