วิธีแปลงมิลลิวินาทีเป็น“ X นาที, x วินาที” ใน Java


572

ฉันต้องการบันทึกเวลาที่ใช้System.currentTimeMillis()เมื่อผู้ใช้เริ่มต้นบางอย่างในโปรแกรมของฉัน เมื่อเขาเสร็จสิ้นฉันจะลบกระแสSystem.currentTimeMillis()ออกจากstartตัวแปรและฉันต้องการแสดงเวลาที่ผ่านไปโดยใช้รูปแบบที่มนุษย์อ่านได้เช่น "XX ชั่วโมง, XX นาที, XX วินาที" หรือแม้กระทั่ง "XX นาที, XX วินาที" ไม่น่าจะใช้เวลาหนึ่งชั่วโมง

วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?


5
หากพวกเขาใช้เวลามากกว่าหนึ่งชั่วโมงคุณยังคงสามารถพิมพ์สิ่งที่ต้องการ; 90 นาที 53 วินาที
Peter Lawrey

1
คำตอบของฉันมาถึงช้ากว่า 6 ปี แต่ฉันคิดว่ามันธรรมดากว่าคำตอบที่ยอมรับได้: stackoverflow.com/a/35082080/82609
Sebastien Lorber

คำตอบ:


1228

ใช้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ไม่ได้รับการสนับสนุน (เช่นบน Android ก่อน API เวอร์ชัน 9) ให้ใช้สมการต่อไปนี้:

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

5
int months = (int) ((ลอย) วัน / 30.4368499f); int Years = (int) (ลอย) วัน / 365.242199f);
Nathan Schwermann

7
Id แนะนำให้ใช้ mod 60 แทนการลบนาทีมันดูสะอาดตา อย่างไรก็ตามต้องรู้ว่า 1 นาที = 60 วินาทีในการทำเช่นนั้น ... =)
ต่อ Alexandersson

2
@AndreasDietrich SimpleDateFormat ไม่ทำงานสำหรับความแตกต่างของเวลาเพราะมันแค่คืนวันที่จากยุค!
Muhammad Babar

5
int hours = (int) ((milliseconds / (1000*60*60)) % 24)มันไม่ทำงาน! แต่ควรเป็นเช่นนี้int hours = (int) (milliseconds / (1000*60*60)) ;
Muhammad Babar

5
หากใครต้องการรูปแบบสำหรับไฟล์วิดีโอ ( h: mm: ss ):String.format("%01d:%02d:%02d", hours, minutes, seconds);
kazy

124

จากคำตอบของ @ 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());
    }

2
คุณควรทำการตรวจสอบที่นั่นสำหรับคนเดียว / หลายคนเพื่อหลีกเลี่ยงสถานการณ์เช่นนี้:1 Days 1 Hours 1 Minutes 1 Seconds
Daniel

7
เราสามารถใช้ฟังก์ชั่นโมดูลัสแทนการลบ: 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; และวิธีการ 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));

พิมพ์:

25: 36: 259


1
ฉันชอบวิธีการข้างต้นที่ดีที่สุดถ้าไม่มีอะไรเรียบง่ายอีกแล้ว! เนื่องจากเราจัดการกับเวลาและระยะเวลาฉันมักจะใช้ Joda ตัวอย่างถ้าคุณมี DateTimes สองรายการให้เริ่มต้นและสิ้นสุดตามลำดับ:Duration dur = new Duration(start, end); long millis = dur.getMillis();
TechTrip

1
ฉันควรจดบันทึก 2 วิธีในการใช้ตัวจัดรูปแบบ Joda รูปแบบครั้งแรกในรูปแบบของคุณ: DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time)); หรือแปลงระยะเวลาระยะเวลาที่สามารถพิมพ์โดยอัตโนมัติโดยใช้ PeriodFormatterJoda การแปลงอาจสูญเสียความแม่นยำหากนอกเหนือจากเหตุการณ์ ISO durationสมมติว่าระยะเวลาแสดงโดยตัวแปร Period period = duration.toPeriod().normalizedStandard(PeriodType.time()); PeriodFormat.getDefault().print(period)) เอาต์พุตน่าประทับใจ: 1 วินาทีและ 581 มิลลิวินาทีตอบคำถามหลักด้านบน
TechTrip

2
ค่อนข้างช้าที่นี่ :) แต่คุณไม่จำเป็นต้องใส่ simpleDateFormat.setTimezone (TimeZone.getTimeZone ("GMT")) ที่นี่เว้นแต่ว่าเป็นเขตเวลาจริงของคุณหรือไม่
Olle Söderström

@ OlleSöderströmมีปัญหากับเขตเวลาที่นี่ แต่การตั้งค่าเป็น GMT หรือ UTC ทำให้ส่วนชั่วโมงเป็น 12 แทน 0 สำหรับระยะเวลาทั้งหมดที่สั้นกว่า 1 ชั่วโมง
Episodex

