web-dev-qa-db-ja.com

Javaでミリ秒を「X分、X秒」に変換する方法

ユーザーが自分のプログラムで何かを始めたときのSystem.currentTimeMillis()を使って時間を記録したいのです。彼が終わったら、私はstart変数から現在のSystem.currentTimeMillis()を引くでしょう、そして私は彼らに "XX時間、XX分、XX秒"あるいは "XX分、XX秒"のような人間が読めるフォーマットを使って経過時間を見せたい誰かが1時間かかるとは思われないからです。

これを行うための最良の方法は何ですか?

529
Click Upvote

Java.util.concurrent.TimeUnit クラスを使用してください。

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toMinutes(millis),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);

注:TimeUnitはJava 1.5仕様の一部ですが、toMinutesはJava 1.6の時点で追加されました。

値0〜9に先行ゼロを追加するには、次のようにします。

String.format("%02d min, %02d sec", 
    TimeUnit.MILLISECONDS.toMinutes(millis),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);

TimeUnitまたはtoMinutesがサポートされていない場合(APIバージョン9より前のAndroidなど)、次の式を使用してください。

int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours   = (int) ((milliseconds / (1000*60*60)) % 24);
//etc...
1141
siddhadev

@ siddhadevの答えに基づいて、ミリ秒をフォーマットされた文字列に変換する関数を書きました。

   /**
     * Convert a millisecond duration to a string format
     * 
     * @param millis A duration to convert to a string form
     * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
     */
    public static String getDurationBreakdown(long millis) {
        if(millis < 0) {
            throw new IllegalArgumentException("Duration must be greater than zero!");
        }

        long days = TimeUnit.MILLISECONDS.toDays(millis);
        millis -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        millis -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
        millis -= TimeUnit.MINUTES.toMillis(minutes);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);

        StringBuilder sb = new StringBuilder(64);
        sb.append(days);
        sb.append(" Days ");
        sb.append(hours);
        sb.append(" Hours ");
        sb.append(minutes);
        sb.append(" Minutes ");
        sb.append(seconds);
        sb.append(" Seconds");

        return(sb.toString());
    }
118
long time = 1536259;

return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time));

プリント:

25:36:259

66
Damien

うーん... 1秒に何ミリ秒あるのでしょうか。そしてすぐに?分割はそれほど難しくありません。

int seconds = (int) ((milliseconds / 1000) % 60);
int minutes = (int) ((milliseconds / 1000) / 60);

何時間も、何時間も、何日も、何週間も、何ヶ月も、何年も、そのように続けます。

35
Bombe

そのためだけに余分な依存関係を引き込むことはしません(結局のところ、分割はそれほど難しいことではありません)が、とにかくCommons Langを使用している場合は、 DurationFormatUtils があります。

26
Thilo

Java 8で Java.timeパッケージ を使用する:

Instant start = Instant.now();
Thread.sleep(63553);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

出力は ISO 8601継続時間フォーマットPT1M3.553S(1分3.553秒)です。

26

手で分割するか、 SimpleDateFormat API を使用します。

long start = System.currentTimeMillis();
// do your work...
long elapsed = System.currentTimeMillis() - start;
DateFormat df = new SimpleDateFormat("HH 'hours', mm 'mins,' ss 'seconds'");
df.setTimeZone(TimeZone.getTimeZone("GMT+0"));
System.out.println(df.format(new Date(elapsed)));

Bombeで編集:これは、このアプローチがより短い期間(つまり1日未満)しか有効でないことを示しています。

25
cadrian

HH:mm:ssのようにフォーマットしたい場合は、さらに情報を追加してください

0 <= HH <=無限大

0 <= mm <60

0 <= ss <60

これを使って:

int h = (int) ((startTimeInMillis / 1000) / 3600);
int m = (int) (((startTimeInMillis / 1000) / 60) % 60);
int s = (int) ((startTimeInMillis / 1000) % 60);

私は今この問題を抱えていて、これを考え出しました

21
fredcrs

私は最善の方法だと思います:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toSeconds(length)/60,
    TimeUnit.MILLISECONDS.toSeconds(length) % 60 );
12
Xtera

最短の解決策:

これはおそらくタイムゾーンを扱う最短のものでしょう。

System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());

例えば、どの出力:

00:18:32

説明:

%tTは、24時間形式で%tH:%tM:%tSとしてフォーマットされた時間です。

