Time Difference when user is late, tracking - java

I want to calculate the difference in minutes between two dates, if this difference is > 0 and < 50 minutes, I show a textview with the next text: "X until limit time" (it's on time, but is close to the limit)
If the difference is < 0 (it's late) the textview should say "X minutes late"
Right now everything work for the first condition, but for the second one, the number sometimes show 740 minutes late or bigger numbers
Date fechaactual = new Date();
long diff = trackingfecha.getTime() - fechaactual.getTime();
long diferenciaminutos = diff / (60 * 1000);
RunneableUpdateUI run = new RunneableUpdateUI();
if(diferenciaminutos < 50) {
if(diferenciaminutos >= 0) {
//Show the minutes close to some specific time
StringBuffer buffer = new StringBuffer();
buffer.append("te quedan ");
String minutes = String.format("%02d", diferenciaminutos);
buffer.append(minutes);
buffer.append(" min");
run.toUpdateValue = buffer.toString();
} else {
//Here is the problem
StringBuffer buffer = new StringBuffer();
String minutes = String.format("%02d", Math.abs(diferenciaminutos));
buffer.append(minutes);
buffer.append(" min tarde");
run.toUpdateValue = buffer.toString();
}
timerHandler.post(run);
}

if (0<=x && x < 50)
{
// x time to reach
}
else
{
if (0> x)
{
// late
}
}
}
where x is your Time Diffrent

Related

Converting String time format of HH:MM:SS (AM/PM) into Seconds

So I have this assignment that is asking us to take in a String format of time in the order of HH:MM:SSAM or HH:SS:MMPM. The constraint is that it cannot run if it is in wrong format, let it be missing any form of the AM or PM, missing a number, or if it is in 24 Hour Format.
I have the whole idea down, however for my statements, it is giving me the error of:
bad operand types for binary operator '>'
incomparable types: String and int
Did I convert them improperly or am I doing something else wrong?
public static void main(String args[]) {
//Test Methods
String fullTime1 = "03:21:36AM";
secondsAfterMidnight(fullTime1);
}
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = Integer.parseInt(units[2]);
int totalSeconds = 0;
if (units[0] > 12 || units[1] > 59 || units[2] > 59) { //1st Error applies to these three, units[0] > 12 units[1] > 59 units[2] > 59
return -1;
} else if (time.equalsIgnoreCase("AM") || time.equalsIgnoreCase("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (time.equalsIgnoreCase("AM") && units[0] == 12) { //2nd Error applies to this units[0] == 12
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
You have already parsed the String values and saved them in the variables hours , minutes, seconds. Then you can use those for the check in the if.
Also the presence of AM?PM in the Integer.parseInt() will cause NumberFormatException to avoid it remove the String part from the number by using regex.
Also for checking the presence of AM/PM you can use String.contains.
Please check the reformatted code below:
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = Integer.parseInt(units[2].replaceAll("[^0-9]", ""));
int totalSeconds = 0;
if (hours > 12 || minutes > 59 || seconds > 59) {
return -1;
} else if (time.contains("AM") || time.contains("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (time.contains("AM") && hours == 12) {
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
Please note that even though you have converted the String to int, you are still comparing String with int. There would also be a RuntimeException when you do this:
int seconds = Integer.parseInt(units[2]);
As units[2] will contain 36AM. So you should be using substring() to remove the "AM/PM" part.
units is of type String and you are trying to compare it with an int hence the compile time error.
You need to convert the String to an int and then compare it, as shown below :
Integer.parseInt(units[0]) > 12
so on and so forth.
Also rather than re-inventing the wheel, you can make use of the already existing java-8's LocalTime to find the number of seconds for a particular time:
public static int secondsAfterMidnight(String time) {
LocalTime localTime = LocalTime.parse(time, DateTimeFormatter.ofPattern("hh:mm:ss a"));
return localTime.toSecondOfDay();
}
I haven't verified your logic to calculate the seconds, but this code has corrections:
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = 0;
String amPm = "";
if ( units[2].contains("AM") || units[2].contains("PM") ||
units[2].contains("am") || units[2].contains("pm") ) {
seconds = Integer.parseInt(units[2].substring(0, 2));
amPm = units[2].substring(2);
}
else {
seconds = Integer.parseInt(units[2]);
}
int totalSeconds = 0;
if (hours > 12 || minutes > 59 || seconds > 59) {
return -1;
} else if (amPm.equalsIgnoreCase("AM") || amPm.equalsIgnoreCase("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (amPm.equalsIgnoreCase("AM") && hours == 12) {
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
java.time
static DateTimeFormatter timeFormatter
= DateTimeFormatter.ofPattern("HH:mm:ssa", Locale.ENGLISH);
public static int secondsAfterMidnight(String time) {
try {
return LocalTime.parse(time, timeFormatter).get(ChronoField.SECOND_OF_DAY);
} catch (DateTimeParseException dtpe) {
return -1;
}
}
Let’s try it out using the test code from your question:
String fullTime1 = "03:21:36AM";
System.out.println(secondsAfterMidnight(fullTime1));
12096
This is the recommended way for production code.
Only if you are doing an exercise training string manipulation, you should use one of the other answers.
Link: Oracle tutorial: Date Time explaining how to use java.time.

calculate elapsed time and display it in Java

There seems to be no easy answer in stackoverflow for this problem. I simply want to get the difference between two Calendar instances and display in HH:mm:ss.SSS
So far, I have
SimpleDateFormat dateFormat = new
SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Calendar start = Calendar.getInstance();
say("start time:"+dateFormat.format(start.getTime()));
and
Calendar ending = Calendar.getInstance();
say("ending time:"+dateFormat.format(ending.getTime()));
long milli = ending.getTime().getTime()
- start.getTime().getTime();
long sec = milli / 1000; // millisec to sec
say("elapsed time: " + sec + "." + milli );
which does work to display the two times.
start time: 2018-03-02 15:44:41.194
*** program runs ***
ending time:2018-03-02 15:44:41.198
elapsed time: 0.4
But shouldn't it be saying 0.004 seconds?
And PLEASE no JodaTime answers. This shop does not support that.
Instant start = Instant.now();
And
Instant end = Instant.now();
long milli = ChronoUnit.MILLIS.between(start, end);
System.out.format(Locale.ENGLISH, "elapsed time: %.3f%n", milli / 1000.0);
On my computer this printed
elapsed time: 0.004
Formatting with String.format or System.out.format() also works with your way of measuring the milliseconds, of course.
Using Java 9 you can (at least on some computers) have more decimals if you want:
System.out.println("elapsed time: "
+ ChronoUnit.NANOS.between(start, end) / (double) TimeUnit.SECONDS.toNanos(1));
I got
elapsed time: 0.003739
I wrote a little function for you, it returns a number as a string filled with as many "0" as you want.
public String getStringNumber(long number, int displaySize) {
String str = new String();
int length = String.valueOf(number).length();
while (length++ < displaySize)
str += "0";
str += number;
return str;
}
Now you can just replace in your code
say("elapsed time: " + sec + "." + getStringNumber(milli, 4));
I finally arrived on this solution. It is awkward and not very elegant, but it works.
Calendar ending = Calendar.getInstance();
say("ending time:"+dateFormat.format(ending.getTime()));
long milli = ending.getTime().getTime()
- start.getTime().getTime();
long hrs = TimeUnit.MILLISECONDS.toHours(milli) % 24;
long
min = TimeUnit.MILLISECONDS.toMinutes(milli) % 60;
long sec
= TimeUnit.MILLISECONDS.toSeconds(milli) % 60;
long mls = milli % 1000;
String elaps =
String.format("%02d:%02d:%02d.%03d", hrs,
min, sec, mls);
say("Elapsed time: " + elaps);
Here is the explanation: I convert the two Calendar variables to long, and subtract. Then I format the Long to a string in format hh:mm:ss.SSS which is what I wanted in the first place.
Here is the output
ending time:2018-03-05 15:07:17.923
Elapsed time: 00:01:15.964
Okay, so, simply off the top of my head, without trying to perform anything kind of fancy, you could make use of the Java 8 date/time API, which provides the capability to calculate the different between two points in time.
So, taking your input, and running it through the code below, it outputs
2018-03-02T15:44:41.194
2018-03-02T15:44:41.198
0.004
Now, personally, I'd take the concept and simply create a DurationFormatter which could take a Duration and spit out your required format, but the idea here is to give you a jumping point to start from.
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Test {
public static void main(String[] args) {
String startTime = "2018-03-02 15:44:41.194";
String endTime = "2018-03-02 15:44:41.198";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
LocalDateTime startDateTime = LocalDateTime.parse(startTime, formatter);
LocalDateTime endDateTime = LocalDateTime.parse(endTime, formatter);
System.out.println(startDateTime);
System.out.println(endDateTime);
Duration duration = Duration.between(startDateTime, endDateTime);
long hours = duration.toHours();
duration = duration.minusHours(hours);
long mins = duration.toMinutes();
duration = duration.minusMinutes(mins);
long secs = duration.getSeconds();
duration = duration.minusSeconds(secs);
long millis = duration.toMillis();
StringBuilder sb = new StringBuilder(12);
if (hours > 0) {
sb.append(pad(hours, 2));
}
if (mins == 0 && sb.length() > 0) {
sb.append(":00");
} else if (mins > 0) {
if (hours > 0) {
sb.append(":");
}
sb.append(pad(mins, 2));
}
if (secs == 0 & sb.length() > 0) {
sb.append(":00");
} else if (secs > 0) {
if (mins > 0) {
sb.append(":");
}
sb.append(pad(secs, 2));
}
if (millis == 0 & sb.length() > 0) {
sb.append(".00");
} else if (millis > 0) {
if (secs > 0 || sb.length() > 0) {
sb.append(".");
} else if (sb.length() == 0) {
sb.append("0.");
}
sb.append(pad(millis, 3));
}
System.out.println(sb.toString());
}
public static String pad(long value, long length) {
return String.format("%0" + length + "d", value);
}
}
Now, if we change the input to something like...
String startTime = "2018-03-02 15:44:41.194";
String endTime = "2018-03-08 15:44:41.198";
It outputs
144:00:00.004
Or if we use
String startTime = "2018-03-02 15:44:41.194";
String endTime = "2018-03-08 15:15:41.198";
It outputs
143:31:00.004
Or
String startTime = "2018-03-02 15:44:41.194";
String endTime = "2018-03-08 15:15:50.198";
It outputs
143:31:09.004
Or
2018-03-02T15:44:41.194
2018-03-02T15:50:41.194
It outputs
06:00.00
... to me, this is where it gets weird, technically it's correct (6 mins), but from the format, it's hard to deduce exactly what it means
This is where I might be tempted to use something more like String.format("%02d:%02d:%02d.%04d", hours, mins, secs, millis) which will output 00:06:00.0000, but that all comes do to you needs. You will need to decide how best to take the raw information and present it based on your needs, but there are a couple of different ideas

Parsing user time input in Java/GWT

What is the best way to parse time that a user typed in a text field in GWT? Default time formats require users to enter time exactly as the time format for locale specifies it.
I want to be more flexible as there are many different ways users can enter time. For example, entries like "8", "8p", "8pm", "8.15pm", "13:15", "1315", "13.15" should be valid.
I ended up with my own method that I want to share. This method returns time in milliseconds, which can be displayed using any data formats for the selected locale.
Any suggestions to improve it are highly appreciated.
EDIT: Improved following suggestions in comments.
public static Long parseTime(String value) {
// ";" is a common typo - we are not punishing users for it
value = value.trim().toLowerCase().replace(";", ":");
RegExp time12 = RegExp.compile("^(1[012]|[1-9])([:.][0-5][0-9])?(\\s)?(a|p|am|pm)?$");
RegExp time24 = RegExp.compile("^(([01]?[0-9]|2[0-3])[:.]?([0-5][0-9])?)$");
if (time12.test(value) || time24.test(value)) {
String hours = "0", minutes = "0";
if (value.contains(":") || value.contains(".")) {
String[] values = value.split("[:.]");
hours = values[0];
minutes = values[1].substring(0, 2);
} else {
// Process strings like "8", "8p", "8pm", "2300"
if (value.contains("a")) {
hours = value.substring(0, value.indexOf("a")).trim();
} else if (value.contains("p")) {
hours = value.substring(0, value.indexOf("p")).trim();
} else if (value.length() < 3) {
hours = value;
} else {
hours = value.substring(0, value.length() - 2);
minutes = value.substring(value.length() - 2);
}
}
if (value.contains("a") && hours.equals("12")) {
// 12am is actually zero hours
hours = "0";
}
Long time = (Long.valueOf(hours) * 60 + Long.valueOf(minutes)) * 60 * 1000;
if (value.contains("p") && !hours.equals("12")) {
// "pm" adds 12 hours to the total, except for 12pm
time += 12 * 60 * 60 * 1000;
}
return time;
}
return null;
}

String split with parseInt in Java

We are asked to build a constructor for a Stopwatch that takes a string in the format of "##:##:###" and updates minutes, seconds and milliseconds (private instance variables) accordingly. For example, "1:21:300" indicates 1 minute 21 seconds 300 milliseconds.
So I am trying to use string.split() paired with parseInt to update values. However, the program will not compile. My constructor has the correct syntax according to eclipse, but there is something wrong with what I am doing. I have never actually used split nor parseInt, so I could be using these 100% wrong. Thank you.
public StopWatch(String startTime){
String [] timeArray = startTime.split(":");
if(timeArray.length == 2){
this.minutes = Integer.parseInt(timeArray[0]);
this.seconds = Integer.parseInt(timeArray[1]);
this.milliseconds = Integer.parseInt(timeArray[2]);
}
else if(timeArray.length == 1){
this.minutes = 0;
this.seconds = Integer.parseInt(timeArray[1]);
this.milliseconds = Integer.parseInt(timeArray[2]);
}
else if(timeArray.length == 0){
this.minutes = 0;
this.seconds = 0;
this.milliseconds = Integer.parseInt(timeArray[2]);
}
else{
this.minutes = 0;
this.seconds = 0;
this.milliseconds = 0;
}
}
P.S. Junit test says "ComparisonFailue: expected 0:00:000 but was 20:10:008" when trying to do:
s = new StopWatch("20:10:8");
assertEquals(s.toString(),"20:10:008");
As mentioned in other answers, the lengths are off by 1 each each, but the index's you are using in if block are also off; eg. if the length is 1, the only index available is 0, if the length is 2, the index's available are 0 and 1.
Thus you get a constructor that looks like:
class StopWatch {
int minutes;
int seconds;
int milliseconds;
public StopWatch(String startTime) {
String[] timeArray = startTime.split(":");
if (timeArray.length == 3) {
this.minutes = Integer.parseInt(timeArray[0]);
this.seconds = Integer.parseInt(timeArray[1]);
this.milliseconds = Integer.parseInt(timeArray[2]);
} else if (timeArray.length == 2) {
this.minutes = 0;
this.seconds = Integer.parseInt(timeArray[0]);
this.milliseconds = Integer.parseInt(timeArray[1]);
} else if (timeArray.length == 1) {
this.minutes = 0;
this.seconds = 0;
this.milliseconds = Integer.parseInt(timeArray[0]);
} else {
this.minutes = 0;
this.seconds = 0;
this.milliseconds = 0;
}
}
}
Replace your toString() method with:
public String toString() {
String paddedMinutes = String.format("%02d", this.minutes);
String paddedSeconds = String.format("%02d", this.seconds);
String paddedMilliseconds = String.format("%03d", this.milliseconds);
return paddedMinutes + ":" + paddedSeconds + ":" + paddedMilliseconds;
}
Though Java arrays are zero-based, their lengths simply count the number of elements.
So, {1,2,3}.length will return 3.
As your code is written now you will be getting ArrayOutOfBounds exceptions left and right.
if(timeArray.length == 2){
should be:
if(timeArray.length == 3){
and so on.
20:10:8 split by : will give you a length of 3 ;)

How to sum minutes in array if their format is string?

I have an string array that includes some minutes like "00:05", "00:30", "00:25" etc. I want to sum the values as time format? Can anyone help me how do I do this?
Total time in minutes:
int sum = 0;
final String[] mins = new String[] { "00:05", "00:30", "00:25" };
for (String str : mins) {
String[] parts = str.split(":");
sum += Integer.parseInt(parts[1]);
}
System.out.println(sum);
You don't specify exactly how you want this output formatted.
If there may be hour elements as well, then replace the second line of the loop with this:
sum += (Integer.parseInt(parts[0]) * 60) + Integer.parseInt(parts[1]);
I'll go for quick and dirty
Split each String on the ":"
Convert both parts to integer
Multiply the first time by 60 to convert hours to minutes, and add the second part
Do this for each value in your array, and count them together
This results in the total time in minutes, which you can convert to whatever format you like
You could substring it, and then call Integer.parseInt on the result. For the hours part, do the same and multiply it by 60.
Split the strings on ':', pars the values as ints and add 'em up.
this is my suggestion. Neither compiled, ran, tested, nor guaranteed.
long seconds = 0;
for ( String min : minutes )
{
seconds += Integer.parseInt(min.substring(0,1))*60 + Integer.parseInt(min.substring(3,4));
}
return new Date ( seconds / 1000 ) ;
An object oriented approach:
public static TimeAcumm sum(final String[] times) {
final TimeAcumm c = new TimeAcumm();
for (final String time : times) {
c.incrementFromFormattedString(time);
}
return c;
}
public class TimeAcumm {
private int hours = 0;
private int minutes = 0;
private int seconds = 0;
public int getHours() {
return hours;
}
public int getMinutes() {
return minutes;
}
public int getSeconds() {
return seconds;
}
public void incrementFromFormattedString(final String time) {
final String[] parts = time.split(":");
this.minutes += Integer.parseInt(parts[0]);
this.seconds += Integer.parseInt(parts[1]);
validate();
}
private void validate() {
if (this.minutes > 59) {
this.hours++;
this.minutes -= 60;
}
if (this.seconds > 59) {
this.minutes++;
this.seconds -= 60;
}
}
#Override
public String toString() {
final String s = hours + "H:" + minutes + "M:" + seconds + "S";
return s;
}
}

Categories

Resources