2
เขตเวลาไม่ใช่ปัญหาเดียวที่นี่ ... คำตอบนี้ทำให้เข้าใจผิดและอาจสับสนมือใหม่ Java อย่างจริงจัง แม้จะไม่สนใจวงเล็บนอกที่ซ้ำซ้อน OP ก็ถามถึงวิธีการนำเสนอช่วงเวลา (ความแตกต่างระหว่างจุดสองจุดในเวลาวัดเป็นมิลลิวินาที) การเรียกช่วงเวลานั้นว่า "เวลา" และถือว่ามันเป็นออฟเซ็ตตั้งแต่วันที่ 1 มกราคม 1970 เพียงเพื่อการจัดรูปแบบส่วนประกอบที่มีขนาดเล็กนั้นเป็นเพียง ... imo ผิด ยิ่งไปกว่านั้นวิธีการเดียวกันนี้ได้รับการแนะนำเมื่อ 3 ปีก่อนโดยคำตอบนี้ (ดูความคิดเห็นที่นั่นเพื่อดูรายละเอียดเพิ่มเติมเกี่ยวกับปัญหาเขตเวลา)
Amos M. Carpenter

36

เอ่อ ... กี่มิลลิวินาทีในไม่กี่วินาที? และในหนึ่งนาที กองนั้นไม่ยาก

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

ทำต่อไปเช่นนั้นเป็นชั่วโมงวันสัปดาห์เดือนเดือนปีทศวรรษอะไรก็ตาม


2
ที่จริงแล้วการทำสิ่งนี้เพื่ออะไรที่นานกว่าหนึ่งชั่วโมงนั้นไม่ใช่ความคิดที่ดีเนื่องจากผลลัพธ์อาจผิด / ไม่ได้ใช้งานง่ายเมื่อมีการปรับเวลาตามฤดูกาล (23 หรือ 24 ชั่วโมง) หรือปีอธิกสุรทิน ถ้าฉันอ่าน "X จะเกิดขึ้นใน 1 ปี / เดือน" ฉันคาดว่ามันจะเป็นวันที่และเวลาเดียวกัน
Michael Borgwardt

5
System.currentTimeMillis () เป็นภูมิคุ้มกันต่อ DST ดังนั้นสิ่งนี้จะไม่สับสนโดยชั่วโมงเพิ่มเติมหรือหายไป หากคุณต้องการแสดงความแตกต่างระหว่างวันที่สองวันคุณจะสามารถสร้างวัตถุวันที่ได้ตามเวลาที่กำหนดและแสดงความแตกต่างระหว่างสองวันนั้น
Bombe

1
เกินสัปดาห์ก็ไม่ได้กำหนดเนื่องจากความยาวของเดือนเป็นตัวแปร ดังนั้นคุณต้องคำนวณเทียบกับเวลาอ้างอิงที่กำหนด
PhiLho

31

การใช้แพ็คเกจ java.timeใน Java 8:

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

เอาต์พุตอยู่ในรูปแบบ ISO 8601 Duration : PT1M3.553S(1 นาทีและ 3.553 วินาที)



1
(ANDROID) ต้องใช้ API ระดับ 26
บางคนอยู่ที่ไหนสักแห่ง

1
@SomeoneSomewhere สำหรับหุ่นยนต์ภายใต้ระดับ API 26 ใช้ย้ายกลับให้ดูวิธีการใช้ ThreeTenABP ในโครงการ
Ole VV

1
มันยอดเยี่ยมมาก :) ขอบคุณสำหรับการเฮฮา!
คนที่ไหนสักแห่ง

27

ฉันจะไม่ดึงในการพึ่งพาพิเศษเพียงสำหรับการที่ (ส่วนไม่ว่าหนักหลังจากทั้งหมด) แต่ถ้าคุณกำลังใช้คอมมอนส์แลงแล้วยังมีDurationFormatUtils

ตัวอย่างการใช้งาน (ดัดแปลงจากที่นี่ ):

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

ตัวอย่าง:

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

//Output: 2s

หมายเหตุ : ในการรับมิลลิวินาทีจากวัตถุ LocalDateTime สองรายการคุณสามารถใช้:

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

1
เยี่ยมมากฉันแค่ถามตัวเองว่ามีห้องสมุดที่มีประสิทธิภาพหรือไม่
Lajcik

เนื่องจากลิงก์โดยทั่วไปไม่ค่อยมีประโยชน์ฉันจึงเพิ่มตัวอย่างว่าจะใช้งานอย่างไร
lepe

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 : มันแสดงให้เห็นในความคิดเห็นว่าวิธีนี้ใช้ได้กับระยะเวลาที่น้อยกว่า (เช่นน้อยกว่าหนึ่งวัน)


