如何在java中格式化持续时间?(例如格式 H:MM:SS)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/266825/
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 to format a duration in java? (e.g format H:MM:SS)
提问by
I'd like to format a duration in seconds using a pattern like H:MM:SS. The current utilities in java are designed to format a time but not a duration.
我想使用像 H:MM:SS 这样的模式以秒为单位格式化持续时间。java中的当前实用程序旨在格式化时间而不是持续时间。
采纳答案by Jon Skeet
If you're using a version of Java prior to 8... you can use Joda Timeand PeriodFormatter
. If you've really got a duration (i.e. an elapsed amount of time, with no reference to a calendar system) then you should probably be using Duration
for the most part - you can then call toPeriod
(specifying whatever PeriodType
you want to reflect whether 25 hours becomes 1 day and 1 hour or not, etc) to get a Period
which you can format.
如果您使用的是 8 之前的 Java 版本...您可以使用Joda Time和PeriodFormatter
. 如果你真的有一个持续时间(即经过的时间量,没有参考日历系统)那么你可能应该使用Duration
大部分 - 然后你可以打电话toPeriod
(指定PeriodType
你想要反映的任何内容,以反映 25 小时是否变成1 天 1 小时与否等)以获得Period
您可以格式化的文件。
If you're using Java 8 or later: I'd normally suggest using java.time.Duration
to represent the duration. You can then call getSeconds()
or the like to obtain an integer for standard string formatting as per bobince's answer if you need to - although you should be careful of the situation where the duration is negative, as you probably want a singlenegative sign in the output string. So something like:
如果您使用的是 Java 8 或更高版本:我通常建议使用java.time.Duration
来表示持续时间。然后,getSeconds()
如果需要,您可以根据 bobince 的回答调用或类似方法获取标准字符串格式的整数 - 尽管您应该注意持续时间为负的情况,因为您可能希望在输出字符串中使用单个负号. 所以像:
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;
}
Formatting this way is reasonablysimple, if annoyingly manual. For parsingit becomes a harder matter in general... You could still use Joda Time even with Java 8 if you want to, of course.
以这种方式格式化相当简单,如果手动操作很烦人。对于解析它变成一般较硬的事......如果你愿意,你当然可以仍然使用约达时间甚至与Java 8。
回答by bobince
If you don't want to drag in libraries, it's simple enough to do yourself using a Formatter, or related shortcut eg. given integer number of seconds s:
如果您不想在库中拖动,那么使用格式化程序或相关快捷方式(例如)很简单。给定整数秒数:
String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
回答by Mihai Vasilache
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())));
回答by Gili Nachum
I use Apache common's DurationFormatUtilslike so:
我像这样使用 Apache common 的DurationFormatUtils:
DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);
回答by sbclint
This is a working option.
这是一个工作选项。
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;
}
Call the method with
调用方法
System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));
Produces something like:
产生类似的东西:
otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463
回答by patrick
This might be kind of hacky, but it is a good solution if one is bent on accomplishing this using Java 8's java.time
:
这可能有点 hacky,但如果人们一心想使用 Java 8 来实现这一点,这是一个很好的解决方案java.time
:
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();
}
回答by Pavel_H
Here is one more sample how to format duration. Note that this sample shows both positive and negative duration as positive duration.
这是如何格式化持续时间的另一个示例。请注意,此示例将正持续时间和负持续时间都显示为正持续时间。
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());
}
}
回答by Meno Hochschild
My library Time4Joffers a pattern-based solution (similar to Apache DurationFormatUtils
, but more flexible):
我的库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
This code demonstrates the capabilities to handle hour overflow and sign handling, see also the API of duration-formatter based on pattern.
此代码演示了处理小时溢出和符号处理的功能,另请参阅基于模式的持续时间格式化程序的 API 。
回答by Bax
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();
}
回答by Ole V.V.
This is easier since Java 9. A Duration
still isn't formattable, but methods for getting the hours, minutes and seconds are added, which makes the task somewhat more straightforward:
从 Java 9 开始,这更容易了。 ADuration
仍然不是可格式化的,但添加了获取小时、分钟和秒的方法,这使任务更加简单:
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);
The output from this snippet is:
此代码段的输出是:
24:19:21
24:19:21