Time comparision in java - java

I just get the time in HH:MM format and check if it is greater than 9:30 then count c is increased as 1.I just did for a single user input time.But i need to get multiple times from user and compare.If it is greater than 9:30 then increment the count values.First get n value and then get n no of time from user.How can i change my code to get the n no of time and compare that?
Scanner input = new Scanner(System.in);
String time = input.nextLine();
System.out.println();
int c=0;
String time2 = "9:30";
DateFormat sdf = new SimpleDateFormat("hh:mm");
Date d1 = sdf.parse(time);
Date d2 = sdf.parse(time2);
if(d1.after(d2))
{
c++;
}
System.out.println(c);

This should do it. It is a basic implementation, you can optimize it the way you like.
EDIT (with explanation comments):
Scanner sc = new Scanner(System.in);
// accept user input for N
System.out.println("Enter N");
int n = sc.nextInt();
String time;
int c = 0;
// store the DateFormat to compare the user inputs with
String time2 = "9:30";
DateFormat sdf = new SimpleDateFormat("hh:mm");
Date d2 = null;
try {
d2 = sdf.parse(time2);
} catch (ParseException e) {
e.printStackTrace();
}
// iterate for N times, asking for a user input N times.
for (int i = 0; i < n; i++) {
// get user's input to parse and compare
System.out.println("Enter Time");
time = sc.next();
Date d1 = null;
try {
d1 = sdf.parse(time);
} catch (ParseException e) {
e.printStackTrace();
}
if (d1.after(d2)) {
c++;
}
}
System.out.println(c);
I have not changed much of your code, just added a loop and did the same thing for N times. To quote from the comments above, "loops are your friend".
Hope this helps. Good luck. Comment if you have any further questions.

Use for loop to iterate over the list of time. Also, you do not need n value, you can directly get it with list.size()
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html

Related

Comma Separated User input in java

Below are the inputs:
Event Name, Date, No. of attendees
Catering party, 01/01/2018, 100
Wedding,24/01/2018,500
Bike Stunts show, 06/01/2018, 300
Below is the code:
public static void main(String[] args) throws ParseException {
//SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
List<Event> events = new ArrayList<>();
for (int i = 0; i < n; i++) {
sc.next();
//String line=sc.nextLine();
String parts[] = sc.nextLine().split(", ");
//StringTokenizer st = new StringTokenizer(line,", ");
//int j=0;
//while(st.hasMoreTokens()) {
//System.out.println(st.nextToken());
//parts[j]=st.nextToken();
//j++;
//}
//System.out.println(j);
//String[] inputs = sc.nextLine().split(", ");`
for (String data : parts) {
System.out.println(data);
}
String name = parts[0].trim();
String date = parts[1].trim();
String attendee = parts[2].trim();
int count = Integer.parseInt(attendee);
events.add(new Event(name, date, count));
}
}
Below is the Error:
3Number of inputs
Catering party, 01/01/2018, 100
party
01/01/2018
100
Wedding, 24/01/2018, 500
24/01/2018
500
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at Main.main(Main.java:74)
I have tried both String Tokenizer and split method but as you can see in the error that I am not able to take the input in correct format. Please help me to know what is wrong in my code.
Hello Everyone! After getting stuck with sc.next() and sc.nextLine() I have used BufferedReader to take the input. And it is working below is the code:
for (int i = 0; i < n; i++) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line=reader.readLine();
String parts[] = line.trim().split(",");
for (String data : parts) {
System.out.println(data);
}
name = parts[0].trim();
date = parts[1].trim();
attendee = parts[2].trim();
count = Integer.parseInt(attendee);
events.add(new Event(name, date, count));
}
You may have noticed that, from your debug logs, you're not getting the correct output even before the IndexOutOfBoundsException. This is due to the sc.next(); that you added at the beginning of the for loop. This is also the reason behind the exception in the second iteration.
What is actually happening
The compiler is reading the first non-space seperated integer characters through sc.nextInt();
Then, in the for loop, you are reading the next non-space seperated string through sc.next();. In your case, that's the word "Catering".
After that, the compiler is reading the rest of the line as "party, 01/01/2018, 100" and operating on it. This is why you are only getting the word "party" in the sysout rather than "Catering party".
The same happens for the next line of input, except this time the entirety of "Wedding," is considered a single sc.next() so you end up with "24/01/2018, 500" and an IndexOutOfBoundsException.
The only reason the first line worked is because it had two words in the first argument so it didn't affect the split array size.
Solution
I would recommend you try to fix it yourself before reading this next part. Consider using the debugger! It's a very helpful tool.
after reading the initial number input sc.nextInt() you should add sc.nextLine(); so that the compiler understands that the previous line is finished and the next read should be on a new line.
You should remove sc.next(); as this accomplishes nothing. (I'm guessing you added this to try and solve the issue where the compiler wasn't reading the next line as mentioned previously).
Finally, I would recommend you split on , rather than , since you're trimming the strings anyway.
#alankar's solution
I have used BufferedReader and now I am able to take input.
for (int i = 0; i < n; i++) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line=reader.readLine();
String parts[] = line.trim().split(",");
for (String data : parts) {
System.out.println(data);
}
name = parts[0].trim();
date = parts[1].trim();
attendee = parts[2].trim();
count = Integer.parseInt(attendee);
events.add(new Event(name, date, count));
}
try to remove white spaces before splitting your input, to make sure there is no white spaces that can affect your separator, also you have to check if the user has entered three fields separated by comma. Here's an example:
public static void main(String[] args) throws ParseException {
//SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
List<Event> events = new ArrayList<>();
for (int i = 0; i < n; i++) {
sc.next();
//String line=sc.nextLine();
String parts[] = sc.nextLine().trim().split(",");
if (parts.length != 3) {
throw new IllegalArgumentException("Error: Input must have 3 parts separated by comma");
}
String name = parts[0];
String date = parts[1];
String attendee = parts[2];
int count = Integer.parseInt(attendee);
events.add(new Event(name, date, count));
}
}

