可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I\'m confused. After stumbling upon this thread, I tried to figure out how to format a countdown timer that had the format hh:mm:ss
.
Here\'s my attempt -
//hh:mm:ss
String.format(\"%02d:%02d:%02d\",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) -
TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
So, when I try a value like 3600000ms
, I get 01:59:00
, which is wrong since it should be 01:00:00
. Obviously there\'s something wrong with my logic, but at the moment, I cannot see what it is!
Can anyone help?
Edit -
Fixed it. Here\'s the right way to format milliseconds to hh:mm:ss
format -
//hh:mm:ss
String.format(\"%02d:%02d:%02d\",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))));
The problem was this TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
. It should have been this TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
instead.
回答1:
You were really close:
String.format(\"%02d:%02d:%02d\",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), // The change is in this line
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
You were converting hours to millisseconds using minutes instead of hours.
BTW, I like your use of the TimeUnit
API :)
Here\'s some test code:
public static void main(String[] args) throws ParseException {
long millis = 3600000;
String hms = String.format(\"%02d:%02d:%02d\", TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
System.out.println(hms);
}
Output:
01:00:00
I realised that my code above can be greatly simplified by using a modulus division instead of subtraction:
String hms = String.format(\"%02d:%02d:%02d\", TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.MILLISECONDS.toSeconds(millis) % TimeUnit.MINUTES.toSeconds(1));
Still using the TimeUnit
API for all magic values, and gives exactly the same output.
回答2:
The generic method for this is fairly simple:
public static String convertSecondsToHMmSs(long seconds) {
long s = seconds % 60;
long m = (seconds / 60) % 60;
long h = (seconds / (60 * 60)) % 24;
return String.format(\"%d:%02d:%02d\", h,m,s);
}
回答3:
If you are using apache commons:
DurationFormatUtils.formatDuration(timeInMS, \"HH:mm:ss,SSS\");
回答4:
// New date object from millis
Date date = new Date(millis);
// formattter
SimpleDateFormat formatter= new SimpleDateFormat(\"HH:mm:ss.SSS\");
formatter.setTimeZone(TimeZone.getTimeZone(\"UTC\"));
// Pass date object
String formatted = formatter.format(date );
See runnable example using input of 1200 ms.
回答5:
I used this:
String.format(\"%1$tH:%1$tM:%1$tS.%1$tL\", millis);
See description of class Formatter.
See runnable example using input of 2400 ms.
回答6:
DateFormat df = new SimpleDateFormat(\"HH:mm:ss\");
String formatted = df.format(aDateObject);
回答7:
Test results for the 4 implementations
Having to do a lot of formatting for huge data, needed the best performance, so here are the (surprising) results:
for (int i = 0; i < 1000000; i++) {
FUNCTION_CALL
}
Durations:
- combinationFormatter: 196 millis
- formatDuration: 272 millis
- apacheFormat: 754 millis
formatTimeUnit: 2216 millis
public static String apacheFormat(long millis) throws ParseException {
return DurationFormatUtils.formatDuration(millis, \"HH:mm:ss\");
}
public static String formatTimeUnit(long millis) throws ParseException {
String formatted = String.format(
\"%02d:%02d:%02d\",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
return formatted;
}
public static String formatDuration(final long millis) {
long seconds = (millis / 1000) % 60;
long minutes = (millis / (1000 * 60)) % 60;
long hours = millis / (1000 * 60 * 60);
StringBuilder b = new StringBuilder();
b.append(hours == 0 ? \"00\" : hours < 10 ? String.valueOf(\"0\" + hours) :
String.valueOf(hours));
b.append(\":\");
b.append(minutes == 0 ? \"00\" : minutes < 10 ? String.valueOf(\"0\" + minutes) :
String.valueOf(minutes));
b.append(\":\");
b.append(seconds == 0 ? \"00\" : seconds < 10 ? String.valueOf(\"0\" + seconds) :
String.valueOf(seconds));
return b.toString();
}
public static String combinationFormatter(final long millis) {
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis));
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis));
long hours = TimeUnit.MILLISECONDS.toHours(millis);
StringBuilder b = new StringBuilder();
b.append(hours == 0 ? \"00\" : hours < 10 ? String.valueOf(\"0\" + hours) :
String.valueOf(hours));
b.append(\":\");
b.append(minutes == 0 ? \"00\" : minutes < 10 ? String.valueOf(\"0\" + minutes) :
String.valueOf(minutes));
b.append(\":\");
b.append(seconds == 0 ? \"00\" : seconds < 10 ? String.valueOf(\"0\" + seconds) :
String.valueOf(seconds));
return b.toString();
}
回答8:
The code below does the conversion in both way
23:59:58:999 to 86398999
and than
86398999 to 23:59:58:999
import java.util.concurrent.TimeUnit;
public class TimeUtility {
public static void main(String[] args) {
long currentDateTime = System.currentTimeMillis();
String strTest = \"23:59:58:999\";
System.out.println(strTest);
long l = strToMilli(strTest);
System.out.println(l);
l += 1;
String str = milliToString(l);
System.out.println(str);
}
/**
* convert a time string into the equivalent long milliseconds
*
* @param strTime string fomratted as HH:MM:SS:MSMS i.e. \"23:59:59:999\"
* @return long integer like 86399999
*/
public static long strToMilli(String strTime) {
long retVal = 0;
String hour = strTime.substring(0, 2);
String min = strTime.substring(3, 5);
String sec = strTime.substring(6, 8);
String milli = strTime.substring(9, 12);
int h = Integer.parseInt(hour);
int m = Integer.parseInt(min);
int s = Integer.parseInt(sec);
int ms = Integer.parseInt(milli);
String strDebug = String.format(\"%02d:%02d:%02d:%03d\", h, m, s, ms);
//System.out.println(strDebug);
long lH = h * 60 * 60 * 1000;
long lM = m * 60 * 1000;
long lS = s * 1000;
retVal = lH + lM + lS + ms;
return retVal;
}
/**
* convert time in milliseconds to the corresponding string, in case of day
* rollover start from scratch 23:59:59:999 + 1 = 00:00:00:000
*
* @param millis the number of milliseconds corresponding to tim i.e.
* 34137999 that can be obtained as follows;
* <p>
* long lH = h * 60 * 60 * 1000; //hour to milli
* <p>
* long lM = m * 60 * 1000; // minute to milli
* <p>
* long lS = s * 1000; //seconds to milli
* <p>
* millis = lH + lM + lS + ms;
* @return a string formatted as HH:MM:SS:MSMS i.e. \"23:59:59:999\"
*/
private static String milliToString(long millis) {
long hrs = TimeUnit.MILLISECONDS.toHours(millis) % 24;
long min = TimeUnit.MILLISECONDS.toMinutes(millis) % 60;
long sec = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;
//millis = millis - (hrs * 60 * 60 * 1000); //alternative way
//millis = millis - (min * 60 * 1000);
//millis = millis - (sec * 1000);
//long mls = millis ;
long mls = millis % 1000;
String toRet = String.format(\"%02d:%02d:%02d:%03d\", hrs, min, sec, mls);
//System.out.println(toRet);
return toRet;
}
}
回答9:
public String millsToDateFormat(long mills) {
Date date = new Date(mills);
DateFormat formatter = new SimpleDateFormat(\"HH:mm:ss\");
String dateFormatted = formatter.format(date);
return dateFormatted; //note that it will give you the time in GMT+0
}
回答10:
Going by Bohemian\'s answer we need need not use TimeUnit to find a known value.
Much more optimal code would be
String hms = String.format(\"%02d:%02d:%02d\", millisLeft/(3600*1000),
millisLeft/(60*1000) % 60,
millisLeft/1000 % 60);
Hope it helps
回答11:
String string = String.format(\"%02d:%02d:%02d.%03d\",
TimeUnit.MILLISECONDS.toHours(millisecend), TimeUnit.MILLISECONDS.toMinutes(millisecend) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisecend)),
TimeUnit.MILLISECONDS.toSeconds(millisecend) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisecend)), millisecend - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(millisecend)));
Format: 00:00:00.000
Example: 615605 Millisecend
00:10:15.605
回答12:
I tried as shown in the first answer. It works, but minus brought me into confusion. My answer by Groovy:
import static java.util.concurrent.TimeUnit.*
...
private static String formatElapsedTime(long millis) {
int hrs = MILLISECONDS.toHours(millis) % 24
int min = MILLISECONDS.toMinutes(millis) % 60
int sec = MILLISECONDS.toSeconds(millis) % 60
int mls = millis % 1000
sprintf( \'%02d:%02d:%02d (%03d)\', [hrs, min, sec, mls])
}
回答13:
The answer marked as correct has a little mistake,
String myTime = String.format(\"%02d:%02d:%02d\",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), // The change is in this line
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
for example this is an example of the value that i get:
417474:44:19
This is the solution to get the right format is:
String myTime = String.format(\"%02d:%02d:%02d\",
//Hours
TimeUnit.MILLISECONDS.toHours(millis) -
TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(millis)),
//Minutes
TimeUnit.MILLISECONDS.toMinutes(millis) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
//Seconds
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
getting as a result a correct format:
18:44:19
other option to get the format hh:mm:ss
is just :
Date myDate = new Date(timeinMillis);
SimpleDateFormat formatter = new SimpleDateFormat(\"HH:mm:ss\");
String myTime = formatter.format(myDate);
回答14:
Well, you could try something like this, :
public String getElapsedTimeHoursMinutesSecondsString() {
long elapsedTime = getElapsedTime();
String format = String.format(\"%%0%dd\", 2);
elapsedTime = elapsedTime / 1000;
String seconds = String.format(format, elapsedTime % 60);
String minutes = String.format(format, (elapsedTime % 3600) / 60);
String hours = String.format(format, elapsedTime / 3600);
String time = hours + \":\" + minutes + \":\" + seconds;
return time;
}
to convert milliseconds to a time value
回答15:
Java 9
Duration timeLeft = Duration.ofMillis(3600000);
String hhmmss = String.format(\"%02d:%02d:%02d\",
timeLeft.toHours(), timeLeft.toMinutesPart(), timeLeft.toSecondsPart());
System.out.println(hhmmss);
This prints:
01:00:00
You are doing right in letting library methods do the conversions involved for you. java.time
, the modern Java date and time API, or more precisely, its Duration
class does it more elegantly and in a less error-prone way than TimeUnit
.
The toMinutesPart
and toSecondsPart
methods I used were introduced in Java 9.
Java 6, 7 and 8
long hours = timeLeft.toHours();
timeLeft = timeLeft.minusHours(hours);
long minutes = timeLeft.toMinutes();
timeLeft = timeLeft.minusMinutes(minutes);
long seconds = timeLeft.toSeconds();
String hhmmss = String.format(\"%02d:%02d:%02d\", hours, minutes, seconds);
System.out.println(hhmmss);
The output is the same as above.
Question: How can that work in Java 6 and 7?
- In Java 8 and later and on newer Android devices (from API level 26, I’m told)
java.time
comes built-in.
- In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
- On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from
org.threeten.bp
with subpackages.
Links
- Oracle tutorial: Date Time explaining how to use
java.time
.
- Java Specification Request (JSR) 310, where
java.time
was first described.
- ThreeTen Backport project, the backport of
java.time
to Java 6 and 7 (ThreeTen for JSR-310).
- ThreeTenABP, Android edition of ThreeTen Backport
- Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
回答16:
For Kotlin
val hours = String.format(\"%02d\", TimeUnit.MILLISECONDS.toHours(milSecs))
val minutes = String.format(\"%02d\",
TimeUnit.MILLISECONDS.toMinutes(milSecs) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milSecs)))
val seconds = String.format(\"%02d\",
TimeUnit.MILLISECONDS.toSeconds(milSecs) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milSecs)))
where, milSecs
is milliseconds
回答17:
this worked for me, with kotlin
fun formatToDigitalClock(miliSeconds: Long): String {
val hours = TimeUnit.MILLISECONDS.toHours(miliSeconds).toInt() % 24
val minutes = TimeUnit.MILLISECONDS.toMinutes(miliSeconds).toInt() % 60
val seconds = TimeUnit.MILLISECONDS.toSeconds(miliSeconds).toInt() % 60
return when {
hours > 0 -> String.format(\"%d:%02d:%02d\", hours, minutes, seconds)
minutes > 0 -> String.format(\"%02d:%02d\", minutes, seconds)
seconds > 0 -> String.format(\"00:%02d\", seconds)
else -> {
\"00:00\"
}
}
}