如何在java中格式化持续时间?(例如格式H:MM:SS)

如何在java中格式化持续时间?(例如格式H:MM:SS),java,date-formatting,duration,android,date,elapsedtime,Java,Date Formatting,Duration,Android,Date,Elapsedtime,我想使用H:MM:SS这样的模式来格式化以秒为单位的持续时间。java中当前的实用程序设计用于格式化时间,而不是持续时间。如果您使用的是8之前版本的java。。。您可以使用和。如果您确实有一个持续时间(即,经过的时间量,不参考日历系统),那么您可能应该在大多数情况下使用duration——然后您可以调用toPeriod(指定要反映25小时是否变为1天1小时的PeriodType,等等)获取可以格式化的期间 import static java.time.temporal.ChronoUnit.D

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

如果您使用的是8之前版本的java。。。您可以使用和。如果您确实有一个持续时间(即,经过的时间量,不参考日历系统),那么您可能应该在大多数情况下使用
duration
——然后您可以调用
toPeriod
(指定要反映25小时是否变为1天1小时的
PeriodType
,等等)获取可以格式化的
期间

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());
    }
}
如果您使用的是Java8或更高版本:我通常建议使用
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;
}
otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463
公共静态字符串格式持续时间(持续时间){
long seconds=duration.getSeconds();
long abs seconds=Math.abs(秒);
字符串正=String.format(
“%d:%02d:%02d”,
秒/3600,
(秒数%3600)/60,
abs(60%);
返回秒数<0?-“+正:正;
}

这种方式的格式化相当简单,尽管手工操作很麻烦。一般来说,解析它会变得更困难。。。当然,如果愿意,即使使用Java 8,您也可以使用Joda Time。

如果您不想在库中拖拽,那么使用格式化程序或相关快捷方式(例如给定整数秒数s)就足够简单了:

  String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
我使用Apache common,如下所示:

DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);

这是一个可行的选择

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)));
产生类似于:

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;
}
otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463

这可能有点老套,但如果你决心使用Java8的
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();

}

下面是如何设置持续时间格式的另一个示例。 请注意,此示例将正持续时间和负持续时间显示为正持续时间

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());
    }
}
My library提供了一个基于模式的解决方案(类似于Apache DurationFormatUtils,但更灵活):

持续时间=
持续时间(-573421,ClockUnit.SECONDS)//仅以秒为单位输入
.具有(持续时间、标准时钟周期);//对h:mm:ss结构执行规范化
字符串fs=Duration.formatter(ClockUnit.class,“+#h:mm:ss”).format(Duration);
System.out.println(fs);//输出=>-159:17:01

这段代码演示了处理小时溢出和签名处理的功能,另请参阅duration formatter的API。

这比Java 9更容易。持续时间仍然不是可格式化的,但是增加了获取小时、分钟和秒的方法,这使任务更简单:

    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


下面的函数如何,它返回 +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 );
    }
}

在scala中,不需要库:

def prettyDuration(str:List[String],seconds:Long):List[String]={
  seconds match {
    case t if t < 60 => str:::List(s"${t} seconds")
    case t if (t >= 60 && t< 3600 ) => List(s"${t / 60} minutes"):::prettyDuration(str, t%60)
    case t if (t >= 3600 && t< 3600*24 ) => List(s"${t / 3600} hours"):::prettyDuration(str, t%3600)
    case t if (t>= 3600*24 ) => List(s"${t / (3600*24)} days"):::prettyDuration(str, t%(3600*24))
  }
}
val dur = prettyDuration(List.empty[String], 12345).mkString("")
def prettyDuration(str:List[String],seconds:Long):List[String]={
秒匹配{
案例t如果t<60=>str:::List(s“${t}秒”)
案例t如果(t>=60&&t<3600)=>列表(s“${t/60}分钟”)::prettyDuration(str,t%60)
案例t如果(t>=3600&&t<3600*24)=>列表(s“${t/3600}小时”)::prettyDuration(str,t%3600)
案例t如果(t>=3600*24)=>列表(s“${t/(3600*24)}天”)::prettyDuration(str,t%(3600*24))
}
}
val dur=prettyDuration(List.empty[String],12345).mkString(“”)

此答案仅使用
Duration
方法,适用于Java 8:

