Làm cách nào để chuyển đổi Milliseconds sang Số phút X, x giây, trong Java?


572

Tôi muốn ghi lại thời gian sử dụng System.currentTimeMillis()khi người dùng bắt đầu một cái gì đó trong chương trình của tôi. Khi anh ta kết thúc, tôi sẽ trừ dòng điện System.currentTimeMillis()ra khỏi startbiến và tôi muốn cho họ thấy thời gian trôi qua bằng cách sử dụng định dạng có thể đọc được của con người như "XX giờ, XX phút, XX giây" hoặc thậm chí "XX phút, XX giây" bởi vì nó không có khả năng mất một người một giờ.

Cách tốt nhất để làm điều này là gì?


5
Nếu họ mất hơn một giờ, bạn vẫn có thể in một cái gì đó như; 90 phút, 53 giây.
Peter Lawrey

1
Câu trả lời của tôi đến muộn 6 năm nhưng tôi nghĩ nó chung chung hơn những câu được chấp nhận: stackoverflow.com/a/35082080/82609
Sebastien Lorber

Câu trả lời:


1228

Sử dụng java.util.concurrent.TimeUnitlớp:

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

Lưu ý: TimeUnitlà một phần của đặc tả Java 1.5, nhưng toMinutesđã được thêm vào kể từ Java 1.6.

Để thêm số 0 đứng đầu cho các giá trị 0-9, chỉ cần làm:

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

Nếu TimeUnithoặc toMinuteskhông được hỗ trợ (chẳng hạn như trên Android trước API phiên bản 9), hãy sử dụng các phương trình sau:

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

5
int tháng = (int) ((float) ngày / 30.4368499f); int năm = (int) ((float) ngày / 365.242199f);
Nathan Schwermann

7
Id đề nghị sử dụng mod 60 thay vì trừ đi số phút, nó trông gọn gàng hơn. Tuy nhiên, người ta cần biết rằng 1 phút = 60 giây để làm điều đó ... =)
Mỗi Alexandersson

2
@AndreasDietrich SimpleDateFormat không hoạt động vì sự khác biệt về thời gian vì nó chỉ trả về ngày từ kỷ nguyên!
Muhammad Babar

5
int hours = (int) ((milliseconds / (1000*60*60)) % 24)cái này không hiệu quả! thay vào đó nên như thế nàyint hours = (int) (milliseconds / (1000*60*60)) ;
Muhammad Babar

5
Nếu ai đó muốn định dạng cho các tệp video ( h: mm: ss ):String.format("%01d:%02d:%02d", hours, minutes, seconds);
kazy

124

Dựa trên câu trả lời của @ siddhadev, tôi đã viết một hàm chuyển đổi mili giây thành một chuỗi được định dạng:

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

2
Bạn nên thực hiện kiểm tra ở đó cho đơn / nhiều người, để tránh tình huống này:1 Days 1 Hours 1 Minutes 1 Seconds
Daniel

7
Chúng ta có thể sử dụng hàm mô đun thay vì phép trừ: 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; và cả phương thức String.format:return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds", days, hours, minutes, seconds, milliseconds);
Jose Tepedino

78
long time = 1536259;

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

Bản in:

25: 36: 259


1
Tôi thích cách tiếp cận trên là tốt nhất nếu không có gì khác đơn giản! Vì chúng ta đang đối phó với thời gian và thời lượng, tôi thường sử dụng Joda. Một ví dụ nếu bạn có hai DateTimes, bắt đầu và kết thúc tương ứng:Duration dur = new Duration(start, end); long millis = dur.getMillis();
TechTrip

1
Tôi nên lưu ý 2 cách để sử dụng các định dạng Joda. Biến thể đầu tiên trong chủ đề của bạn: DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time)); Hoặc chuyển đổi Thời lượng thành Thời gian có thể tự động được in bằng Joda PeriodFormatter. Việc chuyển đổi có thể bị mất độ chính xác nếu không theo niên đại ISO. Giả sử một Thời lượng được biểu thị bằng biến duration. Period period = duration.toPeriod().normalizedStandard(PeriodType.time()); PeriodFormat.getDefault().print(period)) Đầu ra là tuyệt vời: 1 giây và 581 mili giây, trả lời câu hỏi chính ở trên.
TechTrip