%tTは入力としてlongも受け入れるので、Dateを作成する必要はありません。 printf()は単にミリ秒で指定された時間を表示しますが、現在のタイムゾーンでは、現在のタイムゾーンの生のオフセットを引いて0ミリ秒が現在のタイムゾーンのタイムオフセット値ではなく0時間になるようにします。

Note#1: Stringとして結果が必要な場合は、次のようになります。

String t = String.format("%tT", millis-TimeZone.getDefault().getRawOffset());

注2: millisが1日未満の場合にのみ正しい結果が得られます。これは、日の部分が出力に含まれていないためです。

11
icza

ジョダタイム

Joda-Time :を使う

DateTime startTime = new DateTime();

// do something

DateTime endTime = new DateTime();
Duration duration = new Duration(startTime, endTime);
Period period = duration.toPeriod().normalizedStandard(PeriodType.time());
System.out.println(PeriodFormat.getDefault().print(period));
7
dogbane

@ brent-nashの寄与を再考すると、減算の代わりにモジュラス関数を使用し、結果の文字列にString.formatメソッドを使用することができます。

  /**
   * Convert a millisecond duration to a string format
   * 
   * @param millis A duration to convert to a string form
   * @return A string of the form "X Days Y Hours Z Minutes A Seconds B Milliseconds".
   */
   public static String getDurationBreakdown(long millis) {
       if (millis < 0) {
          throw new IllegalArgumentException("Duration must be greater than zero!");
       }

       long days = TimeUnit.MILLISECONDS.toDays(millis);
       long hours = TimeUnit.MILLISECONDS.toHours(millis) % 24;
       long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60;
       long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;
       long milliseconds = millis % 1000;

       return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds",
                            days, hours, minutes, seconds, milliseconds);
   }
6
Jose Tepedino

私の簡単な計算:

String millisecToTime(int millisec) {
    int sec = millisec/1000;
    int second = sec % 60;
    int minute = sec / 60;
    if (minute >= 60) {
        int hour = minute / 60;
        minute %= 60;
        return hour + ":" + (minute < 10 ? "0" + minute : minute) + ":" + (second < 10 ? "0" + second : second);
    }
    return minute + ":" + (second < 10 ? "0" + second : second);
}

ハッピーコーディング:)

5

aPI 9以下のAndroid用

(String.format("%d hr %d min, %d sec", millis/(1000*60*60), (millis%(1000*60*60))/(1000*60), ((millis%(1000*60*60))%(1000*60))/1000)) 
5
Pradeep

1時間もかからない小さな時間には、

long millis = ...

System.out.printf("%1$TM:%1$TS", millis);
// or
String str = String.format("%1$TM:%1$TS", millis);

より長い間隔のために:

private static final long HOUR = TimeUnit.HOURS.toMillis(1);
...
if (millis < HOUR) {
    System.out.printf("%1$TM:%1$TS%n", millis);
} else {
    System.out.printf("%d:%2$TM:%2$TS%n", millis / HOUR, millis % HOUR);
}
4
    long startTime = System.currentTimeMillis();
    // do your work...
    long endTime=System.currentTimeMillis();
    long diff=endTime-startTime;       
    long hours=TimeUnit.MILLISECONDS.toHours(diff);
    diff=diff-(hours*60*60*1000);
    long min=TimeUnit.MILLISECONDS.toMinutes(diff);
    diff=diff-(min*60*1000);
    long seconds=TimeUnit.MILLISECONDS.toSeconds(diff);
    //hour, min and seconds variables contains the time elapsed on your work
3
Fathah Rehman P

これはJava 9のほうが簡単です。

    Duration elapsedTime = Duration.ofMillis(millisDiff );
    String humanReadableElapsedTime = String.format(
            "%d hours, %d mins, %d seconds",
            elapsedTime.toHours(),
            elapsedTime.toMinutesPart(),
            elapsedTime.toSecondsPart());

これは0 hours, 39 mins, 9 secondsのような文字列を生成します。

フォーマットする前に整数に丸めたい場合は、

    elapsedTime = elapsedTime.plusMillis(500).truncatedTo(ChronoUnit.SECONDS);

時間が0の場合、時間を除外するには

    long hours = elapsedTime.toHours();
    String humanReadableElapsedTime;
    if (hours == 0) {
        humanReadableElapsedTime = String.format(
                "%d mins, %d seconds",
                elapsedTime.toMinutesPart(),
                elapsedTime.toSecondsPart());

    } else {
        humanReadableElapsedTime = String.format(
                "%d hours, %d mins, %d seconds",
                hours,
                elapsedTime.toMinutesPart(),
                elapsedTime.toSecondsPart());
    }

