Converting hours in decimal format - java

I've tried mutliple solutions to this problem but I can't seem to get it.
I have time in decimal format, which is in hours. I want to make it much cleaner by changing it into a DD:HH:MM:SS format.
Example:
10.89 hours == 10 hours, 53 minutes, 40 seconds
EDIT: 10.894945454545455 == 10 hours, 53 minutes, 40 seconds
What I've tried:
int hours = (int) ((finalBuildTime) % 1);
int minutes = (int) ((finalBuildTime * (60*60)) % 60);
int seconds = (int) ((finalBuildTime * 3600) % 60);
return String.format("%s(h) %s(m) %s(s)", hours, minutes, seconds);
Which returned: 0(h) 41(m) 41(s)
Any suggestions?

There is no need to do a modular on minutes.
Your calculation of minutes should just multiply by 60, not (60*60)
double finalBuildTime = 10.89;
int hours = (int) finalBuildTime;
int minutes = (int) (finalBuildTime * 60) % 60;
int seconds = (int) (finalBuildTime * (60*60)) % 60;
System.out.println(String.format("%s(h) %s(m) %s(s)", hours, minutes, seconds));
This code gives you the correct output
10(h) 53(m) 24(s)
I believe your expected output of 40 seconds is incorrect. It should be 24 seconds.
(53*60 + 24)/(60*60) = 0.89