2
Một hơi muộn đây :) Nhưng bạn sẽ không cần phải đặt simpleDateFormat.setTimezone (TimeZone.getTimeZone ( "GMT")) ở đây trừ khi đó là múi giờ thực tế của bạn?
Olle Söderström

@ OlleSöderström Thực sự có vấn đề với múi giờ ở đây. Nhưng đặt nó thành GMT hoặc UTC làm cho phần giờ là 12 thay vì 0 cho tất cả thời lượng ngắn hơn 1 giờ.
Episodex

2
Timezone không phải là vấn đề duy nhất ở đây ... câu trả lời này là sai lệch và có thể gây nhầm lẫn nghiêm trọng cho người mới sử dụng Java. Ngay cả khi bỏ qua các dấu ngoặc ngoài dự phòng, OP đã hỏi cách trình bày thời lượng (chênh lệch giữa hai thời điểm, được đo bằng ms). Gọi khoảng thời gian đó là "thời gian" và coi nó như một sự bù đắp kể từ ngày 1 tháng 1 năm 1970 chỉ vì mục đích định dạng các thành phần nhỏ hơn của nó chỉ là ... sai imo. Hơn nữa, cách tiếp cận tương tự đã được đề xuất 3 năm trước bởi câu trả lời này (xem các bình luận ở đó để biết thêm chi tiết về các vấn đề múi giờ).
Amos M. Carpenter

36

Uhm ... có bao nhiêu mili giây trong một giây? Và trong một phút? Phân chia không khó lắm.

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

Tiếp tục như vậy trong nhiều giờ, ngày, tuần, tháng, năm, thập kỷ, bất cứ điều gì.


2
Trên thực tế, làm điều này cho bất cứ điều gì dài hơn một tiếng đồng hồ không phải là một ý tưởng tốt kể từ khi kết quả có thể là sai / unintuitive khi thời gian tiết kiệm ánh sáng ban ngày (ngày 23 hoặc 24 giờ) hoặc bước nhảy vọt năm có liên quan. Nếu tôi đọc "X sẽ xảy ra trong 1 năm / tháng", tôi hy vọng nó sẽ là cùng ngày và giờ.
Michael Borgwardt

5
System.cienTimeMillis () miễn dịch với DST, vì vậy điều này sẽ không bị nhầm lẫn bởi số giờ bổ sung hoặc mất tích. Nếu bạn cần phải chứng minh sự khác biệt giữa hai thời điểm cụ thể, bạn nên xây dựng ngày đối tượng với thời gian nhất định và thể hiện sự khác biệt giữa hai.
Bombe

1
Ngoài các tuần, nó không được xác định, vì độ dài tháng là thay đổi. Vì vậy, thực sự, bạn cần phải tính toán liên quan đến một tham chiếu thời gian nhất định.
PhiLho

31

Sử dụng gói java.time trong Java 8:

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

Đầu ra ở định dạng ISO 8601 Thời lượng : PT1M3.553S(1 phút và 3.553 giây).



1
(ANDROID) Yêu cầu cấp độ API 26
Có người Một nơi nào đó

1
@SomeoneSomewhere For Android dưới mức API 26 sử dụng backport, xem Làm thế nào để sử dụng ThreeTenABP trong dự án Android .
Ole VV

1
Thật tuyệt vời :) cảm ơn vì đã ngẩng cao đầu!
Ai đó ở đâu đó

27

Tôi sẽ không kéo theo sự phụ thuộc thêm chỉ vì điều đó (rốt cuộc thì việc đó không khó lắm), nhưng dù sao bạn cũng đang sử dụng Commons Lang, vẫn có WeatherFormatUtils .

