如何在 Java 中“漂亮地打印”持续时间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3471397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I "pretty print" a Duration in Java?
提问by phatmanace
Does anyone know of a Java library that can pretty print a number in milliseconds in the same way that C# does?
有谁知道可以像 C# 那样以毫秒为单位漂亮地打印一个数字的 Java 库?
E.g., 123456 ms as a long would be printed as 4d1h3m5s.
例如, 123456 ms 作为 long 将被打印为 4d1h3m5s。
采纳答案by Rob Hruska
Joda Timehas a pretty good way to do this using a PeriodFormatterBuilder.
Joda Time使用PeriodFormatterBuilder有一个很好的方法来做到这一点。
Quick Win: PeriodFormat.getDefault().print(duration.toPeriod());
速赢: PeriodFormat.getDefault().print(duration.toPeriod());
e.g.
例如
//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);
回答by skaffman
JodaTimehas a Period
class that can represent such quantities, and can be rendered (via IsoPeriodFormat
) in ISO8601format, e.g. PT4D1H3M5S
, e.g.
JodaTime有一个Period
类可以表示这样的数量,并且可以(通过IsoPeriodFormat
)以ISO8601格式呈现,例如PT4D1H3M5S
,例如
Period period = new Period(millis);
String formatted = ISOPeriodFormat.standard().print(period);
If that format isn't the one you want, then PeriodFormatterBuilder
lets you assemble arbitrary layouts, including your C#-style 4d1h3m5s
.
如果该格式不是您想要的格式,那么PeriodFormatterBuilder
您可以组合任意布局,包括 C# 样式的4d1h3m5s
.
回答by noleto
Apache commons-lang provides a useful class to get this done as well DurationFormatUtils
Apache commons-lang 也提供了一个有用的类来完成这项工作DurationFormatUtils
e.g.
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
=> 4:16:02.000 (H:m:s.millis)
DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
=> P0Y0M0DT4H16M2.000S, cf. ISO8601
例如
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
=> 4:16:02.000 (H:m:s.millis)
DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
=> P0Y0M0DT4H16M2.000S,参见。ISO8601
回答by user678573
Here's how you can do it using pure JDK code:
以下是使用纯 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());
回答by Nick
I realize this might not fit your use case exactly, but PrettyTimemight be useful here.
我意识到这可能不完全适合您的用例,但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”
回答by Konrad H?ffner
With Java 8 you can also use the toString()
method of java.time.Duration
to format it without external libraries using ISO 8601 seconds based representationsuch as PT8H6M12.345S.
使用 Java 8,您还可以使用基于 ISO 8601 秒的表示形式(例如 PT8H6M12.345S)在没有外部库的情况toString()
下对其java.time.Duration
进行格式化的方法。
回答by Meno Hochschild
An alternative to the builder-approach of Joda-Time would be a pattern-based solution. This is offered by my library Time4J. Example using the class Duration.Formatter(added some spaces for more readability - removing the spaces will yield the wished C#-style):
Joda-Time 的 builder-approach 的替代方案是基于模式的解决方案。这是由我的图书馆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
This formatter can also print durations of java.time
-API (however, the normalization features of that type are less powerful):
此格式化程序还可以打印java.time
-API 的持续时间(但是,该类型的规范化功能不那么强大):
System.out.println(f.format(java.time.Duration.ofMillis(123456))); // output: 0d 0h 2m 3.456s
The expectation of the OP that "123456 ms as a long would be printed as 4d1h3m5s" is calculated in an obviously wrong way. I assume sloppiness as reason. The same duration formatter defined above can also be used as parser. The following code shows that "4d1h3m5s" rather corresponds to 349385000 = 1000 * (4 * 86400 + 1 * 3600 + 3 * 60 + 5)
:
OP 的预期“123456 ms as a long will be print as 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
Another way is using the class net.time4j.PrettyTime
(which is also good for localized output and printing relative times like "yesterday", "next Sunday", "4 days ago" etc.):
另一种方法是使用类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
The text width controls if abbreviations are used or not. The list format can be controlled, too, by choosing the appropriate locale. For example, standard English uses the Oxform comma, while UK does not. The latest version v5.5 of Time4J supports more than 90 languages and uses translations based on the CLDR-repository (an industry standard).
文本宽度控制是否使用缩写。也可以通过选择适当的语言环境来控制列表格式。例如,标准英语使用 Oxform 逗号,而 UK 不使用。Time4J 的最新版本 v5.5 支持 90 多种语言,并使用基于 CLDR 存储库(行业标准)的翻译。
回答by lucasls
I've built a simple solution, using Java 8's Duration.toString()
and a bit of regex:
我使用 Java 8Duration.toString()
和一些正则表达式构建了一个简单的解决方案:
public static String humanReadableFormat(Duration duration) {
return duration.toString()
.substring(2)
.replaceAll("(\d[HMS])(?!$)", " ")
.toLowerCase();
}
The result will look like:
结果将如下所示:
- 5h
- 7h 15m
- 6h 50m 15s
- 2h 5s
- 0.1s
If you don't want spaces between, just remove replaceAll
.
如果您不想要空格,只需删除replaceAll
.
回答by Torsten
A Java 8version based on user678573's answer:
一个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()));
}
... since there is no PeriodFormatter in Java 8 and no methods like getHours, getMinutes, ...
...因为在 Java 8 中没有 PeriodFormatter 并且没有像 getHours、getMinutes、...
I'd be happy to see a better version for Java 8.
我很高兴看到 Java 8 的更好版本。
回答by erickdeoliveiraleal
Java 9+
爪哇 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
2 天 1 小时 6 米 4 秒