Я хотел бы отформатировать продолжительность в секундах, используя шаблон, такой как H: MM: SS. Текущие утилиты в java предназначены для форматирования времени, но не продолжительности.
Как отформатировать продолжительность в java? (например, формат H: MM: SS)
Ответ 1
Если вы используете версию Java до 8... вы можете использовать Joda Time и PeriodFormatter. Если у вас действительно есть продолжительность (т.е. Истекшее количество времени, без ссылки на систему календаря), то вы, вероятно, должны использовать Duration по большей части - вы можете вызвать toPeriod (указывая все PeriodType вы хотите определить, будет ли 25 часов 1 день и 1 час или нет, и т.д.), чтобы получить Period, который вы можете отформатировать.
Если вы используете 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;
}
Форматирование этого способа достаточно прост, если досадно ручное. Для синтаксического анализа это становится более сложным делом в целом... Вы все равно можете использовать Joda Time даже с Java 8, если хотите, конечно.
Ответ 2
Если вы не хотите перетаскивать библиотеки, достаточно просто сделать сами, используя Formatter или связанный ярлык, например. заданное целое число секунд s:
  String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
		Ответ 3
Я использую Apache общий DurationFormatUtils примерно так:
DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);
		Ответ 4
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())));
		Ответ 5
Это будет проще с Java 9. A Duration по-прежнему не является готовым (что я знаю), но добавляются методы для получения часов, минут и секунд, что делает задачу несколько более простой:
        Duration diff = // ...;
        String hms = String.format("%d:%02d:%02d", 
                                   diff.toHoursPart(),
                                   diff.toMinutesPart(), 
                                   diff.toSecondsPart());
		Ответ 6
 Это может быть хаккой, но это хорошее решение, если вы java.time выполнить это с помощью 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();
}
		Ответ 7
Это будет одна из новых функций в java 7
Ответ 8
Вот еще один пример того, как форматировать длительность. Обратите внимание, что этот образец показывает как положительную, так и отрицательную длительность как положительную.
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 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());
    }
}
		Ответ 9
Это рабочая опция.
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
		Ответ 10
Как насчет следующей функции, которая возвращает либо + Н: ММ: СС или + Н: ММ: СС.ссс
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 );
    }
}
		Ответ 11
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();
}
		Ответ 12
 Этот ответ использует только методы 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,");
}
		Ответ 13
Моя библиотека 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
Этот код демонстрирует возможности обработки переполнения часов и обработки значков, см. также API-формулу long-formatter на основе шаблона.
Ответ 14
В 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
		Ответ 15
Существует довольно простой и (ИМО) элегантный подход, по крайней мере, для продолжительности менее 24 часов:
 DateTimeFormatter.ISO_LOCAL_TIME.format(value.addTo(LocalTime.of(0, 0)))
Для форматирования нужен временный объект, так что вы можете создать его, добавив продолжительность к LocalTime 00:00 (т.е. полночь). Это даст вам LocalTime, представляющий продолжительность от полуночи до этого времени, которую затем легко отформатировать в стандартной записи HH: mm: ss. Преимущество этого состоит в том, что не требуется внешняя библиотека, и для вычисления используется библиотека java.time, а не часы, минуты и секунды вручную.
Ответ 16
Я не видел этого, поэтому я решил добавить:
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));
 Это работает только в течение 24 часов, но это то, что я обычно хочу на время.
Ответ 17
в 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("")