Cách sử dụng ví dụ (điều chỉnh từ đây ):

import org.apache.commons.lang3.time.DurationFormatUtils

public String getAge(long value) {
    long currentTime = System.currentTimeMillis();
    long age = currentTime - value;
    String ageString = DurationFormatUtils.formatDuration(age, "d") + "d";
    if ("0d".equals(ageString)) {
        ageString = DurationFormatUtils.formatDuration(age, "H") + "h";
        if ("0h".equals(ageString)) {
            ageString = DurationFormatUtils.formatDuration(age, "m") + "m";
            if ("0m".equals(ageString)) {
                ageString = DurationFormatUtils.formatDuration(age, "s") + "s";
                if ("0s".equals(ageString)) {
                    ageString = age + "ms";
                }
            }
        }
    }
    return ageString;
}   

Thí dụ:

long lastTime = System.currentTimeMillis() - 2000;
System.out.println("Elapsed time: " + getAge(lastTime)); 

//Output: 2s

Lưu ý : Để lấy millis từ hai đối tượng LocalDateTime, bạn có thể sử dụng:

long age = ChronoUnit.MILLIS.between(initTime, LocalDateTime.now())

1
Thật tuyệt, tôi chỉ tự hỏi liệu có một thư viện mạnh mẽ bao gồm những thứ này không.
Lajcik

Là một liên kết nói chung không phải là rất hữu ích, tôi đã thêm một ví dụ về cách nó có thể được sử dụng.
Lepe

26

Hoặc chia tay hoặc sử dụng API SimpleDateFormat .

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

Chỉnh sửa bởi Bombe : Nó đã được thể hiện trong các ý kiến ​​rằng phương pháp này chỉ hoạt động trong thời lượng nhỏ hơn (tức là dưới một ngày).


Ồ Đó là một hack độc ác, phụ thuộc múi giờ. Nó sẽ bị phá vỡ không thương tiếc khi bạn có độ lệch múi giờ không phải là bội số của 60 phút (và chúng ta có một vài múi giờ bù 30 phút phiền phức trên thế giới).
Bombe

Ngoài ra, nó sẽ bị hỏng ngay khi bạn đưa số giờ vào chuỗi định dạng và không ở GMT + 0, vì những lý do tương tự.
Bombe

Chúng tôi làm gì? Có thật không? Ở đâu? Không nghi ngờ bạn, chỉ chưa bao giờ nghe về nó trước đây - một số cạm bẫy mới để xem xét ;-)
Treb

Đúng. Kiểm tra Danh sách các múi giờ của người dùng trên Wikipedia, ví dụ Nepal ở GMT + 05: 45.
Bombe

2
cadrian, bây giờ nó sẽ chỉ làm việc trong thời gian ít hơn một ngày. Số giờ sẽ luôn nằm trong khoảng từ 0 đến 23.
Bombe

21

Chỉ cần thêm thông tin nếu bạn muốn định dạng như: HH: mm: ss

0 <= HH <= vô hạn

0 <= mm <60

0 <= ss <60

dùng cái này:

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

Tôi chỉ có vấn đề này bây giờ và tìm ra điều này


1
Câu trả lời tốt nhất ở đây. Tại sao mọi người muốn làm cho mọi thứ phức tạp như vậy? Đây là toán đơn giản, folks.
Lambart

11

Tôi nghĩ cách tốt nhất là:

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

trong vài phút, bạn có thể sử dụng TimeUnit.MILLISECONDS.toMinutes (độ dài)
EminenT

11

Giải pháp ngắn nhất:

Đây có lẽ là ngắn nhất cũng liên quan đến múi giờ.

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

Những kết quả đầu ra ví dụ:

00:18:32

Giải trình:

%tTlà thời gian được định dạng cho đồng hồ 24 giờ như %tH:%tM:%tS.