ว้าว. นั่นคือแฮ็คที่ชั่วร้ายขึ้นอยู่กับเขตเวลา มันจะพังอย่างไร้ความปราณีเมื่อคุณมีการชดเชยเขตเวลาซึ่งไม่ใช่เวลา 60 นาที (และเรามีเขตเวลาชดเชย 30 นาทีที่น่ารำคาญในโลก)
Bombe

นอกจากนี้มันจะหยุดพักทันทีที่คุณรวมชั่วโมงในสตริงรูปแบบและไม่อยู่ที่ GMT + 0 ด้วยเหตุผลเดียวกัน
Bombe

พวกเราทำ? จริงๆ? ที่ไหน? ไม่สงสัยคุณก็ไม่เคยได้ยินมาก่อน - บางหลุมพรางใหม่ที่จะต้องพิจารณา ;-)
Treb

ใช่. ทำเครื่องหมายที่ "รายชื่อของเขตเวลา" บน Wikipedia เช่น Nepal ที่ GMT + 05: 45
Bombe

2
cadrian ตอนนี้จะใช้งานได้สำหรับระยะเวลาน้อยกว่าหนึ่งวัน จำนวนชั่วโมงจะอยู่ระหว่าง 0 ถึง 23 เสมอ
Bombe

21

เพียงเพิ่มข้อมูลเพิ่มเติมหากคุณต้องการจัดรูปแบบเช่น: 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);

ฉันเพิ่งมีปัญหานี้และคิดออก


1
คำตอบที่ดีที่สุดที่นี่ ทำไมทุกคนต้องการทำสิ่งที่ซับซ้อนมาก? นี่คือคณิตศาสตร์อย่างง่ายผู้คน
Lambart

11

ฉันคิดว่าวิธีที่ดีที่สุดคือ:

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

นาทีคุณสามารถใช้ TimeUnit.MILLISECONDS.toMinutes (ความยาว)
EminenT

11

ทางออกที่สั้นที่สุด:

นี่อาจสั้นที่สุดที่เกี่ยวข้องกับเขตเวลา

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

ตัวอย่างผลลัพธ์ใด:

00:18:32

คำอธิบาย:

%tTเป็นเวลาที่จัดรูปแบบสำหรับนาฬิกา 24 %tH:%tM:%tSชั่วโมงเป็น

%tTยังยอมรับ longs เป็น input Dateจึงไม่จำเป็นต้องสร้าง printf()จะพิมพ์เวลาที่ระบุในหน่วยมิลลิวินาที แต่ในเขตเวลาปัจจุบันดังนั้นเราต้องลบการชดเชยแบบดิบของเขตเวลาปัจจุบันเพื่อให้ 0 มิลลิวินาทีจะเป็น 0 ชั่วโมงไม่ใช่ค่าชดเชยเวลาของเขตเวลาปัจจุบัน

หมายเหตุ # 1:หากคุณต้องการผลลัพธ์เป็น a Stringคุณสามารถได้รับดังนี้:

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

หมายเหตุ # 2:นี่จะให้ผลลัพธ์ที่ถูกต้องหากmillisน้อยกว่าหนึ่งวันเพราะส่วนวันไม่รวมอยู่ในเอาท์พุท


นี่เป็นทางลัดที่ยอดเยี่ยม แต่เมื่อฉันใช้มันฉันไม่ได้ผลลัพธ์ที่คาดหวัง ดังนั้นฉันจึงมี: long millis = 8398;และเมื่อฉันส่งสิ่งนั้นไปยังString.format("%tT", millis)เอาท์พุทของฉันคือ 19:00:08 19 มาจากไหน
Nelda.techspiress

1
@ Nelda.techspiress นั่นคือการชดเชยเขตเวลาของคุณ คุณต้องลบTimeZone.getDefault().getRawOffset()มันออกไปตามที่เขียนไว้ในคำตอบ:String.format("%tT", millis-TimeZone.getDefault().getRawOffset())
icza

ที่ดูแลมัน ขอบคุณสำหรับการชี้แจง
Nelda.techspiress

8

Joda เวลา

ใช้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
ไม่จำเป็นต้องใช้PeriodFormatในบรรทัดสุดท้าย เพียงแค่โทรPeriod::toStringเพื่อรับสตริงISO 8601 Durationตามค่าเริ่มต้น
Basil Bourque

8

Revisiting @ 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

สำหรับ Android ด้านล่าง 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

สำหรับเวลาเล็ก ๆ น้อยกว่าหนึ่งชั่วโมงฉันชอบ:

long millis = ...

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

สำหรับ intervall อีกต่อไป:

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

