I'm having Minutes in java.lang.Long and want to convert this value to java.math.BigDecimal, ie. as Hours.
BigDecimal hours = BigDecimal.valueOf(minutes)
.divide(BigDecimal.valueOf(DateTimeConstants.MINUTES_PER_HOUR))
.setScale(2,RoundingMode.HALF_DOWN);
Tried the above method. It return hours, but no the way actually i want it
How i need is :
240 Minutes : 4 Hours
230 Minutes : 3.50 hours
Any help?
I would convert your Minutes to a Period object:
Minutes minutes = ...;
Long millisec = minutes*60*1000;
Period period = new Period(millisec);
Then use the Period object you can ask the Hours. Anything you want...
Note: 230 minutes is not 3.50 hours, it's 3.83 hours, i'm assuming you mean "3 hours and 50 minutes".
So what you want is the hh:mm representation.
You don't need BigDecimals. Use this:
long minutes = 230;
long hours = minutes / 60;
long minnutesRemaining = minutes % 60;
System.out.println(hours + "." + minnutesRemaining);
I'm betting the OP actually wants to convert minutes into hours and minutes. This is as easy as:
int minutes = 230;
System.out.println(
String.format("%d Minutes: %d:%02d Hours", minutes, (minutes/60), (minutes%60)));
Just printing the minutes divided by 60 (using integer arithmetic) and the modulo of minutes divided by 60 (formatted as two digits with leading zeros by the "%02d" format.
You can do this using BigDecimal easy. You can use divideAndRemainder()
long minutes = 230L;
BigDecimal min = new BigDecimal(minutes);
BigDecimal constant = new BigDecimal(60);
BigDecimal[] val=min.divideAndRemainder(constant);
System.out.println(val[0]+"."+val[1]+" Hours");
Out put:
3.50 Hours
I don't know in what universe 230 minutes equals 3.5 hours, so I'm afraid that some string manipulation is your best bet:
BigDecimal hours = new BigDecimal(
String.format("%d.%d", minutes / 60, minutes % 60));
Printing out the value of hours yields 3.50, as per your requirement.
Use integer and modulo arithmetic:
long hours = minutes / 60; /*implicit round-down*/
long numberAfterDecimal = (minutes % 1.0 /*pull out the remainder*/) * 60;
Then format these two numbers as you wish.
Related
This question already has answers here:
TimeDelta java?
(3 answers)
Closed 3 years ago.
I have a duration stored in the database as a Double, but in my operations on LocalTime I need it to be of type Duration.
I need to be able to change from double to duration and vice versa.
I expect a duration of 3,5 hours to be 3 hours and 30 minutes.
// the Double value
Double someTime = 3.5;
// two ways of converting it to Duration
// (we need to use minutes because Duration.of expects a long, which cannot be fractional
Duration someDuration = Duration.ofMinutes((long) (someTime * 60));
Duration someDuration2 = Duration.of((long) (someTime * 60), ChronoUnit.MINUTES);
// convert the duration back to Double
Double someTimeAgain = (double)someDuration.toMinutes() / 60;
I assume your duration is hours as double?
Then you first need to calculate minutes from this.
This could either be
long durationInMinutes = durationFromDB * 60
or, if 0.5 is "half an hour" you need to calculate first the hours and then the minutes and add them... so 3.5h are 180 minutes + 30 minutes = 210 minutes
then you can use java.time.Duration#ofMinutes(long minutes) and get what you need.
I have a Java function that convert seconds to an specific format (hh:mm:ss):
public static String formatChronometer(long seconds) {
return String.format("%02d:%02d:%02d", TimeUnit.SECONDS.toHours(seconds),
TimeUnit.SECONDS.toMinutes(seconds) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.SECONDS.toSeconds(seconds) % TimeUnit.MINUTES.toSeconds(1));
}
My client want to show this chronometer without the "hour" labels. Example:
if 100 hours => 6000:00
if 0 hours and 50 minutes => 50:00
if 1 hour and 12 minutes and 30 seconds => 72:30
if 10 hours and 5 minutes => 600:05
if 0 hours, 0 minutes and 0 seconds => 00:00
How should I change my method?
For flexible minutes number you have to use %d instead of %02d which specify how many digit you want, your solution should look like this :
return String.format("%d:%02d",
TimeUnit.SECONDS.toMinutes(seconds),
TimeUnit.SECONDS.toSeconds(seconds) % TimeUnit.MINUTES.toSeconds(1)
);
Example
long[] times = {360000, 3000, 4350, 36300, 0};
for (long time : times) {
String result = String.format("%d:%02d",
TimeUnit.SECONDS.toMinutes(time),
TimeUnit.SECONDS.toSeconds(time) % TimeUnit.MINUTES.toSeconds(1));
System.out.println(String.format("%d : %s", time, result));
}
Outputs
360000 : 6000:00
3000 : 50:00
4350 : 72:30
36300 : 605:00
0 : 0:00
Just ditch the hours bit.
return String.format("%04d:%02d",
TimeUnit.SECONDS.toMinutes(seconds),
TimeUnit.SECONDS.toSeconds(seconds) % TimeUnit.MINUTES.toSeconds(1));
public static String formatChronometer(long seconds) {
Duration dur = Duration.ofSeconds(seconds);
return String.format("%02d:%02d", dur.toMinutes(), dur.toSecondsPart());
}
When I fed 36005 into this method, it returned 600:05.
I take it that your chronometer seconds denote a duration, an amount of time. Either an elapsed time or a value to count down from. Not a time of day (you mentioned 100 hours an example, but the time of day is never 100 hours). In that case I would clearly use the Duration class for modelling it. It’s the most correct thing to do. Some use the word self-documenting about code written with such a consideration in mind.
The Duration.toSecondsPart method was only introduced in Java 9. If you are using Java 8 (or Java 6 or 7 with the ThreeTen Backport), get the seconds part by subtracting the minutes and then converting to seconds:
long minutes = dur.toMinutes();
dur = dur.minusMinutes(minutes);
return String.format("%02d:%02d", minutes, dur.toSeconds());
Then the result is the same.
PS If your seconds denoted a time-of-day instead, the correct and self-documenting solution would be to use the LocalTime class:
LocalTime chrono = LocalTime.ofSecondOfDay(seconds);
return String.format("%02d:%02d",
chrono.get(ChronoField.MINUTE_OF_DAY), chrono.getSecond());
This will reject seconds values greater than 86399 with an exception since the time of day cannot be 24:00 or greater.
Remove your hours from the formatting
public static String formatChronometer(long seconds) {
return String.format("%02d:%02d",
TimeUnit.SECONDS.toMinutes(seconds),
TimeUnit.SECONDS.toSeconds(seconds) % TimeUnit.MINUTES.toSeconds(1));
}
Problem Statement:
Write a method whatTime, which takes an int, seconds, representing the number of seconds since midnight on some day, and returns a String formatted as "::". Here, represents the number of complete hours since midnight, represents the number of complete minutes since the last complete hour ended, and represents the number of seconds since the last complete minute ended. Each of , , and should be an integer, with no extra leading 0's. Thus, if seconds is 0, you should return "0:0:0", while if seconds is 3661, you should return "1:1:1"
My Algorithm:
Here is how my algorithm is supposed to work for the input 3661:
3661/3600 = 1.016944 -> This means the number of hours is 1
Subtract the total number of hours elapsed i.e. 1.016944-1=0.016944
Multiply this with 60 i.e. 0.016944*60=1.016666 -> The number of minutes elapsed is equal to 1
Subtract the total number of minutes elapsed i.e. 1.01666-1=0.01666. Multiply this with 60. This would yield the number of seconds elapsed.
The output produced however is 1:1:0. I tried to use a print statement and it appears that the value of 'answer3' variable is 0.999 and that is why prints the integer part (0). I tried to use the Math.ceil() function to round up the value and it produces a correct output. However I can only score about 60/250 points when I submit my code (TopCoder SRM 144 Div2) . Any insight for improving the algorithm will be helpful.
public class Time
{
public String whatTime(int seconds)
{
double answer1,answer2,answer3; int H;
answer1=(double)seconds/3600;
H=(int)answer1;
answer2=(double)((answer1-H)*60);
int M=(int)answer2;
answer3=answer2-M;
answer3=(double)answer3*60;
int S=(int)answer3;
String answer=Integer.toString(H);
answer=Integer.toString(H)+":"+Integer.toString(M)+":"+Integer.toString(S);
return answer;
}
}
public String whatTime(int seconds) {
int secondVal = seconds % 60;
int minutes = seconds / 60;
int minuteVal = minutes % 60;
int hours = minutes / 60;
int hourVal = hours % 24;
int daysVal = hours / 24;
String answer = "" + daysVal + ":" + hourVal + ":" + minuteVal + ":" + secondVal;
return answer;
}
Could do the formatting more elegantly, but that's the basic idea.
Avoid floating point values, and work entirely with ints or longs.
You could solve this by working with ints :
3661/3600 = 1.016944 -> This means the number of hours is 1
Subtract the number of hours * 3600 - i.e. 3661-(1*3600) = 61
61/60 = 1.0166666 -> The number of minutes elapsed is equal to 1
Subtract the number of minutes * 60 i.e. 61-(1*60)=1. This yields the number of seconds elapsed.
i did some research, but still can't find how to get the days... Here is what I got:
int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours = (int) ((milliseconds / (1000*60*60)) % 24);
int days = ????? ;
Please help, I suck at math, thank's.
For simple cases like this, TimeUnit should be used. TimeUnit usage is a bit more explicit about what is being represented and is also much easier to read and write when compared to doing all of the arithmetic calculations explicitly. For example, to calculate the number days from milliseconds, the following statement would work:
long days = TimeUnit.MILLISECONDS.toDays(milliseconds);
For cases more advanced, where more finely grained durations need to be represented in the context of working with time, an all encompassing and modern date/time API should be used. For JDK8+, java.time is now included (here are the tutorials and javadocs). For earlier versions of Java joda-time is a solid alternative.
If you don't have another time interval bigger than days:
int days = (int) (milliseconds / (1000*60*60*24));
If you have weeks too:
int days = (int) ((milliseconds / (1000*60*60*24)) % 7);
int weeks = (int) (milliseconds / (1000*60*60*24*7));
It's probably best to avoid using months and years if possible, as they don't have a well-defined fixed length. Strictly speaking neither do days: daylight saving means that days can have a length that is not 24 hours.
Go for TImeUnit in java
In order to import use, java.util.concurrent.TimeUnit
long millisec=System.currentTimeMillis();
long seconds=TimeUnit.MILLISECONDS.toSeconds(millisec);
long minutes=TimeUnit.MILLISECONDS.toMinutes(millisec);
long hours=TimeUnit.MILLISECONDS.toMinutes(millisec);
long days=TimeUnit.MILLISECONDS.toDays(millisec);
java.time
You can use java.time.Duration which is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementation. With Java-9 some more convenient methods were introduced.
Demo:
import java.time.Duration;
public class Main {
public static void main(String[] args) {
// Duration between the two instants
Duration duration = Duration.ofMillis(1234567890L);
// Print Duration#toString
System.out.println(duration);
// Custom format
// ####################################Java-8####################################
String formattedElapsedTime = String.format(
"%d Day %02d Hour %02d Minute %02d Second %d Millisecond (%d Nanosecond)", duration.toDays(),
duration.toHours() % 24, duration.toMinutes() % 60, duration.toSeconds() % 60,
duration.toMillis() % 1000, duration.toNanos() % 1000000000L);
System.out.println(formattedElapsedTime);
// ##############################################################################
// ####################################Java-9####################################
formattedElapsedTime = String.format("%d Day %02d Hour %02d Minute %02d Second %d Millisecond (%d Nanosecond)",
duration.toDaysPart(), duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart(),
duration.toMillisPart(), duration.toNanosPart());
System.out.println(formattedElapsedTime);
// ##############################################################################
}
}
A sample run:
PT342H56M7.89S
14 Day 06 Hour 56 Minute 07 Second 890 Millisecond (890000000 Nanosecond)
14 Day 06 Hour 56 Minute 07 Second 890 Millisecond (890000000 Nanosecond)
Learn more about the modern date-time API from Trail: Date Time.
int days = (int) (milliseconds / 86 400 000 )
public static final long SECOND_IN_MILLIS = 1000;
public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
You could cast int but I would recommend using long.
You can’t. Sorry. Or more precisely: you can if you know a time zone and a start time (or end time). A day may have a length of 23, 24 or 25 hours or some other length. So there isn’t any sure-fire formula for converting from milliseconds to days. So while you can safely rely on 1000 milliseconds in a second, 60 seconds in a minute (reservation below) and 60 minutes in an hour, the conversion to days needs more context in order to be sure and accurate.
Reservation: In real life a minute is occasionally 61 seconds because of a leap second. Not in Java. Java always counts a minute as 60 seconds because common computer clocks don’t know leap seconds. Common operating systems and Java itself do know not only summer time (DST) but also many other timeline anomalies that cause a day to be shorter or longer than 24 hours.
To demonstrate. I am writing this on March 29, 2021, the day after my time zone, Europe/Copenhagen, and the rest of the EU switched to summer time.
ZoneId myTimeZone = ZoneId.of("Europe/Copenhagen");
ZonedDateTime now = ZonedDateTime.now(myTimeZone);
ZonedDateTime twoDaysAgo = now.minusDays(2);
ZonedDateTime inTwoDays = now.plusDays(2);
System.out.println(ChronoUnit.MILLIS.between(twoDaysAgo, now));
System.out.println(ChronoUnit.MILLIS.between(now, inTwoDays));
Output:
169200000
172800000
So how many milliseconds are in two days depends on which two days you mean. And in which time zone.
So what to do?
If for your purpose you can safely define a day as 24 hours always, for example because your days are counted in UTC or your users are fine with the inaccuracy, use either Duration or TimeUnit. Since Java 9 the Duration class will additionally tell you how many hours, minutes and seconds there are in addition to the whole days. See the answer by Arvind Kumar Avinash. For the TimeUnit enum see the answers by whaley and Dev Parzival. In any case the good news is that it doesn’t matter if you suck at math because the math is taken care of for you.
If you know a time zone and a starting point, use ZonedDateTime and ChronoUnit.DAYS. In this case too the math is taken care of for you.
ZonedDateTime start = LocalDate.of(2021, Month.MARCH, 28).atStartOfDay(myTimeZone);
long millisToConvert = 170_000_000;
ZonedDateTime end = start.plus(millisToConvert, ChronoUnit.MILLIS);
long days = ChronoUnit.DAYS.between(start, end);
System.out.format("%d days%n", days);
2 days
If you additionally want the hours, minutes and seconds:
Duration remainingTime = Duration.between(start.plusDays(days), end);
System.out.format(" - and an additional %s hours %d minutes %d seconds%n",
remainingTime.toHours(),
remainingTime.toMinutesPart(),
remainingTime.toSecondsPart());
- and an additional 0 hours 13 minutes 20 seconds
If instead you had got an endpoint, subtract your milliseconds from the endpoint using the minus method (instead of the plus method used in the above code) to get the start point.
Under no circumstances do the math yourself as in the question and in the currently accepted answer. It’s error-prone and results in code that is hard to read. And if your reader sucks at math, he or she can spend much precious developer time trying to verify that you have done it correctly. Leave the math to proven library methods, and it will be much easier for your reader to trust that your code is correct.
In case you solve a more complex task of logging execution statistics in your code:
public void logExecutionMillis(LocalDateTime start, String callerMethodName) {
LocalDateTime end = getNow();
long difference = Duration.between(start, end).toMillis();
Logger logger = LoggerFactory.getLogger(ProfilerInterceptor.class);
long millisInDay = 1000 * 60 * 60 * 24;
long millisInHour = 1000 * 60 * 60;
long millisInMinute = 1000 * 60;
long millisInSecond = 1000;
long days = difference / millisInDay;
long daysDivisionResidueMillis = difference - days * millisInDay;
long hours = daysDivisionResidueMillis / millisInHour;
long hoursDivisionResidueMillis = daysDivisionResidueMillis - hours * millisInHour;
long minutes = hoursDivisionResidueMillis / millisInMinute;
long minutesDivisionResidueMillis = hoursDivisionResidueMillis - minutes * millisInMinute;
long seconds = minutesDivisionResidueMillis / millisInSecond;
long secondsDivisionResidueMillis = minutesDivisionResidueMillis - seconds * millisInSecond;
logger.info(
"\n************************************************************************\n"
+ callerMethodName
+ "() - "
+ difference
+ " millis ("
+ days
+ " d. "
+ hours
+ " h. "
+ minutes
+ " min. "
+ seconds
+ " sec."
+ secondsDivisionResidueMillis
+ " millis).");
}
P.S. Logger can be replaced with simple System.out.println() if you like.
Currently I have a function which can take the start time and end time of one day, and calculate the difference between the two, giving me the hours worked in a day. What I would like to do is be able to get the hours worked for 7 days, and return a grand total, while remaining with the display format (HH:mm).
My function for a single day's total:
Period p = new Period(this.startTime[dayIndex], this.endTime[dayIndex]);
long hours = p.getHours();
long minutes = p.getMinutes();
String format = String.format("%%0%dd", 2);//Ensures that the minutes will always display as two digits.
return Long.toString(hours)+":"+String.format(format, minutes);
this.startTime[] & this.endTime[] are both arrays of DateTime objects.
Any suggestions?
You'll need something to hold a week's worth of days, and call your function once for each day.
But that means you'll want to refactor so that your calculator method doesn't format as a string, but instead returns a numeric value, so you can easily add them together.
Another simple solution:
Here is a method that receives separate the hours and minutes.The parameters are:
Start Hour
Start Minutes
End Hour
End Minutes
first, calculate the difference between hours and minutes separate:
int hours = pEndHour - pStartHour;
int minutes = ((60 - pStartMinutes) + pEndMinutes) - 60;
then, validates if the value of "minutes" variable is negative:
// If so, the "negative" value of minutes is our remnant to the next hour
if (minutes < 0) {
hours--;
minutes = 60 + minutes ;
}
Finally you can print the period of time in the hour format:
String format = String.format("%%0%dd", 2);
System.out.println( "*** " + hours + " : " + minutes);
That's all.
Solution I ended with for those interested
Period[] p=new Period[7];
long hours = 0;
long minutes =0;
for(int x=0; x<=this.daysEntered;x++)
{
p[x] = new Period(this.startTime[x], this.endTime[x]);
hours += p[x].getHours();
minutes += p[x].getMinutes();
}
hours += minutes/60;
minutes=minutes%60;
String format = String.format("%%0%dd", 2);
return Long.toString(hours)+":"+String.format(format, minutes);