[java] 자바에서 지속 시간을 포맷하는 방법은 무엇입니까? (예 : H : MM : SS 형식)

H : MM : SS와 같은 패턴을 사용하여 지속 시간을 초 단위로 포맷하고 싶습니다. Java의 현재 유틸리티는 시간 형식이 아닌 시간 형식을 지정하도록 설계되었습니다.



답변

8 이전의 Java 버전을 사용하는 경우 Joda Time 및을 사용할 수 있습니다 PeriodFormatter. 실제로 지속 시간 (예 : 달력 시스템을 참조하지 않고 경과 된 시간)이 있다면 아마도 Duration대부분 을 사용해야 할 것입니다 -그런 다음 전화를 걸 수 있습니다 toPeriod( PeriodType25 시간이 될지 여부를 반영하려는 모든 것을 지정하십시오) 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;
}

이런 식으로 포맷 것은 합리적 귀찮게 매뉴얼 경우, 간단한. 위해 분석 은 물론, 원하는 경우가 더 열심히 문제 일반적으로이된다 … 당신은 여전히 심지어 자바 8 Joda 시간을 사용할 수 있습니다.


답변

라이브러리에서 드래그하지 않으려는 경우 Formatter 또는 관련 바로 가기와 같은 직접 작성을 사용하는 것이 간단합니다. 주어진 정수 초 수 s :

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


답변

Apache common의 DurationFormatUtils를 다음 과 같이 사용합니다.

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


답변

Java 9부터는 더 쉽습니다. A는 Duration여전히 형식을 지정할 수 없지만 시간, 분 및 초를 얻는 방법이 추가되어 작업이 다소 간단합니다.

    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


답변

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


답변

이것은 해킹 일 수도 있지만 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();

}


답변

다음은 지속 시간을 형식화하는 방법에 대한 샘플입니다. 이 샘플은 양수 기간과 음수 기간을 양수 기간으로 표시합니다.

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