นั่นเป็นคำใบ้ที่มีค่ามีความเป็นไปได้มากมายสำหรับวันที่และเวลาด้วย Java Formatter API ( docs.oracle.com/javase/8/docs/api/java/util/Formatter.html ) นอกจากนี้คุณยังสามารถมีผลลัพธ์เงื่อนไขอื่นด้วย: System.out.printf ("% 1 $ tH:% 1 $ tM:% 1 $ tS% n", มิลลิวินาที); หรือแม้แต่ System.out.printf ("% 1 $ tT% n", มิลลิวินาที);
Jose Tepedino

@JoseTepedino แต่คุณทราบหรือไม่ว่า%tH จะมีการแสดงตั้งแต่ 0 ถึง 23 ชั่วโมงเท่านั้น ซึ่งหมายความว่าตัวอย่างเช่น 24 ชั่วโมงจะปรากฏเป็น0025 ชั่วโมงเช่น01... ถูกต้องสำหรับ%tT- วันจะถูกทิ้งในใจ แน่นอนว่าอาจมีวันที่แสดง แต่นั่นจะเป็นปัญหามากเกินไปสำหรับปัญหาที่ฉันมีเมื่อฉันเขียนสิ่งนี้ (ย้อนกลับไปในปี 2011) [:-)
user85421

ฉันเห็น ... ว่าจะใช้งานได้จริงน้อยกว่าหนึ่งวัน (24 ชั่วโมง) ขอบคุณ.
Jose Tepedino

5

การคำนวณอย่างง่ายของฉัน:

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

Happy coding :)


ฉันคิดว่านานเหมาะสมกว่าสำหรับฟังก์ชั่นนี้เป็น System.currentTimeMillis () ส่งคืนค่ายาว
aprodan

ไม่ถูกต้องคุณตรวจสอบเอาท์พุทหรือไม่?
Jorgesys

4

นี่คือคำตอบจากคำตอบของ 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());
}

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
สูตรในบรรทัด 6 ไม่ถูกต้อง ควรจะเป็นdiff=diff-(hours*60*1000); diff=diff-(hours*60*60*1000);ฉันพยายามแก้ไข แต่นโยบายการแก้ไขที่น่ารำคาญของ StackOverflow บอกว่ามีอักขระไม่เพียงพอสำหรับการแก้ไข
quux00

4

ประการแรกSystem.currentTimeMillis()และInstant.now()ไม่เหมาะสำหรับเวลา พวกเขาทั้งสองรายงานเวลานาฬิกาแขวนซึ่งคอมพิวเตอร์ไม่ทราบอย่างแม่นยำและสามารถเคลื่อนย้ายผิดปกติรวมถึงการย้อนกลับหากตัวอย่าง NTP daemon แก้ไขเวลาระบบ หากเวลาของคุณเกิดขึ้นในเครื่องเดียวคุณควรใช้System.nanoTime ()แทน

ประการที่สองจาก Java 8 เป็นต้นไปjava.time.Durationเป็นวิธีที่ดีที่สุดในการแสดงช่วงเวลา:

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

หากคุณรู้ว่าความแตกต่างของเวลาจะน้อยกว่าหนึ่งชั่วโมงคุณสามารถใช้รหัสต่อไปนี้:

    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


3

คำตอบนี้คล้ายกับคำตอบข้างต้น อย่างไรก็ตามฉันรู้สึกว่ามันจะเป็นประโยชน์เพราะไม่เหมือนกับคำตอบอื่น ๆ ซึ่งจะลบเครื่องหมายจุลภาคพิเศษหรือช่องว่างออกและจัดการตัวย่อ

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

มีปัญหา เมื่อมิลลิวินาทีเป็น 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);
}

2

ง่ายกว่าใน 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ตอนนี้เราสามารถมีตัวอย่างเช่น

หากต้องการพิมพ์นาทีและวินาทีโดยมีศูนย์นำหน้าเพื่อให้ตัวเลขสองหลักเสมอเพียงแค่ใส่02ตัวระบุรูปแบบที่เกี่ยวข้องดังนี้:

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

0 hours, 39 mins, 09 secondsตอนนี้เราสามารถมีตัวอย่างเช่น


การจัดรูปแบบใด ๆ เพื่อลบชั่วโมง / นาที / วินาทีเมื่อหมายเลขก่อนหน้าเป็น 0? ฉันหมายความว่ามันสามารถทำได้โดยมีเงื่อนไขอื่น แต่สิ่งที่เกี่ยวกับการดำรงอยู่ของการจัดรูปแบบสตริงดังกล่าวหรือสิ่งที่ใกล้ชิดมีอะไรบ้าง
Farid

1
ไม่ขอโทษ @FARID ที่คุณต้องการif- elseนั่น
Ole VV

1

สำหรับสตริงที่ถูกต้อง ("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

ฉันแก้ไขคำตอบของ @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" : "");
}

int intervalMins vs long millis
Kiquenet

1

ฉันพูดถึงเรื่องนี้ด้วยคำตอบอื่นแต่คุณสามารถทำได้:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.