NumberFormatException when trying to read dates from console input

So I'm trying to find the latest date from a list of dates, but I keep getting a NumberFormatException. Is there any way of resolving this?
import java.util.*;
public class Date
{
private String date;
private int day;
private int month;
private int year;
public Date(String date)
{
String [] newDate = date.split(" ");
this.day = Integer.parseInt(newDate[0]);
this.month = Integer.parseInt(newDate[1]);
this.year = Integer.parseInt(newDate[2]);
}
public boolean isOnOrAfter(Date other)
{
if(this.day < other.day)
{
return true;
}
else if(this.day == other.day && this.month < other.month)
{
return true;
}
else if(this.day == other.day && this.month == other.month && this.year < other.year)
{
return true;
}
return false;
}
public String toString()
{
return day + "/" + month + "/" + year;
}
public static void main(String [] args)
{
Scanner in = new Scanner(System.in);
System.out.print("How many dates: ");
int num = in.nextInt();
System.out.println("Enter " + num + " dates: ");
String [] dates = new String[num];
for(int i = 0; i < dates.length; i++)
{
dates[i] = in.nextLine();
}
Date latest = new Date(dates[0]);
for(int i = 0; i < dates.length; i++)
{
Date newDates = new Date(dates[i]);
if(latest.isOnOrAfter(newDates))
{
latest = newDates;
}
}
System.out.println(latest);
}
}
I think its just a tiny problem, but I can't seem to find it. Thanks in advance.
I have a method that checking for the latest date, the logic of the code seems fine to me, if you see any problems in the logic, let me know.
The dates will be input one line at a time, for example:
1 1 1890
1 1 2000
2 1 2000
30 12 1999
The output should be 2/1/2000.
There are two reasons for the NumberFormatException here:
1.You have multiple spaces in your input between the day, month and the year.
2. Scanner's nextInt does not consume the newline. Hence you need to include a dummy nextLine after it. You can read more about this here.
int num = in.nextInt();
in.nextLine(); //To consume the new line after entering the number of dates
System.out.println("Enter " + num + " dates: ");
String [] dates = new String[num];
...
NumberFormatException is caused by Integer.parseInt() trying to parse string that is not an integer.
Your example input contains consecutive spaces and if you split input by space and there are multiple consecutive spaces in the input the resulting array will contain empty strings. Integer.parseInt() is trying to parse one of these empty Strings and that is causing the exception.
instead of
String [] newDate = date.split(" ");
use
String [] newDate = date.split(" +");
This will consider multiple spaces as a split token and return only the non space characters.

How to convert military time integer to standard time string

