有谁知道Java库可以像C#一样以毫秒为单位打印数字?
例如,最长的123456 ms将被打印为4d1h3m5s。
有谁知道Java库可以像C#一样以毫秒为单位打印数字?
例如,最长的123456 ms将被打印为4d1h3m5s。
%
,并/
以数量分成几部分。几乎比一些建议的答案容易。
/
and 更干净,更清晰的代码%
。
Answers:
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(H:m:s.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
由JSR 310,java.time和Joda-Time的作者Stephen Colebourne维护的ThreeTen-Extra项目具有一个与标准Java 8日期时间类一起使用的类。不过,它相当冗长,没有选择可提供更紧凑的输出。AmountFormats
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
基于模式的解决方案可以替代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 ms将被打印为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逗号,而英国则不使用。Time4J的最新版本v5.5支持90多种语言,并使用基于CLDR存储库(行业标准)的翻译。
一个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的更好版本。
我意识到这可能不完全适合您的用例,但是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
=四个半小时。