%tTcũng chấp nhận lâu dài như đầu vào, vì vậy không cần phải tạo a Date. printf()sẽ chỉ in thời gian được chỉ định bằng mili giây, nhưng trong múi giờ hiện tại do đó chúng ta phải trừ đi phần bù thô của múi giờ hiện tại để 0 mili giây sẽ là 0 giờ và không phải là giá trị bù thời gian của múi giờ hiện tại.

Lưu ý # 1: Nếu bạn cần kết quả là a String, bạn có thể nhận được kết quả như sau:

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

Lưu ý # 2: Điều này chỉ cho kết quả chính xác nếu millisít hơn một ngày vì phần ngày không được bao gồm trong đầu ra.


Đây là một cách rút ngắn tuyệt vời, nhưng khi tôi sử dụng nó, tôi không nhận được kết quả như mong đợi. Vì vậy, tôi có: long millis = 8398;và khi tôi chuyển nó cho String.format("%tT", millis)đầu ra của tôi là 19:00:08. 19 đến từ đâu?
Nelda.techspiress

1
@ Nelda.techspiress Đó là phần bù của múi giờ của bạn. Bạn phải trừ TimeZone.getDefault().getRawOffset()nó, chính xác như được viết trong câu trả lời:String.format("%tT", millis-TimeZone.getDefault().getRawOffset())
icza

đã chăm sóc nó. Cảm ơn bạn đã làm rõ.
Nelda.techspiress

8

Joda-Thời gian

Sử dụng 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));

1
Không cần điều đó PeriodFormattrong dòng cuối cùng. Chỉ cần gọi Period::toStringđể nhận chuỗi Thời lượng ISO 8601 theo mặc định.
Basil Bourque

8