So I'm trying to write a program that tells a user what bus they can take to get to their class. I have one issue at the moment: I want to have the user pass an int to compare with an ArrayList of int values to tell them if they can catch that bus.
However, I'd like to convert the output to a 12-hour type string but I can't figure out an effective way to do it! Here's my code so far.
package bus;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
public class busSchedule {
public static void main(String[]args){
int classTime = 0;
Scanner scnr = new Scanner(System.in);
System.out.print("What time do you have to be in class?: ");
classTime = scnr.nextInt();
for(int i = 0; i < AB.toCampus.size() - 1; ++i){
if(classTime > AB.toCampus.get(i)){
String timeString = Integer.toString(AB.toCampus.get(i));
DateFormat f2 = new SimpleDateFormat("h:mm aa");
String newTime = f2.format(timeString).toLowerCase();
System.out.println("You can take the " + AB.line + " line at " + newTime + " to get to class.");
}
}
}
}
I also have the class AB which is the name of the line. It follows:
package bus;
import java.util.ArrayList;
import java.util.Arrays;
public class AB {
static String line = "A-B";
static ArrayList<Integer> toCampus = new ArrayList<Integer>(
Arrays.asList(623, 1234, 1734, 2100)
);
}
The way it is, the output only prints 4:00 pm over and over.
Any help is appreciated!
You could simply parse the military time to a time class and then format it to your desired output, for example...
ArrayList<Integer> toCampus = new ArrayList<>(
Arrays.asList(623, 1234, 1734, 2100)
);
for (int time : toCampus) {
String value = String.format("%04d", time);
LocalTime lt = LocalTime.parse(value, DateTimeFormatter.ofPattern("HHmm"));
System.out.println(DateTimeFormatter.ofPattern("hh:mm a").format(lt));
}
Which outputs
06:23 AM
12:34 PM
05:34 PM
09:00 PM
Now, because your data is actually sorted, you can use Collections.binarySearch to find matches, for example...
ArrayList<Integer> toCampus = new ArrayList<>(
Arrays.asList(623, 1234, 1734, 2100)
);
Scanner scnr = new Scanner(System.in);
System.out.print("What time do you have to be in class?: ");
int classTime = scnr.nextInt();
int index = Collections.binarySearch(toCampus, classTime);
System.out.println(index);
if (index < 0) {
index = Math.abs(index) - 1;
}
if (index > 0 && index <= toCampus.size()) {
int time = toCampus.get(index - 1);
String value = String.format("%04d", time);
LocalTime lt = LocalTime.parse(value, DateTimeFormatter.ofPattern("HHmm"));
System.out.println(DateTimeFormatter.ofPattern("hh:mm a").format(lt));
} else {
System.out.println("Go back to bed");
}
When Collections.binarySearch can't find a match, it will return "-(insertion point) - 1", this tells us where out item would have appeared, had it been in the List.
This allows us to make some decisions about which value in the list is most appropriate.
For example, if we enter 630, the binarySearch will return -2, add 1 for the offset, which gives us -1, convert it to a positive number and that would 1. Now, obviously the element at 1 is 1234, but if we take the previous one, it returns 623!

compareTo cannot be applied to java.util.Date (Java)