public static String format(Duration d) {
    long days = d.toDays();
    d = d.minusDays(days);
    long hours = d.toHours();
    d = d.minusHours(hours);
    long minutes = d.toMinutes();
    d = d.minusMinutes(minutes);
    long seconds = d.getSeconds() ;
    return 
            (days ==  0?"":days+" jours,")+ 
            (hours == 0?"":hours+" heures,")+ 
            (minutes ==  0?"":minutes+" minutes,")+ 
            (seconds == 0?"":seconds+" secondes,");
}

在Scala中,以YourBestBet的解决方案为基础,但简化了:

def prettyDuration(seconds: Long): List[String] = seconds match {
  case t if t < 60      => List(s"${t} seconds")
  case t if t < 3600    => s"${t / 60} minutes" :: prettyDuration(t % 60)
  case t if t < 3600*24 => s"${t / 3600} hours" :: prettyDuration(t % 3600)
  case t                => s"${t / (3600*24)} days" :: prettyDuration(t % (3600*24))
}

val dur = prettyDuration(12345).mkString(", ") // => 3 hours, 25 minutes, 45 seconds
def prettyDuration(秒:长):列表[字符串]=秒匹配{
如果t<60=>列表(s“${t}秒”),则为案例t
案例t如果t<3600=>s“${t/60}分钟”::prettyDuration(t%60)
案例t如果t<3600*24=>s“${t/3600}小时”::prettyDuration(t%3600)
案例t=>s“${t/(3600*24)}天”::prettyDuration(t%(3600*24))
}
val dur=prettyDuration(12345).mkString(“,”/>3小时25分45秒

有一种相当简单且(IMO)优雅的方法,至少在不到24小时的时间内:

DateTimeFormatter.ISO\u LOCAL\u TIME.format(value.addTo(LocalTime.of(0,0)))

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

在scala中(我看到了一些其他尝试,但没有印象):

def formatDuration(duration:duration):字符串={
导入持续时间。\ uu//获取对所有成员的访问权;)
f“$toDaysPart$toHoursPart%02d:$toMinutesPart%02d:$toSecondsPart%02d:$toMillisPart%03d”
}
看起来很可怕是吗?这就是为什么我们使用IDE来编写这些东西,所以方法调用(
$toHoursPart
等)是不同的颜色

f“…”
是一个
printf
/
String.format
样式的字符串插值器(它允许
$
代码注入工作) 给定
1 14:06:32.583
的输出,
f
插值字符串将等效于
string.format(“1%02d:%02d:%02d.%03d”,14,6,32,583)
使用此函数

private static String strDuration(long duration) {
    int ms, s, m, h, d;
    double dec;
    double time = duration * 1.0;

    time = (time / 1000.0);
    dec = time % 1;
    time = time - dec;
    ms = (int)(dec * 1000);

    time = (time / 60.0);
    dec = time % 1;
    time = time - dec;
    s = (int)(dec * 60);

    time = (time / 60.0);
    dec = time % 1;
    time = time - dec;
    m = (int)(dec * 60);

    time = (time / 24.0);
    dec = time % 1;
    time = time - dec;
    h = (int)(dec * 24);
    
    d = (int)time;
    
    return (String.format("%d d - %02d:%02d:%02d.%03d", d, h, m, s, ms));
}

我不确定你想要什么,但是检查一下这个Android助手类

import android.text.format.DateUtils
例如:
DateUtils.formatElapsedTime()

您可以使用Java-8A的模型和引入的
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Month;

public class Main {
    public static void main(String[] args) {
        LocalDateTime startDateTime = LocalDateTime.of(2020, Month.DECEMBER, 10, 15, 20, 25);
        LocalDateTime endDateTime = LocalDateTime.of(2020, Month.DECEMBER, 10, 18, 24, 30);

        Duration duration = Duration.between(startDateTime, endDateTime);
        // Default format
        System.out.println(duration);

        // Custom format
        // ####################################Java-8####################################
        String formattedElapsedTime = String.format("%02d:%02d:%02d", duration.toHours() % 24,
                duration.toMinutes() % 60, duration.toSeconds() % 60);
        System.out.println(formattedElapsedTime);
        // ##############################################################################

        // ####################################Java-9####################################
        formattedElapsedTime = String.format("%02d:%02d:%02d", duration.toHoursPart(), duration.toMinutesPart(),
                duration.toSecondsPart());
        System.out.println(formattedElapsedTime);
        // ##############################################################################
    }
}
PT3H4M5S
03:04:05
03:04:05
public String formatDuration(Duration duration) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("h:mm.SSS");
    return LocalTime.ofNanoOfDay(duration.toNanos()).format(formatter);
}
Duration.ofMinutes(110L).toMinutesPart() == 50