Xem lại đóng góp @ brent-nash, chúng ta có thể sử dụng hàm modulus thay vì trừ và sử dụng phương thức String.format cho chuỗi kết quả:

  /**
   * 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

cho Android bên dưới API 9

(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

Đối với thời gian nhỏ, ít hơn một giờ, tôi thích:

long millis = ...

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

cho các khoảng thời gian dài hơn:

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

Đó là một gợi ý quý giá, có rất nhiều khả năng về ngày và thời gian với API Formatter của Java ( docs.oracle.com/javase/8/docs/api/java/util/Formatter.html )! Bạn cũng có thể có kết quả điều kiện khác với: System.out.printf ("% 1 $ tH:% 1 $ tM:% 1 $ tS% n", millis); hoặc thậm chí System.out.printf ("% 1 $ tT% n", millis);
Jose Tepedino

@JoseTepedino nhưng bạn có biết rằng %tH chỉ hiển thị từ 0 đến 23 giờ? Điều đó có nghĩa là ví dụ 24 giờ sẽ được hiển thị dưới dạng 00, 25 giờ như 01... cùng một giá trị trong %tT- ngày sẽ bị loại bỏ trong âm thầm. Chắc chắn, cũng có thể có ngày hiển thị, nhưng đó sẽ là một sự quá mức cho vấn đề tôi gặp phải khi tôi viết bài này (trở lại năm 2011) [:-)
user85421 14/2/18

Tôi thấy ... điều đó thực sự sẽ chỉ hoạt động trong thời gian ít hơn một ngày (24h). Cảm ơn bạn.
Jose Tepedino

5

Tính toán đơn giản của tôi:

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

Chúc mừng mã hóa :)


Tôi cho rằng dài là phù hợp hơn cho chức năng này vì System.civerseTimeMillis () trả về một giá trị dài.
aprodan

Điều này là không chính xác, bạn đã kiểm tra đầu ra?
Jorgesys

4

Đây là một câu trả lời dựa trên câu trả lời của Brent Nash, Hy vọng là có ích!

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

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
Công thức trên dòng 6 là sai. diff=diff-(hours*60*1000);nên diff=diff-(hours*60*60*1000);. Tôi đã thử chỉnh sửa nó nhưng chính sách chỉnh sửa gây phiền nhiễu của StackOverflow nói rằng nó không đủ ký tự để chỉnh sửa.
quux00

4

Thứ nhất, System.currentTimeMillis()Instant.now()không lý tưởng cho thời gian. Cả hai đều báo cáo thời gian đồng hồ treo tường mà máy tính không biết chính xác và có thể di chuyển thất thường, bao gồm cả việc quay ngược lại, ví dụ như trình nền NTP sửa thời gian hệ thống. Nếu thời gian của bạn xảy ra trên một máy đơn thì thay vào đó bạn nên sử dụng System.nanoTime () .

Thứ hai, từ Java 8 trở đi java.time.Duration là cách tốt nhất để biểu thị thời lượng:

long start = System.nanoTime();
// do things...
long end = System.nanoTime();
Duration duration = Duration.ofNanos(end - start);
System.out.println(duration); // Prints "PT18M19.511627776S"
System.out.printf("%d Hours %d Minutes %d Seconds%n",
        duration.toHours(), duration.toMinutes() % 60, duration.getSeconds() % 60);
// prints "0 Hours 18 Minutes 19 Seconds"

3

Nếu bạn biết chênh lệch thời gian sẽ ít hơn một giờ, thì bạn có thể sử dụng mã sau:

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

Nó sẽ dẫn đến: 51:00


3

Câu trả lời này tương tự như một số câu trả lời ở trên. Tuy nhiên, tôi cảm thấy rằng nó sẽ có ích vì, không giống như các câu trả lời khác, điều này sẽ xóa bất kỳ dấu phẩy hoặc khoảng trắng thừa nào và xử lý viết tắt.

/**
 * 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);
}

3

Có một vấn đề. Khi mili giây là 59999, thực tế là 1 phút nhưng nó sẽ được tính là 59 giây và mất 999 mili giây.

Đây là một phiên bản sửa đổi dựa trên các câu trả lời trước đó, có thể giải quyết sự mất mát này:

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

2

Điều này dễ dàng hơn trong Java 9:

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

Điều này tạo ra một chuỗi như 0 hours, 39 mins, 9 seconds.

Nếu bạn muốn làm tròn đến toàn bộ giây trước khi định dạng:

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

Để lại giờ nếu họ là 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());
    }

Bây giờ chúng ta có thể có ví dụ 39 mins, 9 seconds.

Để in phút và giây với số 0 đứng đầu để làm cho chúng luôn có hai chữ số, chỉ cần chèn 02vào các chỉ định định dạng có liên quan, do đó:

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

Bây giờ chúng ta có thể có ví dụ 0 hours, 39 mins, 09 seconds.


Bất kỳ định dạng để loại bỏ giờ / phút / giây khi một số trước là 0? Tôi có nghĩa là nó có thể đạt được với điều kiện khác, nhưng về sự tồn tại của định dạng Chuỗi như vậy hoặc một cái gì đó gần, thì có gì không?
Farid

1
Không, xin lỗi, @FARID, bạn cần if- elseở đó.
Ole VV

1

cho các chuỗi chính xác ("1 giờ, 3 giây", "3 phút" nhưng không phải "0 giờ, 0 phút, 3 giây") tôi viết mã này:

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

Tôi đã sửa đổi câu trả lời của @MyKuLLSKI và thêm hỗ trợ số nhiều. Tôi lấy ra vài giây vì tôi không cần chúng, mặc dù vậy, vui lòng thêm lại nếu bạn cần.

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" : "");
}

int intervalMins vs long millis
Kiquenet

1

Tôi đã đề cập đến điều này trong một câu trả lời khác nhưng bạn có thể làm:

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

Đầu ra giống như Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0} , với các đơn vị đặt hàng.

Tùy thuộc vào bạn để tìm ra cách quốc tế hóa dữ liệu này theo ngôn ngữ đích.


1

Sử dụng java.util.concản.TimeUnit và sử dụng phương pháp đơn giản này:

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

Ví dụ:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.