it-swarm.com.de

Wie formatiere ich eine Dauer in Java? (z. B. Format H: MM: SS)

Ich möchte eine Dauer in Sekunden mit einem Muster wie H: MM: SS formatieren. Die aktuellen Hilfsprogramme in Java sind zum Formatieren einer Zeit, nicht aber einer Dauer konzipiert.

126
kofte

Wenn Sie eine Java-Version vor 8 verwenden, können Sie Joda Time und PeriodFormatter verwenden. Wenn Sie wirklich eine Dauer haben (dh eine verstrichene Zeit ohne Bezug zu einem Kalendersystem), sollten Sie wahrscheinlich Duration verwenden. Sie können dann toPeriod aufrufen (wobei Sie angeben, welche PeriodType Sie angeben möchten, ob Sie angeben möchten 25 Stunden wird zu 1 Tag und 1 Stunde oder nicht usw.), um eine Period zu erhalten, die Sie formatieren können.

Wenn Sie Java 8 oder höher verwenden: Ich würde normalerweise die Verwendung von Java.time.Duration zur Darstellung der Dauer vorschlagen. Sie können dann getSeconds() oder Ähnliches aufrufen, um eine Ganzzahl für die Standard-String-Formatierung gemäß der Antwort von Bobince zu erhalten, wenn Sie müssen - obwohl Sie vorsichtig sein sollten, wenn die Dauer negativ ist, da Sie wahrscheinlich ein single negatives Vorzeichen in der Ausgabezeichenfolge. So etwas wie:

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;
}

Das Formatieren auf diese Weise ist vernünftig einfach, wenn es störend manuell ist. Für Parsing wird es im Allgemeinen schwieriger ... Sie können Joda Time auch mit Java 8 verwenden, wenn Sie möchten.

69
Jon Skeet

Wenn Sie nicht in Bibliotheken ziehen möchten, ist es einfach genug, einen Formatter oder eine verwandte Verknüpfung zu verwenden, z. gegebene Ganzzahl von Sekunden s:

  String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
174
bobince

Ich benutze Apache Common's DurationFormatUtils wie so: 

DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);
72
Gili Nachum
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())));
24
Mihai Vasilache

Mit Java 9 wird dies einfacher. Eine Duration ist immer noch nicht formatierbar (was ich weiß), aber es werden Methoden zum Abrufen der Stunden, Minuten und Sekunden hinzugefügt, wodurch die Aufgabe etwas einfacher wird:

        Duration diff = // ...;
        String hms = String.format("%d:%02d:%02d", 
                                   diff.toHoursPart(),
                                   diff.toMinutesPart(), 
                                   diff.toSecondsPart());
16
Ole V.V.

Dies kann ein bisschen hackig sein, aber es ist eine gute Lösung, wenn man dazu bereit ist, dies mit Hilfe von Java 8 zu 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();

}
7
patrick

Dies wird eine der neuen Funktionen in Java 7 sein

JSR-310

6
luke

Hier ein weiteres Beispiel zum Formatieren der Dauer ..__ Beachten Sie, dass dieses Beispiel sowohl positive als auch negative Dauer als positive Dauer anzeigt.

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());
    }
}
6
Pavel_H

Dies ist eine funktionierende 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;
}

Rufen Sie die Methode mit auf

System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));

Produziert so etwas wie:

otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463
3
sbclint

Es gibt einen relativ einfachen und (IMO) eleganten Ansatz, zumindest für eine Dauer von weniger als 24 Stunden:

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

Formatierer benötigen ein temporäres Objekt zum Formatieren, sodass Sie eines erstellen können, indem Sie die Dauer zu einer LocalTime von 00:00 (d. H. Mitternacht) hinzufügen. Auf diese Weise erhalten Sie eine LocalTime, die die Dauer von Mitternacht bis zu dieser Zeit darstellt. Diese kann dann einfach in der Standardnotation HH: mm: ss formatiert werden. Dies hat den Vorteil, dass keine externe Bibliothek erforderlich ist und die Java.time-Bibliothek für die Berechnung verwendet wird, anstatt die Stunden, Minuten und Sekunden manuell zu berechnen.

2
ctg

Wie wäre es mit der folgenden Funktion, die entweder + H: MM: SS Oder + H: MM: SS.sss zurückgibt

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 );
    }
}
2
mksteve
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();
}
1
Bax

Diese Antwort verwendet nur Duration-Methoden und funktioniert mit 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,");
}
1
lauhub

Meine Bibliothek Time4J bietet eine musterbasierte Lösung (ähnlich wie Apache DurationFormatUtils, aber flexibler):

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

Dieser Code demonstriert die Fähigkeiten zum Umgang mit Stundenüberlauf und zur Zeichenverarbeitung, siehe auch die API für Dauerformatierer basierend auf Muster .

0
Meno Hochschild

in Scala ist keine Bibliothek erforderlich:

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("")
0
YourBestBet

In Scala die YourBestBet-Lösung aufbauen, aber vereinfacht

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
0
dpoetzsch