Frage

Ich möchte eine Dauer in Sekunden zu formatieren, ein Muster wie H mit: MM: SS. Die aktuellen Dienstprogramme in Java sind so konzipiert, um eine Zeit zu formatieren, aber nicht mit einer Dauer.

War es hilfreich?

Lösung

Wenn Sie eine Version von Java vor 8 mit ... können Sie Joda Zeit verwenden und PeriodFormatter . Wenn Sie wirklich eine Dauer (dh einer verstrichenen Zeitspanne ohne Bezugnahme auf ein System Kalender) haben, dann sollten Sie wahrscheinlich zum größten Teil mit Duration - Sie dann toPeriod nennen kann (unter Angabe, was auch immer PeriodType Sie reflektieren wollen, ob 25 Stunden wird 1 Tag und 1 Stunde oder nicht, usw.) eine Period zu erhalten, die Sie formatieren können.

Wenn Sie mit Java 8 oder höher: ich normalerweise würde vorschlagen java.time.Duration mit der Dauer darzustellen. Sie können dann rufen getSeconds() oder dergleichen eine ganze Zahl für Standard-Zeichenfolge als pro bobince Antwort Formatierung zu erhalten, wenn Sie benötigen - auch wenn Sie die Situation vorsichtig sein sollte, wo die Dauer negativ ist, wie Sie wahrscheinlich ein Einzel wollen negatives Vorzeichen in der Ausgabe-String. 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;
}

Formatieren auf diese Weise ist vernünftig einfach, wenn annoyingly Handbuch. Für Parsen es eine schwierige Materie im Allgemeinen wird ... Sie noch Joda Zeit auch mit Java 8, wenn Sie wollen verwenden könnte, natürlich.

Andere Tipps

Wenn Sie nicht in Bibliotheken ziehen wollen, dann ist es einfach genug, um sich selbst zu tun, um eine Formatter verwenden oder damit verbundene Verknüpfung zB. gegebene ganze Zahl von Sekunden s:

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

verwende ich Apache gemeinsam die DurationFormatUtils wie folgt:

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())));

Dies wird einfacher mit Java 9. Duration noch nicht formatierbare ist (was ich kenne), aber Methoden, um die Stunden, Minuten und Sekunden hinzugefügt werden, die die Aufgabe etwas einfacher macht:

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

Dies könnte Art von Hacky sein, aber es ist eine gute Lösung, wenn man auf das Erreichen dieses mit Hilfe von Java 8 des java.time gebogen ist:

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();

}

Das wird eine der neuen Funktionen in Java 7

sein

JSR-310

Hier ist eine weitere Probe, wie Dauer zu formatieren. Beachten Sie, dass diese Probe zeigt sowohl positive als auch negative Duration als positive Dauer.

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

Dies ist eine Arbeits 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

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

Erzeugt etwas wie:

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

Wie über die folgende Funktion, die entweder zurück + H: MM: SS oder + H: MM: SS.mss

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

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

Es ist ein ziemlich einfacher und (IMO) eleganter Ansatz, zumindest für eine Dauer von weniger als 24 Stunden:

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

Formatter braucht eine zeitlichen Objekt-Format, so dass Sie ein, indem Sie die Dauer zu einer Localtime von 00.00 (d Mitternacht) zu schaffen. Dies gibt Ihnen eine Localtime die Dauer von Mitternacht bis zu diesem Zeitpunkt darstellt, die dann leicht in Standard-HH zu formatieren: mm: ss-Notation. Dies hat den Vorteil, nicht um eine externe Bibliothek benötigt und verwendet die java.time Bibliothek die Berechnung zu tun, anstatt manuell die Stunden, Minuten und Sekunden berechnet wird.

Meine Bibliothek Time4J bietet eine musterbasierte Lösung (ähnlich 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 zeigt die Funktionen Stunde Überlauf zu handhaben und melden Handhabung siehe auch die API von Dauer-Formatierer basierend auf Muster .

In Scala, auf YourBestBet Lösung Aufbau 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

in scala, keine Bibliothek benötigt:

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

Ich habe nicht gesehen, das man so dachte ich, dass ich es hinzufügen würde:

Date started=new Date();
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
task
long duration=new Date().getTime()-started.getTime();
System.out.println(format.format(new Date(duration));

Es funktioniert nur für 24 Stunden, aber das ist, was ich in der Regel für die Dauer will.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top