これで、例えば39 mins, 9 secondsを手に入れることができます。

分と秒を先行ゼロで印刷して常に2桁にするには、関連するフォーマット指定子に02を挿入するだけです。

    String humanReadableElapsedTime = String.format(
            "%d hours, %02d mins, %02d seconds",
            elapsedTime.toHours(),
            elapsedTime.toMinutesPart(),
            elapsedTime.toSecondsPart());

これで、例えば0 hours, 39 mins, 09 secondsを手に入れることができます。

2
Ole V.V.

これがBrent Nashの回答に基づいた回答です。

public static String getDurationBreakdown(long millis)
{
    String[] units = {" Days ", " Hours ", " Minutes ", " Seconds "};
    Long[] values = new Long[units.length];
    if(millis < 0)
    {
        throw new IllegalArgumentException("Duration must be greater than zero!");
    }

    values[0] = TimeUnit.MILLISECONDS.toDays(millis);
    millis -= TimeUnit.DAYS.toMillis(values[0]);
    values[1] = TimeUnit.MILLISECONDS.toHours(millis);
    millis -= TimeUnit.HOURS.toMillis(values[1]);
    values[2] = TimeUnit.MILLISECONDS.toMinutes(millis);
    millis -= TimeUnit.MINUTES.toMillis(values[2]);
    values[3] = TimeUnit.MILLISECONDS.toSeconds(millis);

    StringBuilder sb = new StringBuilder(64);
    boolean startPrinting = false;
    for(int i = 0; i < units.length; i++){
        if( !startPrinting && values[i] != 0)
            startPrinting = true;
        if(startPrinting){
            sb.append(values[i]);
            sb.append(units[i]);
        }
    }

    return(sb.toString());
}
2
Reda Bouaichi

正しい文字列( "1時間、3秒"、 "3分"で、 "0時間、0分、3秒"ではない)については、私はこのコードを書く:

int seconds = (int)(millis / 1000) % 60 ;
int minutes = (int)((millis / (1000*60)) % 60);
int hours = (int)((millis / (1000*60*60)) % 24);
int days = (int)((millis / (1000*60*60*24)) % 365);
int years = (int)(millis / 1000*60*60*24*365);

ArrayList<String> timeArray = new ArrayList<String>();

if(years > 0)   
    timeArray.add(String.valueOf(years)   + "y");

if(days > 0)    
    timeArray.add(String.valueOf(days) + "d");

if(hours>0)   
    timeArray.add(String.valueOf(hours) + "h");

if(minutes>0) 
    timeArray.add(String.valueOf(minutes) + "min");

if(seconds>0) 
    timeArray.add(String.valueOf(seconds) + "sec");

String time = "";
for (int i = 0; i < timeArray.size(); i++) 
{
    time = time + timeArray.get(i);
    if (i != timeArray.size() - 1)
        time = time + ", ";
}

if (time == "")
  time = "0 sec";
1
John

これについては別の 回答 で説明しましたが、次のようにすることもできます。

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {
    long diffInMillies = date2.getTime() - date1.getTime();
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;
    for ( TimeUnit unit : units ) {
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;
        result.put(unit,diff);
    }
    return result;
}

出力はMap:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}のようなもので、単位は順序付けされています。

ターゲットロケールに従ってこのデータを国際化する方法を判断するのはあなた次第です。

1

Java.util.concurrent.TimeUnitを使用して、この単純なメソッドを使用してください。

private static long timeDiff(Date date, Date date2, TimeUnit unit) {
    long milliDiff=date2.getTime()-date.getTime();
    long unitDiff = unit.convert(milliDiff, TimeUnit.MILLISECONDS);
    return unitDiff; 
}

例えば:

SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm:ss");  
Date firstDate = sdf.parse("06/24/2017 04:30:00");
Date secondDate = sdf.parse("07/24/2017 05:00:15");
Date thirdDate = sdf.parse("06/24/2017 06:00:15");

System.out.println("days difference: "+timeDiff(firstDate,secondDate,TimeUnit.DAYS));
System.out.println("hours difference: "+timeDiff(firstDate,thirdDate,TimeUnit.HOURS));
System.out.println("minutes difference: "+timeDiff(firstDate,thirdDate,TimeUnit.MINUTES));
System.out.println("seconds difference: "+timeDiff(firstDate,thirdDate,TimeUnit.SECONDS));