I am writing an appointment program in Java and am coming across an error which is as follows :
AppointmentNew.java:68: unreported exception java.text.ParseException; must be caught or declared to be thrown
Date lowDate = sdf.parse(stdin.nextLine());
^
AppointmentNew.java:70: unreported exception java.text.ParseException; must be caught or declared to be thrown
Date highDate = sdf.parse(stdin.nextLine());
^
AppointmentNew.java:77: unreported exception java.text.ParseException; must be caught or declared to be thrown
Date newCurrentDate = sdf.parse(currentDate);
This program is suppose to allow the user to make new appointments, when they do that they are then able to input a date and description (they can do this as many times as they want), after that they can then pick a range of dates for the program to print out (it is suppose to print out the appointments in the date range they provided". This is where my error occurs...
Here is the code I have :
import java.util.*;
import java.text.SimpleDateFormat;
import java.util.Date;
public class AppointmentNew
{
public static void main (String[] args)
{
ArrayList<String> list = new ArrayList<String>();
Scanner stdin = new Scanner(System.in);
String choice = "";
int choiceNum = 0;
String date = "";
String descrip = "";
int type = 0;
String typeChose = "";
System.out.println("Welcome to Appointment App!\n");
System.out.println("\t============================");
do
{
System.out.print("\n\tMake Choice (1: New, 2: Print Range, 3: Print All, 4: Quit) ");
choice = stdin.nextLine();
choiceNum = Integer.parseInt(choice);
if (choiceNum == 1)
{
System.out.print("\n\n\tEnter New Appointment Date in mm/dd/yyyy format: ");
date = stdin.nextLine();
System.out.print("\n\n\tEnter New Appointment Description: ");
descrip = stdin.nextLine();
System.out.print("\n\n\tEnter Type (1 = Once, 2 = Daily, 3 = Monthly): ");
type = stdin.nextInt();
stdin.nextLine();
if (type == 1)
{
Once once = new Once(date, descrip);
typeChose = "One-Time";
}
else if (type == 2)
{
Daily daily = new Daily(date, descrip);
typeChose = "Daily";
}
else
{
Monthly monthly = new Monthly(date, descrip);
typeChose = "Monthly";
}
String stringToAdd = "";
stringToAdd = (date + " : \"" + descrip + "\", " + typeChose);
list.add(stringToAdd);
System.out.println("\n\n\tNew " + typeChose + " Appointment Added for " + date + "\n");
System.out.println("\t============================\n");
}
if (choiceNum == 2)
{
System.out.print("\n\n\tEnter START Date in mm/dd/yyyy format: ");
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
Date lowDate = sdf.parse(stdin.nextLine());
System.out.print("\n\n\tEnter END Date in mm/dd/yyyy format: ");
Date highDate = sdf.parse(stdin.nextLine());
for(int i = 0; i < list.size(); i++)
{
int dateSpot = list.get(i).indexOf(" ");
String currentDate = list.get(i);
currentDate.substring(0, dateSpot);
Date newCurrentDate = sdf.parse(currentDate);
if (newCurrentDate.compareTo(lowDate) >= 0 && newCurrentDate.compareTo(highDate) <= 0)
{
System.out.println("\n\t" + list.get(i));
}
}
}
if (choiceNum == 3)
{
for(int i = 0; i < list.size(); i++)
{
System.out.println("\n\t" + list.get(i));
}
}
}while (choiceNum != 4);
}
}
The problem is that you're trying to compare a string to a date. What does that even mean?
You should convert the String to a Date (e.g. with SimpleDateFormat) - or ideally, use Joda Time - and then compare the values when you've got them both as the same type.
EDIT: As noted in comments, this isn't what you want either:
SimpleDateFormat sdf = new SimpleDateFormat("mm/dd/yyyy");
mm means minutes in SimpleDateFormat, not months. You want MM/dd/yyyy instead. See the SimpleDateFormat documentation for more details.
currentDate.compareTo(lowDate)
currentDate is String and lowDate is Date. You are trying compareTo on two different things.
Convert currentDate to Date object and then call compareTo();
It is normal, you compare a object of Type Date with a String. Convert your String to a Date with your SimpleDateFormat (or with another format) and you will able to compare both objects.
Date correctCurrentDate = sdf.parse(currentDate);
To avoid to add try/catch in test program, I generally wrote the main method like :
public static void main (String[] args) throws Exception
Of course, for program that run in production, you should use try/catch where you can handle the exception. But it is annoying for a test program.

Find next character in a string?

I have a java programming assignment where you have to input a date on a single line and it gives you a numerology (horoscope-like) report based on the date. It is assumed that the user will enter a formatted date, separated with spaces.
I can retrieve the month, day, and year of the input by using in.nextInt(). However, I also have to check that the user used a correct separating character for each part of the date, which means I just have to check whether the user used forward slashes.
When looking at my code below, I currently use charAt() to find the separating characters. The problem is that the date won't always be 14 characters long. So a date in the form of 10 / 17 / 2004 is 14 characters long, but a date of 4 / 7 / 1992 is only 12 characters long, meaning that "slash1" won't always be in.charAt(3), in the latter situation it would be in.charAt(2).
Does java have a method that allows something like in.nextChar()? I know that it doesn't, but how could I just find a next character in the date?
EDIT: I forgot to reflect this originally, but my professor said that we are NOT allowed to use the String.split() method, for some reason. The thing is, I get the month, day, and year perfectly fine. I just need to check that the person used a forward slash to separate the date. If a dash is entered, the date is invalid.
public void getDate()
{
char slash1, slash2;
do
{
System.out.print("Please enter your birth date (mm / dd / yyyy): ");
Scanner in = new Scanner(System.in);
String date = in.nextLine();
month = in.nextInt();
day = in.nextInt();
year = in.nextInt();
slash1 = date.charAt(3);
slash2 = date.charAt(8);
} while (validDate(slash1, slash2) == false);
calcNum();
}
you could consider to split the input date string with " / ", then you get a String array. the next step is converting each string in that array to int.
I would use Scanner just to get a line. Then split() the line on whitespace and check the fields:
import java.util.Scanner;
import java.util.regex.Pattern;
public class GetDate {
int month, day, year;
public static void main(String[] args)
{
GetDate theApp = new GetDate();
theApp.getDate();
}
public void getDate()
{
String date;
do
{
System.out.print("Please enter your birth date (mm / dd / yyyy): ");
Scanner in = new Scanner(System.in);
date = in.nextLine();
} while (validDate(date) == false);
calcNum();
}
boolean validDate(String date)
{
// split the string based on white space
String [] fields = date.split("\\s");
// must have five fields
if ( fields.length != 5 )
{
return false;
}
// must have '/' separators
if ( ! ( fields[1].equals("/") && fields[3].equals("/") ) )
return false;
// must have integer strings
if ( ! ( Pattern.matches("^\\d*$", fields[0]) &&
Pattern.matches("^\\d*$", fields[2]) &&
Pattern.matches("^\\d*$", fields[4]) ) )
return false;
// data was good, convert strings to integer
// should also check for integer within range at this point
month = Integer.parseInt(fields[0]);
day = Integer.parseInt(fields[2]);
year = Integer.parseInt(fields[4]);
return true;
}
void calcNum() {}
}
Rather than thinking about what characters are used as separators, focus on the content you want, which is digits.
This code splits on non digits, do it doesn't matter how many digits are in each group or what characters are used as separators:
String[] parts = input.split("\\D+");
It's also hardly any code, so there's much less chance for a bug.
Now that you have the numerical parts in the String[], you can get on with your calculations.
Here's some code you could use following the above split:
if (parts.length != 3) {
// bad input
}
// assuming date entered in standard format of dd/mm/yyyy
// and not in retarded American format, but it's up to you
int day = Integer.parseInt(parts[0];
int month = Integer.parseInt(parts[1];
int year = Integer.parseInt(parts[2];
Look ahead in the stream to make sure it contains what you expect.
private static final Pattern SLASH = Pattern.compile("\\s*/\\s*");
static SomeTypeYouMadeToHoldCalendarDate getDate() {
while (true) { /* Might want to give user a way to quit. */
String line =
System.console().readLine("Please enter your birth date (mm / dd / yyyy): ");
Scanner in = new Scanner(line);
if (!in.hasNextInt())
continue;
int month = in.nextInt();
if (!in.hasNext(SLASH)
continue;
in.next(SLASH);
...
if (!validDate(month, day, year))
continue;
return new SomeTypeYouMadeToHoldCalendarDate(month, day, year);
}
}
This uses Scanner methods to parse:
import java.util.Scanner;
import java.util.InputMismatchException;
public class TestScanner {
int month, day, year;
public static void main(String[] args)
{
TestScanner theApp = new TestScanner();
theApp.getDate();
theApp.calcNum();
}
public void getDate()
{
int fields = 0;
String delim1 = "";
String delim2 = "";
Scanner in = new Scanner(System.in);
do
{
fields = 0;
System.out.print("Please enter your birth date (mm / dd / yyyy): ");
while ( fields < 5 && in.hasNext() )
{
try {
fields++;
switch (fields)
{
case 1:
month = in.nextInt();
break;
case 3:
day = in.nextInt();
break;
case 5:
year = in.nextInt();
break;
case 2:
delim1 = in.next();
break;
case 4:
delim2 = in.next();
break;
}
}
catch (InputMismatchException e)
{
System.out.println("ERROR: Field " + fields + " must be an integer");
String temp = in.nextLine();
fields = 6;
break;
}
}
} while ( fields != 5 || validDate(delim1, delim2) == false);
in.close();
System.out.println("Input date: " + month + "/" + day + "/" + year);
}
boolean validDate(String delim1, String delim2)
{
if ( ( ! delim1.equals("/") ) || ( ! delim2.equals("/") ) )
{
System.out.println("ERROR: use '/' as the date delimiter");
return false;
}
if ( month < 1 || month > 12 )
{
System.out.println("Invalid month value: " + month);
return false;
}
if ( day < 1 || day > 31 )
{
System.out.println("Invalid day value: " + day);
return false;
}
if ( year < 1 || year > 3000 )
{
System.out.println("Invalid year: " + year);
return false;
}
return true;
}
void calcNum()
{
}
}

Categories