Here is a complete implementation:
package test.std.java;
public class Test {
public static void main(String[] args) {
System.out.println(GetReadableTime(10.89));
}
//Prints outs HH:MM:SS
public static String GetReadableTime(double finalBuildTime){
int hours = (int) Math.floor(finalBuildTime);
int remainderInSeconds = (int)(3600.0* (finalBuildTime - Math.floor(finalBuildTime)) );
int seconds = remainderInSeconds % 60;
int minutes = remainderInSeconds / 60;
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
}

First part of rgettman is true :
float finalBuildTime = 10.89;
int hours = (int) finalBuildTime; // 10 ok
But (int) ((10.89 * (60 *60)) / 60) = 683 which is not what you want : it is the direct conversion of finalBuildTime in minutes
int minutes = (int) ((finalBuildTime - hours) * 60); // 53 ok
int seconds = (int) ((finalBuildTime - hours) * 3600 - minutes * 60 + 0.5); // 24 ok
I've added 0.5 for the seconds computation to round to the nearest second rather than truncate. For your example it is no use because your time is an integer number of seconds.
And the number of seconds is 24 seconds = 0.4 minutes

I assume finalBuildTime is a double. You just have to do :
int hours = (int)finalBuildTime;
int minutes = (int)((finalBuildTime - hours) * 60);
int seconds = (int)((((finalBuildTime - hours) * 60) - minutes ) * 60);

(int) rounds down. Therefore, (int)(finalBuildTime) gives you hours.
Since 60 times 60 is 3600, your seconds and minutes calculations are the same.
To find the minutes and seconds, I would observe that the 10.89 hours in your example is 10 hours and 0.89 hours. I would first calculate how many minutes is in 0.89 hours.(the part after the decimal point) That would be 0.89 times 60. Again, since this number should always be less than 60, casting(therefore, rounding down) the number to an (int) gives you minutes. Therefore, for minutes, it is int minutes = (int)((finalBuildTime-hours)*60);
You can keep the rest of your code.

The other answers are correct, but in case it helps you (or someone else who stumbles across this) it is a lot easier to use a library like Joda-Time to do this. Here is a solution to your problem using Joda-Time 2.3:
double buildDurationInHours = 10.89;
long buildDurationInMilliseconds = new Double(DateTimeConstants.MILLIS_PER_HOUR * buildDurationInHours).longValue();
Period period = new Period(buildDurationInMilliseconds);
System.out.println("The build took "
+ period.getDays() + " days, "
+ period.getHours() + " hours, "
+ period.getMinutes() + " minutes, and "
+ period.getSeconds() + " seconds.");
Output:
The build took 0 days, 10 hours, 53 minutes, and 24 seconds.
This way you don't have to deal directly with calculating the hours, minutes, seconds, etc.

Related

How to build stopwatch with hundreth of a second precision?

I'm trying to build a stopwatch with hundreth of second precision. I have this code that runs every 10 milliseconds but I am having trouble converting it to a 0(min):0(sec):00 format.
timer.post(new Runnable() {
#Override
public void run() {
time += 1;
txtView.setText(convertTimeToText(time));
timer.postDelayed(this, 10);
}
});
private String convertTimeToText(int time) {
String convertedTime = time / 6000 + ":" + (time / 100) % 60
+ ":" + (time / 10) % 10 + time % 10;
return convertedTime;
}
I need help with the convertTimeToText(int time){} that formats time.
EDIT:
Thanks to Ole V.V. and WJS for the formatting answer and how to fix the delay I was having, this is the code I came up with if anybody needs it, so far it works well, maybe using System.nanoTime() will get you more accurate results but for my use its fine.
public void start(){
final long timeMillisWhenStarted = System.currentTimeMillis();
if(!isRunning){
isRunning = true;
timer.post(new Runnable() {
#Override
public void run() {
long millisNow = System.currentTimeMillis();
long time = millisNow - timeMillisWhenStarted;
yourtxtView.setText(convertTimeToText(time));
timer.postDelayed(this, 10);
}
});
}
}
private String convertTimeToText(long time){
long hundredths = time / 10;
long sec = hundredths / 100;
long min = sec / 60;
return String.format("%02d:%02d.%02d", min % 60, sec % 60, hundredths % 100);
}
See if this helps. The remainders weren't being computed correctly.
For 12340 hundreds of seconds that would be 123.40 seconds
so 12340 / 6000 = 2 for minutes
12340 % 6000 gets what's left which is 340
so 340 /100 = 3 seconds
leaving 340 % 100= 40 hundredths
public static void main(String[] args) {
// n = 16 mins 4 seconds and 99 hundredths
int n = (16 * 6000) + (4 * 100) + 99;
System.out.println(convertTimeToText(n));
}
private static String convertTimeToText(int time) {
int mins = time / 6000;
time %= 6000; // get remaining hundredths
int seconds = time / 100;
int hundredths = time %= 100; // get remaining hundredths
// format the time. The leading 0's mean to pad single
// digits on the left with 0. The 2 is a field width
return String.format("%02d:%02d:%02d", mins, seconds,
hundredths);
}
This prints
16:04:99
Use the standard library
Your timer isn’t accurate. Your observed delay comes from there. Read the time off some clock each time rather than adding 1/100 second. Use for example System.currentTimeMillis(), System.nanoTime() or Instant.now(). Keep the reading from when your stopwatch was started and subtract for getting the current stopwatch value.
Should performing a system call 100 times per second be too expensive (which I don’t expect), do it for example for every 30 ticks to adjust your stopwatch back to the correct time.
Next if you are using Java 9 or higher, use the Duration class for converting from the the time (whether in milliseconds or nanoseconds) to minutes and seconds. If you do the conversion by hand as you tried, it’s error-prone and hard to read, which — I believe — was one reason for your question.
For example:
long millisNow = System.currentTimeMillis();
Duration time = Duration.ofMillis(millisNow - timeMillisWhenStarted);
String convertedTime = String.format("%d:%02d.%02d",
time.toMinutes(), time.toSecondsPart(), time.toMillisPart() / 10);

Timer shows 010:00 after 10 minutes instead of 10:00

What do I have to change so that the timer is showing 10:00 after 10 minutes instead of 010:00. I know a bit how to solve it but it doesn't solve the original problem -- if delete the "0" from (textTimer.setText("0" + minutes + ":") it shows 0:00 when its under 10. How do I make it to show 10:00 after 10 minutes and 00:00 before 10 mins. Thanks
public void run() {
timeInMillies = SystemClock.uptimeMillis() - startTime;
finalTime = timeSwap + timeInMillies;
int seconds = (int) (finalTime / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
int milliseconds = (int) (finalTime % 1000);
textTimer.setText("0" + minutes + ":"
+ String.format("%02d", seconds));
myHandler.postDelayed(this, 0);
}
I'm not entirely sure why you're not formatting the entire string
textTimer.setText(String.format("%02d:%02d", minutes, seconds));

Convert long to remaining time

I'm currently trying to convert a long to a remaining time. I have got a
long remaining = XXXX
The long are the milliseconds to a certain date. For example: 3,600,000 should result in int weeks = 0, days = 0, hours = 1, minutes = 0, seconds = 0
how can I convert this long so that I end up with 5 ints:
int weeks;
int days;
int hours;
int minutes;
int seconds;
Thank you in advance!
DirtyDev
First, I suggest defining the number of ms in a second, minute, hour, etc as constants
static final int SECOND = 1000; // no. of ms in a second
static final int MINUTE = SECOND * 60; // no. of ms in a minute
static final int HOUR = MINUTE * 60; // no. of ms in an hour
static final int DAY = HOUR * 24; // no. of ms in a day
static final int WEEK = DAY * 7; // no. of ms in a week
Then, you can use basic division (/) and modulus (%) operations to find what you need.
long remaining = XXXX;
int weeks = (int)( remaining / WEEK);
int days = (int)((remaining % WEEK) / DAY);
int hours = (int)((remaining % DAY) / HOUR);
int minutes = (int)((remaining % HOUR) / MINUTE);
int seconds = (int)((remaining % MINUTE) / SECOND);
Excuse me, I don’t want to criticize too much, still I gather from the other answers that it’s easy to either write code that is hard to read or code with typos that gives an incorrect result. DirtyDev, I am aware that you may not be allowed to use Duration, but for anyone else:
long remaining = 3_600_000;
Duration remainingTime = Duration.ofMillis(remaining);
long days = remainingTime.toDays();
remainingTime = remainingTime.minusDays(days);
long weeks = days / 7;
days %= 7; // or if you prefer, days = days % 7;
long hours = remainingTime.toHours();
remainingTime = remainingTime.minusHours(hours);
long minutes = remainingTime.toMinutes();
remainingTime = remainingTime.minusMinutes(minutes);
long seconds = remainingTime.getSeconds();
System.out.println("" + weeks + " weeks " + days + " days "
+ hours + " hours " + minutes + " minutes " + seconds + " seconds");
This prints:
0 weeks 0 days 1 hours 0 minutes 0 seconds
It’s not perfect, but I believe it’s both readable, correct and robust. Duration was meant for times from hours down to nanoseconds, so we still have to do the weeks “by hand”.
Happy New Year.
This should do what you want.
long inputTimeInMilliseconds = 93800000;
long milliseconds = inputTimeInMilliseconds % 1000;
long seconds = (inputTimeInMilliseconds / 1000) % 60 ;
long minutes = ((inputTimeInMilliseconds / (1000*60)) % 60);
long hours = ((inputTimeInMilliseconds / (1000*60*60)) % 24);
long days = ((inputTimeInMilliseconds / (1000*60*60*24)) % 7);
long weeks = (inputTimeInMilliseconds / (1000*60*60*24*7));
String remainingTime = "time:"+weeks+":"+days+":"+ hours+":"+minutes+":"+seconds+":"+milliseconds;
System.out.println(remainingTime);

Rounding off decimals at a particular decimal number java

How to get correct time when subtracting decimal numbers. I wanted to subtract numbers as if it were tiime. But time only goes to 60 minutes whereas numbers to 100. How could I put some sort of restriction on the decimal places to make it like time.
Here's one way. The elapsed time is in milliseconds, as that is what you have when you subtract a start System.currentTimeMillis() from a finish System.currentTimeMillis().
public String formatElapsedTime(long elapsedTime) {
int centiseconds = (int) (((elapsedTime % 1000L) + 5L) / 10L);
centiseconds %= 10;
int seconds = (int) (elapsedTime / 1000L);
int minutes = seconds / 60;
seconds -= minutes * 60;
int hours = minutes / 60;
minutes -= hours * 60;
if (hours > 0) {
return String.format("%2d:%02d:%02d.%02d", hours, minutes, seconds,
centiseconds);
} else if (minutes > 0) {
return String.format("%2d:%02d.%02d", minutes, seconds,
centiseconds);
} else {
return String.format("%2d.%02d", seconds, centiseconds);
}
}
You probably don’t need to display centiseconds when you’re measuring elapsed time in hours.
Because my format strings start with “%2d”, seconds, minutes, and hours less than 10 have a space as the first character of the string. I find this keeps the display from jumping so much. If you don’t want the leading space, change the format String to “%1d”.
You can calculate days as well, for really long elapsed times. You would probably want a format like “3 days, 6 hours, 25 minutes, and 13 seconds”. Or not.

JAVA convert minutes into default time [hh:mm:ss]

what is the easiest and fastest way to convert minutes (double) to default time hh:mm:ss
for example I used this code in python and it's working
time = timedelta(minutes=250.0)
print time
result:
4:10:00
is there a java library or a simple code can do it?
EDIT: To show the seconds as SS you can make an easy custom formatter variable to pass to the String.format() method
EDIT: Added logic to add one minute and recalculate seconds if the initial double value has the number value after the decimal separator greater than 59.
EDIT: Noticed loss of precision when doing math on the double (joy of working with doubles!) seconds, so every now and again it would not be the correct value. Changed code to properly calculate and round it. Also added logic to treat cases when minutes and hour overflow because of cascading from seconds.
Try this (no external libraries needed)
public static void main(String[] args) {
final double t = 1304.00d;
if (t > 1440.00d) //possible loss of precision again
return;
int hours = (int)t / 60;
int minutes = (int)t % 60;
BigDecimal secondsPrecision = new BigDecimal((t - Math.floor(t)) * 100).setScale(2, RoundingMode.HALF_UP);
int seconds = secondsPrecision.intValue();
boolean nextDay = false;
if (seconds > 59) {
minutes++; //increment minutes by one
seconds = seconds - 60; //recalculate seconds
}
if (minutes > 59) {
hours++;
minutes = minutes - 60;
}
//next day
if (hours > 23) {
hours = hours - 24;
nextDay = true;
}
//if seconds >=10 use the same format as before else pad one zero before the seconds
final String myFormat = seconds >= 10 ? "%d:%02d:%d" : "%d:%02d:0%d";
final String time = String.format(myFormat, hours, minutes, seconds);
System.out.print(time);
System.out.println(" " + (nextDay ? "The next day" : "Current day"));
}
Of course this can go on and on, expanding on this algorithm to generalize it. So far it will work until the next day but no further, so we could limit the initial double to that value.
if (t > 1440.00d)
return;
Using Joda you can do something like:
import org.joda.time.Period;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;
final Period a = Period.seconds(25635);
final PeriodFormatter hoursMinutes = new PeriodFormatterBuilder().appendHours().appendSuffix(" hour", " hours")
.appendSeparator(" and ").appendMinutes().appendSuffix(" minute", " minutes").appendSeparator(" and ")
.appendSeconds().appendSuffix(" second", " seconds").toFormatter();
System.out.println(hoursMinutes.print(a.normalizedStandard()));
//Accept minutes from user and return time in HH:MM:SS format
private String convertTime(long time)
{
String finalTime = "";
long hour = (time%(24*60)) / 60;
long minutes = (time%(24*60)) % 60;
long seconds = time / (24*3600);
finalTime = String.format("%02d:%02d:%02d",
TimeUnit.HOURS.toHours(hour) ,
TimeUnit.MINUTES.toMinutes(minutes),
TimeUnit.SECONDS.toSeconds(seconds));
return finalTime;
}

Categories