時差が1時間未満になることがわかっている場合は、次のコードを使用できます。

    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();

    c2.add(Calendar.MINUTE, 51);

    long diff = c2.getTimeInMillis() - c1.getTimeInMillis();

    c2.set(Calendar.MINUTE, 0);
    c2.set(Calendar.HOUR, 0);
    c2.set(Calendar.SECOND, 0);

    DateFormat df = new SimpleDateFormat("mm:ss");
    long diff1 = c2.getTimeInMillis() + diff;
    System.out.println(df.format(new Date(diff1)));

51:00

1
Gourav Singla

この答えは上記のいくつかの答えに似ています。ただし、他の回答とは異なり、余分なコンマや空白文字が削除され、省略形が処理されるため、これは有益だと思います。

/**
 * Converts milliseconds to "x days, x hours, x mins, x secs"
 * 
 * @param millis
 *            The milliseconds
 * @param longFormat
 *            {@code true} to use "seconds" and "minutes" instead of "secs" and "mins"
 * @return A string representing how long in days/hours/minutes/seconds millis is.
 */
public static String millisToString(long millis, boolean longFormat) {
    if (millis < 1000) {
        return String.format("0 %s", longFormat ? "seconds" : "secs");
    }
    String[] units = {
            "day", "hour", longFormat ? "minute" : "min", longFormat ? "second" : "sec"
    };
    long[] times = new long[4];
    times[0] = TimeUnit.DAYS.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[0], TimeUnit.DAYS);
    times[1] = TimeUnit.HOURS.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[1], TimeUnit.HOURS);
    times[2] = TimeUnit.MINUTES.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[2], TimeUnit.MINUTES);
    times[3] = TimeUnit.SECONDS.convert(millis, TimeUnit.MILLISECONDS);
    StringBuilder s = new StringBuilder();
    for (int i = 0; i < 4; i++) {
        if (times[i] > 0) {
            s.append(String.format("%d %s%s, ", times[i], units[i], times[i] == 1 ? "" : "s"));
        }
    }
    return s.toString().substring(0, s.length() - 2);
}

/**
 * Converts milliseconds to "x days, x hours, x mins, x secs"
 * 
 * @param millis
 *            The milliseconds
 * @return A string representing how long in days/hours/mins/secs millis is.
 */
public static String millisToString(long millis) {
    return millisToString(millis, false);
}
1
Jared Rummler

問題があります。ミリ秒が59999の場合、実際には1分ですが、59秒として計算され、999ミリ秒は失われます。

これはこの損失を解決することができる前の答えに基づいて修正されたバージョンです:

public static String formatTime(long millis) {
    long seconds = Math.round((double) millis / 1000);
    long hours = TimeUnit.SECONDS.toHours(seconds);
    if (hours > 0)
        seconds -= TimeUnit.HOURS.toSeconds(hours);
    long minutes = seconds > 0 ? TimeUnit.SECONDS.toMinutes(seconds) : 0;
    if (minutes > 0)
        seconds -= TimeUnit.MINUTES.toSeconds(minutes);
    return hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d", minutes, seconds);
}
1
Hexise

@MyKuLLSKIの答えを修正し、plurlizationのサポートを追加しました。私はそれらを必要としなかったので私は数秒かかりました、あなたがそれを必要とするならば、それを再追加すること自由に感じなさい。

public static String intervalToHumanReadableTime(int intervalMins) {

    if(intervalMins <= 0) {
        return "0";
    } else {

        long intervalMs = intervalMins * 60 * 1000;

        long days = TimeUnit.MILLISECONDS.toDays(intervalMs);
        intervalMs -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(intervalMs);
        intervalMs -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(intervalMs);

        StringBuilder sb = new StringBuilder(12);

        if (days >= 1) {
            sb.append(days).append(" day").append(pluralize(days)).append(", ");
        }

        if (hours >= 1) {
            sb.append(hours).append(" hour").append(pluralize(hours)).append(", ");
        }

        if (minutes >= 1) {
            sb.append(minutes).append(" minute").append(pluralize(minutes));
        } else {
            sb.delete(sb.length()-2, sb.length()-1);
        }

        return(sb.toString());          

    }

}

public static String pluralize(long val) {
    return (Math.round(val) > 1 ? "s" : "");
}
0
bitstream
0
TOUDIdel