我想用H:MM:SS这样的模式以秒为单位格式化持续时间。java中当前的实用程序设计用于格式化时间,而不是持续时间。


当前回答

从Java 9开始,这变得更容易了。Duration仍然是不可格式化的,但是添加了获取小时、分钟和秒的方法,这使得任务更简单:

    LocalDateTime start = LocalDateTime.of(2019, Month.JANUARY, 17, 15, 24, 12);
    LocalDateTime end = LocalDateTime.of(2019, Month.JANUARY, 18, 15, 43, 33);
    Duration diff = Duration.between(start, end);
    String hms = String.format("%d:%02d:%02d", 
                                diff.toHours(), 
                                diff.toMinutesPart(), 
                                diff.toSecondsPart());
    System.out.println(hms);

这个代码片段的输出是:

24:19:21

其他回答

有一个相当简单和优雅的方法,至少在24小时内:

DateTimeFormatter.ISO_LOCAL_TIME.format(value.addTo(LocalTime.of(0, 0)))

格式化程序需要一个时态对象来格式化,因此可以通过将持续时间添加到LocalTime为00:00(即午夜)来创建一个时态对象。这将为您提供一个LocalTime,表示从午夜到该时间的持续时间,然后很容易将其格式化为标准HH:mm:ss表示法。这样做的优点是不需要外部库,并且使用java。时间库做计算,而不是手动计算小时、分、秒。

我的库Time4J提供了一个基于模式的解决方案(类似于Apache DurationFormatUtils,但更灵活):

Duration<ClockUnit> duration =
    Duration.of(-573421, ClockUnit.SECONDS) // input in seconds only
    .with(Duration.STD_CLOCK_PERIOD); // performs normalization to h:mm:ss-structure
String fs = Duration.formatter(ClockUnit.class, "+##h:mm:ss").format(duration);
System.out.println(fs); // output => -159:17:01

这段代码演示了处理小时溢出和符号处理的功能,请参见基于模式的持续时间格式化程序的API。

下面是在Kotlin中将java.time.Duration转换为一个漂亮的字符串的一行代码:

duration.run {
   "%d:%02d:%02d.%03d".format(toHours(), toMinutesPart(), toSecondsPart(), toMillisPart())
}

示例输出: 120:56:03.004

long duration = 4 * 60 * 60 * 1000;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
log.info("Duration: " + sdf.format(new Date(duration - TimeZone.getDefault().getRawOffset())));
String duration(Temporal from, Temporal to) {
    final StringBuilder builder = new StringBuilder();
    for (ChronoUnit unit : new ChronoUnit[]{YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS}) {
        long amount = unit.between(from, to);
        if (amount == 0) {
            continue;
        }
        builder.append(' ')
                .append(amount)
                .append(' ')
                .append(unit.name().toLowerCase());
        from = from.plus(amount, unit);
    }
    return builder.toString().trim();
}