I'm trying to compare a duration to an integer representing minutes (so another duration) in order to find out if it's a longer or shorter time. I'm trying to use compareTo(Duration duration) method but I can't use an int as parameter. How would I transform that int (minutes) into Duration?
You can create a duration in minutes with the ofMinutes static method. So, as a silly example
int compareDurations(Duration d) {
int myMinutes = 5;
Duration durationInMinutes = Duration.ofMinutes(myMinutes);
return d.compareTo(durationMinutes);
}
I always find code involving compareTo() hard to read. Therefore for most purposes I would prefer to do it the other way around: convert your Duration to minutes and compare using plain < or >.
int minutes = 7;
Duration dur = Duration.ofMinutes(7).plusSeconds(30);
if (minutes > dur.toMinutes()) {
System.out.println("The minutes are longer");
} else {
System.out.println("The minutes are shorter or the same");
}
Output:
The minutes are shorter or the same
If you need to know whether the minutes are strictly shorter, the code will be a bit longer, of course (no joke intended). One way does involve converting the minutes to a Duration in some cases:
if (minutes > dur.toMinutes()) {
System.out.println("The minutes are longer");
} else if (Duration.ofMinutes(minutes).equals(dur)) {
System.out.println("The minutes are the same");
} else {
System.out.println("The minutes are shorter");
}
The minutes are shorter
I really wish the Duration class had had methods isLonger() and isShorter() (even though the names just suggested may not be quite clear when it comes to negative durations). Then I would have recommended converting the minutes to a Duration too as in the accepted answer.
One way, with Duration:
Duration duration = Duration.of(10, ChronoUnit.SECONDS);
int seconds = 5;
System.out.println(duration.getSeconds() - seconds);
Note, that ChronoUnit has a lot of useful constant members, like MINUTES, DAYS, WEEKS, CENTURIES, etc.
Another way, with LocalTime:
LocalTime localTime = LocalTime.of(0, 0, 15); //hh-mm-ss
int seconds = 5;
System.out.println(localTime.getSecond() - seconds);
Related
I have been trying to figured out an algorithm to return a list of time based on a start time and end time and how many loop. For example the start time at 6 am and the end time at 10 pm and the looping number is 5 so I need to return 22-6 = 16 and 16/5 = 3.2 so I need to return
6:00:00
9:20:00
12:40:00
15:60:00
18:20:00
21:40:00
I need to return such these values. (Note, the return value I wrote are not accurate but just for the purpose of demonstration)
The current code:
// List<Time> times(int looping){
long test(){
List<Time> result = new ArrayList<Time>();
String start = "06:00:00";
String finish = "22:00:00";
Time startTime = Time.valueOf(start);
Time endTime = Time.valueOf(finish);
long totalHours = endTime.getTime() - startTime.getTime();
return totalHours;
// return result;
}
Note: the long totalHours return a strange number not 16 and I'm not sure how to loop throw time and return the wanted values.
java.time
This is one of the places where java.time, the modern Java date and time API, excels. The method Duration::dividedBy does just want you want, dividing a span of time into a certain number of chunks.
List<LocalTime> result = new ArrayList<>();
String start = "06:00:00";
String finish = "22:00:00";
LocalTime startTime = LocalTime.parse(start);
LocalTime endTime = LocalTime.parse(finish);
Duration totalTime = Duration.between(startTime, endTime);
int subintervalCount = 5;
Duration subintervalLength = totalTime.dividedBy(subintervalCount);
LocalTime currentTime = startTime;
for (int i = 0; i < subintervalCount; i++) {
result.add(currentTime);
currentTime = currentTime.plus(subintervalLength);
}
System.out.println(result);
This outputs:
[06:00, 09:12, 12:24, 15:36, 18:48]
Where did the strange number of total hours come from?
the long totalHours return a strange number not 16 and I'm not sure
how to loop throw time and return the wanted values.
The Time class doesn’t define a getTime method. Instead you are calling the getTime method of the superclass java.util.Date, another poorly designed and long outdated class that we should no longer use. This getTime retunrs the count of milliseconds since the epoch of 1970-01-01T00:00:00 UTC, something that does not make sense for a time of day. I consider it likely that your subtraction yielded the number of milliseconds rather than the number of hours between your two times.
Edit: In case you’re curious and want to check: 16 hours equals 57 600 000 milliseconds. I obtained the number from TimeUnit.HOURS.toMillis(16).
Link
Oracle tutorial: Date Time explaining how to use java.time.
I'm trying to generate 10 random times within a range of two times, and there is a condition that the times generated cannot have less than 30 minutes between them. So, if i Start at 10:00am and end at 05:00pm, the times between these must be a least 30 minutes between them.
I already can get the random times, but don't know how to put the condition there, any ideas?
public LocalTime between(LocalTime startTime, LocalTime endTime) {
int startSeconds = startTime.toSecondOfDay();
int endSeconds = endTime.toSecondOfDay();
int randomTime = ThreadLocalRandom
.current()
.nextInt(startSeconds, endSeconds);
return LocalTime.ofSecondOfDay(randomTime);
}
i put this in a for loop to get 10 of them
For a good random distribution: Out of the 7 hours between your start of 10:00 and your end of 17:00 (on a 24 hour clock, “military hours”), 4 hours 30 minutes are already reserved for your minimal gaps (9 gaps # 30 minutes minimum). So subtract 4:30 from 7, this gives 2 hours 30 minutes of freedom.
Generate 10 random times within 2 hours 30 minutes, for example the way you already do.
Sort them chronologically.
Add 0 minutes to the first time, 30 minutes to the next, 1 hour to the third, etc. So you will be adding 4 hours 30 minutes to the last time. This will make sure that the gaps become at least 30 minutes each and that the last time is still within the 17:00 end time.
You can use isBefore in LocalTime, so check startTime+30 Min is before result and result is before endTime-30 Min
LocalTime result = LocalTime.ofSecondOfDay(randomTime);
if (startTime.plusMinutes(30).isBefore(result) && result.isBefore(endTime.minusMinutes(30))) {
return result;
}
Probably you can use while loop to loop until it get the valid result
while(true) {
LocalTime result = LocalTime.ofSecondOfDay(ThreadLocalRandom. current().nextInt(startSeconds, endSeconds));
if (startTime.plusMinutes(30).isBefore(result) && result.isBefore(endTime.minusMinutes(30))) {
return result;
}
}
You can not generate truly random numbers with computers, you always have to have some strategy. And if your numbers are truly random then, they can not be aware of each other. So, you can not generate truly random time 30 minutes apart separately. You have to generate them all together. You have to find a minimum distance. And start time and end time must have enough distance to generate the number of random times you want.
You can generate any number of random times by the following method in any given range if they have enough distance -
public List<LocalTime> generateRandomTimes(LocalTime startTime, LocalTime endTime, int n) {
if (n < 0) {
throw new RuntimeException("Must be greater than zero");
}
List<LocalTime> localTimeList = new ArrayList<>();
int startSeconds = startTime.toSecondOfDay();
int endSeconds = endTime.toSecondOfDay();
int minimumDistance = LocalTime.of(0, 30).toSecondOfDay();
int standardDistance = (endSeconds - startSeconds) / n;
if (standardDistance <= minimumDistance) {
throw new RuntimeException("Not enough time distance to generate the required number of random times");
}
int randomRange = (endSeconds - (n * minimumDistance)) / n;
for (int i = 1; i <= 10; i++) {
int nextInt = ThreadLocalRandom
.current()
.nextInt(startSeconds, startSeconds + randomRange);
LocalTime time = LocalTime.ofSecondOfDay(nextInt);
localTimeList.add(time);
startSeconds = nextInt + minimumDistance;
}
return localTimeList;
}
I have a string that contain certain hour ex. 14:34, and now I want to calculate the difference between the current hour ex. 21:36-14:34=7 hours 2 minutes (or something like that.) Can someone explain me how can I do that?
It's very easy: You need to separate the string in terms you can add or substract:
String timeString1="12:34";
String timeString2="06:31";
String[] fractions1=timeString1.split(":");
String[] fractions2=timeString2.split(":");
Integer hours1=Integer.parseInt(fractions1[0]);
Integer hours2=Integer.parseInt(fractions2[0]);
Integer minutes1=Integer.parseInt(fractions1[1]);
Integer minutes2=Integer.parseInt(fractions2[1]);
int hourDiff=hours1-hours2;
int minutesDiff=minutes1-minutes2;
if (minutesDiff < 0) {
minutesDiff = 60 + minutesDiff;
hourDiff--;
}
if (hourDiff < 0) {
hourDiff = 24 + hourDiff ;
}
System.out.println("There are " + hourDiff + " and " + minutesDiff + " of difference");
UPDATE:
I'm rereading my answer and I'm surprised is not downvoted. My fault. I wrote it without any IDE check. So, the answer should be minutes1 and 2 for the minutesDiff and obviously and a check to carry the hour difference if the rest of minutes is negative, making minutes (60+minutesDiff). If minutes is negative, rest another hour to the hourDiff. If hours become negative too, make it (24+hourDiff). Now is fixed.
For the sake of fastness, I'm using a custom function. For the sake of scalability, read Nikola Despotoski answer and complete it with this:
System.out.print(Hours.hoursBetween(dt1, dt2).getHours() % 24 + " hours, ");
System.out.println(Minutes.minutesBetween(dt1, dt2).getMinutes() % 60 + " minutes, ");
I would start by using the .split method to get the string into its two components (minutes and hours) then I would convert both times into minutes by mutliplying the hours by 60 and then adding the minutes
String s = "14:34";
String[] sArr = s.split(",");
int time = Integer.parseInt(sArr[0]);
time *= 60;
int time2 = Integer.parseInt(sArr[1]);
time = time + time2;
do this for both strings and then subtract one from the other. You can convert back to normal time by using something like this
int hours = 60/time;
int minutes = 60%time;
The answer labeled as correct will not work. It does not account for if the first time is for example 3:17 and the second is 2:25. You end up with 1 hour and -8 minutes!
I'm trying to make a timing mechanism using threads, and I'm having a problem in getting the time difference between two Dates, and using that difference to get a current percentage of the time left. Here is the concept I'm trying to prototype:
And here is my implementation:
long startMilisecs = System.currentTimeMillis();
long currentMilisecs;
long endDateMilisecs = getEndDate().getTime();
int diffMillisecs = ((int)(endDateMilisecs - startMilisecs) / 1000) / 60;
int currPerc;
while (startMilisecs <= endDateMilisecs)
{
currentMilisecs = (int) System.currentTimeMillis();
currPerc = ((int)currentMilisecs * 100) / diffMillisecs;
System.out.println(" Current Percentage: " + currPerc);
}
The problem with this code is that the percentage is not starting from 0 but rather in the 20's to 40 percent.
Can you tell me what is wrong with this? and for this problem I have been restricted to using only threads.
check below:
public static int getPercentageLeft(Date start, Date end) {
long now = System.currentTimeMillis();
long s = start.getTime();
long e = end.getTime();
if (s >= e || now >= e) {
return 0;
}
if (now <= s) {
return 100;
}
return (int) ((e - now) * 100 / (e - s));
}
You need to subtract the starting time like this
currPerc = ((currentMilisecs - startMilisecs) * 100) / diffMillisecs;
to get the correct percentage.
The problem is with the System.currentTimeMillis();. Taken from the javadoc:
public static long currentTimeMillis()
Returns the current time in milliseconds. Note that while the unit of
time of the return value is a millisecond, the granularity of the
value depends on the underlying operating system and may be larger.
For example, many operating systems measure time in units of tens of
milliseconds.
See the description of the class Date for a discussion of slight
discrepancies that may arise between "computer time" and coordinated
universal time (UTC).
Returns:
the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
So your current time in milliseconds is based on January 1, 1970 UTC, not on your start date.
You need to calculate current time by subtracting start time from the value that is given by System.currentTimeMillis();.
I am basically formulating your linked image here. Other alternative calculations can also be carried out.
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);