如何在java中格式化持续时间? (例如格式H:MM:SS)
我想使用像H:MM:SS这样的模式在几秒钟内格式化一个持续时间。 java中的当前实用程序devise为格式化一个时间,但不是一个持续时间。
如果您使用的是8之前的Java版本,则可以使用Joda Time和PeriodFormatter
。 如果你真的有一个持续时间(即一段时间,没有参考日历系统),那么你应该大部分Duration
使用Duration
– 然后你可以调用到toPeriod
(指定你想反映的任何PeriodType
是否25小时变成1天1小时等)来获得一个可以格式化的Period
。
如果您使用的是Java 8或更高版本:我通常会build议使用java.time.Duration
来表示持续时间。 然后你可以调用getSeconds()
或者类似的方法来获得一个整数,用于标准string格式化,如果你需要的话,尽pipe你应该注意持续时间为负的情况,因为你可能需要一个负号输出string。 所以像这样:
public static String formatDuration(Duration duration) { long seconds = duration.getSeconds(); long absSeconds = Math.abs(seconds); String positive = String.format( "%d:%02d:%02d", absSeconds / 3600, (absSeconds % 3600) / 60, absSeconds % 60); return seconds < 0 ? "-" + positive : positive; }
格式化这种方式是相当简单的,如果烦人的手动。 对于parsing它一般来说变得更加困难……当然,如果你愿意的话,你甚至可以用Java 8来使用Joda Time。
如果您不想在库中拖动,那么使用Formatter或相关的快捷键(例如, 给定整数秒s:
String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
我使用Apache常见的DurationFormatUtils,如下所示:
DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true));
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())));
这将成为Java 7中的新特性之一
JSR-310
这可能是一种怪异的方法,但是如果一个人java.time
用Java 8的java.time
来完成这个工作,那么这是一个很好的解决scheme:
import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.UnsupportedTemporalTypeException; public class TemporalDuration implements TemporalAccessor { private static final Temporal BASE_TEMPORAL = LocalDateTime.of(0, 1, 1, 0, 0); private final Duration duration; private final Temporal temporal; public TemporalDuration(Duration duration) { this.duration = duration; this.temporal = duration.addTo(BASE_TEMPORAL); } @Override public boolean isSupported(TemporalField field) { if(!temporal.isSupported(field)) return false; long value = temporal.getLong(field)-BASE_TEMPORAL.getLong(field); return value!=0l; } @Override public long getLong(TemporalField field) { if(!isSupported(field)) throw new UnsupportedTemporalTypeException(new StringBuilder().append(field.toString()).toString()); return temporal.getLong(field)-BASE_TEMPORAL.getLong(field); } public Duration getDuration() { return duration; } @Override public String toString() { return dtf.format(this); } private static final DateTimeFormatter dtf = new DateTimeFormatterBuilder() .optionalStart()//second .optionalStart()//minute .optionalStart()//hour .optionalStart()//day .optionalStart()//month .optionalStart()//year .appendValue(ChronoField.YEAR).appendLiteral(" Years ").optionalEnd() .appendValue(ChronoField.MONTH_OF_YEAR).appendLiteral(" Months ").optionalEnd() .appendValue(ChronoField.DAY_OF_MONTH).appendLiteral(" Days ").optionalEnd() .appendValue(ChronoField.HOUR_OF_DAY).appendLiteral(" Hours ").optionalEnd() .appendValue(ChronoField.MINUTE_OF_HOUR).appendLiteral(" Minutes ").optionalEnd() .appendValue(ChronoField.SECOND_OF_MINUTE).appendLiteral(" Seconds").optionalEnd() .toFormatter(); }
这是一个工作选项。
public static String showDuration(LocalTime otherTime){ DateTimeFormatter df = DateTimeFormatter.ISO_LOCAL_TIME; LocalTime now = LocalTime.now(); System.out.println("now: " + now); System.out.println("otherTime: " + otherTime); System.out.println("otherTime: " + otherTime.format(df)); Duration span = Duration.between(otherTime, now); LocalTime fTime = LocalTime.ofNanoOfDay(span.toNanos()); String output = fTime.format(df); System.out.println(output); return output; }
调用方法
System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));
产生类似于:
otherTime: 09:30 otherTime: 09:30:00 11:31:27.463 11:31:27.463
对于Java 9来说,这将更容易。 Duration
仍然不是可格式化的(我所知道的),但是添加了获取小时,分钟和秒的方法,这使得任务变得更直接:
Duration diff = // ...; String hms = String.format("%d:%02d:%02d", diff.toHoursPart(), diff.toMinutesPart(), diff.toSecondsPart());
这里是另一个示例如何格式化持续时间。 请注意,此示例显示正持续时间和正负持续时间。
import static java.time.temporal.ChronoUnit.DAYS; import static java.time.temporal.ChronoUnit.HOURS; import static java.time.temporal.ChronoUnit.MINUTES; import static java.time.temporal.ChronoUnit.SECONDS; import java.time.Duration; public class DurationSample { public static void main(String[] args) { //Let's say duration of 2days 3hours 12minutes and 46seconds Duration d = Duration.ZERO.plus(2, DAYS).plus(3, HOURS).plus(12, MINUTES).plus(46, SECONDS); //in case of negative duration if(d.isNegative()) d = d.negated(); //format DAYS HOURS MINUTES SECONDS System.out.printf("Total duration is %sdays %shrs %smin %ssec.\n", d.toDays(), d.toHours() % 24, d.toMinutes() % 60, d.getSeconds() % 60); //or format HOURS MINUTES SECONDS System.out.printf("Or total duration is %shrs %smin %sec.\n", d.toHours(), d.toMinutes() % 60, d.getSeconds() % 60); //or format MINUTES SECONDS System.out.printf("Or total duration is %smin %ssec.\n", d.toMinutes(), d.getSeconds() % 60); //or format SECONDS only System.out.printf("Or total duration is %ssec.\n", d.getSeconds()); } }
我的库Time4J提供了一个基于模式的解决scheme(类似于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
此代码演示了处理小时溢出和签名处理的function,另请参阅基于模式的duration-formatter的API。
下面的函数怎么样,返回+ H:MM:SS或+ H:MM:SS.sss
public static String formatInterval(final long interval, boolean millisecs ) { final long hr = TimeUnit.MILLISECONDS.toHours(interval); final long min = TimeUnit.MILLISECONDS.toMinutes(interval) %60; final long sec = TimeUnit.MILLISECONDS.toSeconds(interval) %60; final long ms = TimeUnit.MILLISECONDS.toMillis(interval) %1000; if( millisecs ) { return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms); } else { return String.format("%02d:%02d:%02d", hr, min, sec ); } }
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(); }