I realize this has been asked a lot. I did actually look. I've spent hours looking around and trying to figure this out. I'm supposed to be making a program that stores what amounts to a list of appointments in a database, with a description, date, start time, and end time. It has to take input from the user to add or cancel appointments, so as far as I know that means I need to convert a string to a date.
These are my imports:
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Time;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Scanner;
As you can see, no java.util.Date there. Here is the bit where I'm getting the error:
private static java.sql.Date getDay()
{
Scanner in = new Scanner(System.in);
String input;
Date apptDay = null;
DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
java.sql.Date sqlDate;
System.out.println("\nPlease enter the date of the appointment, format: yyyy/mm/dd");
while(apptDay == null)
{
try
{
input = in.next();
apptDay = (Date) df.parse(input);
}
catch(ParseException e)
{
System.out.println("Please enter a valid date! Format is yyyy/mm/dd");
}
}
sqlDate = new Date(apptDay.getTime());
return sqlDate;
}
I've added java.sql.Dates to it and mucked about with it a bunch trying to get it to work, but it's still giving me this:
Exception in thread "main" java.lang.ClassCastException: java.util.Date cannot be cast to java.sql.Date
at Calendar.getDay(Calendar.java:47)
Any ideas on what I'm doing wrong or how to make this work would be very much appreciated.
Edit: I thought perhaps it would help if I added the bit of code that is calling this so maybe it will be more clear how I am trying to use it, so here is the addAppointment() method, so you can see where getDay() is being called and where it's going.
public static void addAppointment() throws SQLException
{
//get the info
String desc = getDesc();
java.sql.Date apptDay = getDay();
Time[] times = getTime();
Time startTime = times[0];
Time endTime = times[1];
int key;
Connection conn = SimpleDataSource.getConnection(); //connect to the database
try
{
PreparedStatement max = conn.prepareStatement("SELECT MAX(ID) FROM Calendar");
ResultSet result = max.executeQuery();
key = result.getInt("ID") + 1;
PreparedStatement stat = conn.prepareStatement(
"INSERT INTO Calendar " +
"VALUES (?, ?, ?, ?, ?)");
stat.setInt(1, key);
stat.setString(2, desc);
stat.setDate(3, apptDay);
stat.setTime(4, startTime);
stat.setTime(5, endTime);
stat.execute();
System.out.println("\nAppointment added!\n");
}
finally
{
conn.close(); //finished with the database
}
}
It would be much simpler to change the input format to yyyy-MM-dd and use java.sql.Date.valueOf(String date) method which converts a string in the above format to a java.sql.Date value directly.
This should work:
private static java.sql.Date getDay()
{
Scanner in = new Scanner(System.in);
String input;
Date apptDay = null;
DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
java.sql.Date sqlDate;
System.out.println("\nPlease enter the date of the appointment, format: yyyy/mm/dd");
while(apptDay == null)
{
try
{
input = in.next();
apptDay = (Date) df.parse(input);
}
catch(ParseException e)
{
System.out.println("Please enter a valid date! Format is yyyy/mm/dd");
}
}
sqlDate = new java.sql.Date(apptDay.getTime());
return sqlDate;
}
java.sql.Date and java.util.Date are two different Classes. You need to convert the sql date into util date which is compatible with Calendar.
Date jDate = new Date(sqlDate.getTime());
and vice-versa
java.sql.Date sqlDate = new java.sql.Date(jDate.getTime());
The following statement caused the error:
apptDay = (java.sql.Date) df.parse(input);
In fact, the type of the return value of java.text.DateFormat.parse(String) is java.util.Date, which is incomparable with java.sql.Date.
In your situation, the easiest way might be using java.util.Date instead of java.sql.Date.
Another note: your class name Calendar is duplicate with java.util.Calendar. And it is not a good coding style to use class names which are already used by the standard library.
sqlDate = new java.sql.Date(apptDay.getTime());
Date.valueOf(scanner.nextLine())
String strDate = scanner.nextLine();
SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date = format.parse(strDate);
Try below method -
private static java.sql.Date getDay() throws SQLException {
Scanner in = new Scanner(System.in);
String input;
java.util.Date utilDay = null;
DateFormat df = new SimpleDateFormat("yyyy-mm-dd");
System.out.println("\nPlease enter the date of the appointment, format: yyyy-mm-dd");
while(utilDay == null){
try{
input = in.next();
utilDay = (java.util.Date) df.parse(input);
}catch(ParseException e){
System.out.println("Please enter a valid date! Format is yyyy/mm/dd");
}
}
java.sql.Date sqlDate = new java.sql.Date(utilDay.getTime());
return sqlDate;
}
And from main() method, call this method -
Date birthday = getDay();
java.time
It’s time someone writes the modern answer to this question.
Assuming that you are using (or can start using) a JDBC 4.2 compliant driver you should not use the two Date classes nor DateFormat or SimpleDateFormat. All those classes are poorly designed, the last two particularly troublesome. They are also long outdated. Instead rely on java.time, the modern Java date and time API. It’s much nicer to work with. We need a LocalDate and a DateTimeFormatter.
Now we’re at it, don’t use java.sql.Time either. Use LocalTime from java.time.
So your variable declarations become:
//get the info
String desc = getDesc();
LocalDate apptDay = getDay();
LocalTime[] times = getTime();
LocalTime startTime = times[0];
LocalTime endTime = times[1];
int key;
Only for passing the java.time objects to your prepared statement you don’t use setDate and setTime. You need to use setObject:
stat.setInt(1, key);
stat.setString(2, desc);
stat.setObject(3, apptDay);
stat.setObject(4, startTime);
stat.setObject(5, endTime);
stat.execute();
Everything else is as before. For parsing the user input string to a LocalDate, here is a short demonstration:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/M/d");
String input = "2019/11/09";
try {
LocalDate aptDate = LocalDate.parse(input, dateFormatter);
System.out.println("Parsed date: " + aptDate);
} catch (DateTimeParseException dtpe) {
System.out.println("Please enter a valid date. Format is yyyy/mm/dd");
}
The output from the last snippet is:
Parsed date: 2019-11-09
I have specified just one M and one d in the format pattern string to allow the user to enter one or two digits for month and day of month, for example 2019/11/9. Most users I know will appreciate this.
Link
Oracle tutorial: Date Time explaining how to use java.time.
Related
This question already has answers here:
How to compare dates in Java? [duplicate]
(11 answers)
How to use Scanner to accept only valid int as input
(6 answers)
Java Date() giving the wrong date [duplicate]
(9 answers)
Java iterator.hasNext() is always true
(2 answers)
Closed 1 year ago.
I have problem which can't solve. The user is asked to input a date and it's compared to todays date and if it's in the future the user is asked to input date again. The first time it works and tells user it's in the future but when he enters a valid date it's still showing to re-enter. Any help appreciated.
System.out.println("Purchase date DD/MM/YYYY:");
String date = sc.nextLine();
SimpleDateFormat dateform = new SimpleDateFormat ("DD/MM/YYYY");
dateform.parse(date);
Date d = new Date();
Date d2 = dateform.parse(date);
while (d2.compareTo(d) > 0 ){
System.out.println("Re-enter");
date = sc.nextLine();
}
consumbles.add(date);
System.out.println("Purchase date DD/MM/YYYY:");
String date = sc.nextLine();
// Use java.time, the modern Java date and time API, for your date work.
// Use single letters in the format pattern string to allow user
// to enter single digit day and month.
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("d/M/u");
// Use saying variable names (not just d and d2)
LocalDate today = LocalDate.now(ZoneId.systemDefault());
LocalDate dateEntered = LocalDate.parse(date, dateFormatter);
// Using isAfter() for comparison is easier to read then compareTo()
while (dateEntered.isAfter(today)) {
System.out.println("Re-enter");
date = sc.nextLine();
// Parse the new entered date string into dateEntered
dateEntered = LocalDate.parse(date, dateFormatter);
}
System.out.println("You have successfully entered " + dateEntered);
Sample session:
Purchase date DD/MM/YYYY:
15/3/2021
Re-enter
11/3/2021
You have successfully entered 2021-03-11
Your errors were:
You were using the wrong case of pattern letters in your format pattern string. No matter if using the old and troublesome SimpleDateFormat or the modern DateTimeFormatter pattern letters are case sensitive. Upper case D is for day of year, lowercase d for day of month. Upper case Y is for week year and only useful with a week number. Lowercase y is for year of era. In my code I used lower case u for a signed year, this is special for DateTimeFormatter.
You were not assigning a new value to d2 when the user entered a new date. Thus when your condition, d2.compareTo(d) > 0, was true, it would stay true no matter how many times the user entered a different date.
You can use a variable (e.g. boolean valid in the code below) to track whether the input is valid. If the input is not valid, you need to loop back. I prefer using do-while loop, which guarantees to execute its body at least once, for such a scenario. I also recommend you handle exception for invalid input.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws ParseException {
Scanner sc = new Scanner(System.in);
SimpleDateFormat parser = new SimpleDateFormat("d/M/yyyy", Locale.ENGLISH);
Date today = new Date();
boolean valid;
do {
valid = true;
System.out.print("Purchase date DD/MM/YYYY: ");
String strDate = sc.nextLine();
Date date = null;
try {
date = parser.parse(strDate);
if (date.after(today)) {
System.out.println("The date should not be a future date. Please try again.");
valid = false;
}
} catch (ParseException e) {
System.out.println("Invalid date/format. Please try again.");
valid = false;
}
} while (!valid);
System.out.println("Thank you! Processing ...");
}
}
A sample run:
Purchase date DD/MM/YYYY: a
Invalid date/format. Please try again.
Purchase date DD/MM/YYYY: 14/3/2021
The date should not be a future date. Please try again.
Purchase date DD/MM/YYYY: 12/2/2020
Thank you! Processing ...
Note that the java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API*.
Using the modern date-time API:
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
DateTimeFormatter parser = DateTimeFormatter.ofPattern("d/M/u", Locale.ENGLISH);
LocalDate today = LocalDate.now();
boolean valid;
do {
valid = true;
System.out.print("Purchase date DD/MM/YYYY: ");
String strDate = sc.nextLine();
LocalDate date = null;
try {
date = LocalDate.parse(strDate, parser);
if (date.isAfter(today)) {
System.out.println("The date should not be a future date. Please try again.");
valid = false;
}
} catch (DateTimeException e) {
System.out.println("Invalid date/format. Please try again.");
valid = false;
}
} while (!valid);
System.out.println("Thank you! Processing ...");
}
}
Learn more about the modern date-time API from Trail: Date Time.
Note:
You have wrongly used D instead of d. D is used for Day in year, not for Day in month.
You have wrongly used Y instead of y. Y is used for a Week year, not for year.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Object Class
public Association(String assoName, String Abbrv, GregorianCalendar formDate, Student president)
{
this.assoName = assoName;
this.abbrv = abbrv;
this.formDate = formDate;
this.president = president;
}
Application class
String assoName = JOptionPane.showInputDialog("Association Name: ");
pw.println(assoName);
String abbrv = JOptionPane.showInputDialog("Association's Abbreviation");
pw.print(","+abbrv);
GregorianCalendar formDate = JOptionPane.showInputDialog("Association Formation Date (dd/mm/yyyy) ");
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/mm/yyyy");
Can you please help me with the program T_T
I cant change anything as it's for my project and it's already set by my professor.
how to change to LocalDate and DateTimeFormatter from GregorianCalender?
If you can, change GregorianCalendar formDate to LocalDate formDate in the Association class.
In any case, the one-arg JOptionPane.showInputDialog that you use for reading the formation date from the user returns a String, so I suggest you read it into a String variable, say, formationDateString, and then parse it into a LocalDate. Something like:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("d/M/u");
String formationDateString = JOptionPane.showInputDialog("Association Formation Date (dd/mm/yyyy) ");
try {
LocalDate formDate = LocalDate.parse(formationDateString, dateFormatter);
} catch (DateTimeParseException dtpe) {
JOptionPane.showMessageDialog(null, "Invalid date format",
"id frn’s app", JOptionPane.ERROR_MESSAGE);
}
If you cannot change the Association constructor, convert your LocalDate to GregorianCalendar like this after parsing:
ZonedDateTime startOfDay = formDate.atStartOfDay(ZoneId.systemDefault());
GregorianCalendar formDateGregCal = GregorianCalendar.from(startOfDay);
If what you are saying is that your professor insists on using the badly designed and long outdated GregorianCalendar (not to mention the notoriously troublesome SimpleDateFormat), you may want to check whether it’s OK to use the modern and far better alternative, though (and feel free to quote me here).
I want to return the message "Date is very wrong" if the transaction date is greater than the computation date. Instead, it just prints "-1 days".
import java.text.SimpleDateFormat;
import java.util.Date;
public class Age {
public static long computeAge(String transDate, String computeDate){
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
long lapseDays = 0;
try {
Date TDate = format.parse(transDate);
Date CDate = format.parse(computeDate);
long aging = CDate.getTime() - TDate.getTime();
lapseDays = aging/(24*60*60*1000);
}catch (Exception e){
e.printStackTrace();
System.out.print("Date is very wrong");
}
return lapseDays;
}
public static void main(String[] args) {
String transaction = "10/01/2014";
String computation = "09/30/2014";
System.out.println(computeAge(transaction, computation)+ " days");
}
}
If I understand your question, you could call the method Date.after(Date) and something like
Date TDate = format.parse(transDate);
Date CDate = format.parse(computeDate);
if (TDate.after(CDate)) {
System.out.print("Date is very wrong");
return -1;
}
try this: change the return type to String of computeAge() method.
public class Test2 {
public static String computeAge(String transDate, String computeDate){
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
long lapseDays = 0;
try {
Date TDate = format.parse(transDate);
Date CDate = format.parse(computeDate);
long aging = CDate.getTime() - TDate.getTime();
lapseDays = aging/(24*60*60*1000);
if(lapseDays<0){
return "Date is very wrong";
}
}catch (Exception e){
e.printStackTrace();
System.out.print("Date is very wrong");
}
return lapseDays+" days";
}
public static void main(String[] args) {
String transaction = "10/01/2014";
String computation = "09/30/2014";
System.out.println(computeAge(transaction, computation));
}
}
Joda-Time
Here is some easier code, using the Joda-Time library version 2.4. Joda-Time is far superior to the confusing and troublesome java.util.Date & .Calendar classes bundled with Java.
LocalDate
In particular, Joda-Time offers a class to represent a date-only without time-of-day or time zone, LocalDate.
The java.time package built into Java 8 (inspired by Joda-Time) also offers a LocalDate class.
Test For All Outcomes
The question may be confusing three possible outcomes, and fails to test for the second:
Either string input is invalid format, and cannot be parsed. (bad)
The first date may occur after the second date, or is equal. (bad)
The first date occurs before the second date. (good)
For more robust code, you should also do sanity-checks on the data, looking for dates that are too far in the past or in the future.
Give Better Feedback
Note that I use different messages for each possible outcome. The code in the Question uses identical messages which leads to confusion.
Example Code
Invalid string inputs are detected during parsing by throwing the Joda-Time exception, IllegalArgumentException.
String inputA = "10/01/2014";
String inputB = "09/30/2014";
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MM/dd/yyyy" );
try {
LocalDate a = formatter.parseLocalDate( inputA );
LocalDate b = formatter.parseLocalDate( inputB );
int daysBetween = Days.daysBetween( a , b ).getDays();
if ( a.isBefore( b ) ) {
System.out.println( "First date is " + daysBetween + " days before second date." );
} else { // Else the same date or a is later than b.
System.out.println( "Error: First date is same or later than second date." );
}
} catch ( IllegalArgumentException e ) {
System.out.println( "Invalid date string." );
}
I am trying to get client arrival date and compare it with my SQL database to see if in my data base the same date exists. however i receive the following error: The operator > is undefined for the argument type(s) java.lang.String, java.lang.String
P.S I need to compare it via java not using sql query
public void makeNewReservation() throws ParseException {
// Enter informations
System.out.println("Date of arrivel?");
Scanner in = new Scanner(System.in);
String date_entree = in.next();
System.out.println("Date of exit? dd/MM/yyyy");
String date_sortiee = in.next();
calculateDaysDifference(date_sortiee, date_entree);
public void calculateDaysDifference(String date_entree, String date_sortiee) throws ParseException{
ConnectionMySQL myConnection=new ConnectionMySQL();
Connection conSQL=myConnection.startDBConnection();
boolean connectionOK=myConnection.checkConnection(conSQL);
String query = ("SELECT `START_DATE`,`END_DATE` FROM `room_booking");
//if everything is fine with the connection, i try to execute a query
if (connectionOK){
try{
ResultSet mesResultats=myConnection.executeQuery(conSQL, query);
//the while loop is just for me to check the dates
while (mesResultats.next()) {
System.out.println("START_DATE: "+mesResultats.getString(1)+" END_DATE : "+ mesResultats.getString(2));
if (date_entree > mesResultats.getString(1){
System.out.println("cant reserve room room reserved already");
}
}
// je ferme la connexion
conSQL.close();
}
catch(SQLException e){
e.printStackTrace();
}
}
my data base
You need to compare 2 Dates
1) Convert the input String into Date
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");
java.util.Date d=df.format(/*date String*/);
NOTE: df.format will throw parseException if the String format does not match "yyyy-MM-dd" . I leave it upto you to make sure the date string is of the specified format.
2)get Date from sql query
java.util.Date sqlDate=new java.util.Date(resultset.getDate().getTime());
NOTE : resultset.getDate() will give you java.sql.Date class's object.
3) Compare 2 dates
try this logic
Date date1=new Date(df.parse(mesResultats.getString(1)));
Date date2=new Date(df.parse(mesResultats.getString(2)));
int status=date1.compareTo(date2); //compareto is a function defined for date
if status==0 print same date
if status<0 print date1 is older then date2
if status>0 print date1 is newer then date2
[Update after comment]
DateFormat df = new SimpleDateFormat("Format of your date goes here");
I want to convert string to date format, but the following way didn't work.
It yields null for birth.
Date birth;
try {
DateFormat formatter ;
formatter = new SimpleDateFormat("dd-MMM-yyyy");
birth = (Date)formatter.parse(birthDate); // birtDate is a string
} catch (ParseException e) {
System.out.println("Exception :"+e);
}
Your answer is right on the money. I put it in a full program and tested it.
It now prints out
Default date format Fri Mar 30 00:00:00 CDT 2012
Our SimpleDateFormat 30-Mar-2012
Our SimpleDateFormat with all uppercase 30-MAR-2012
Here are some tips:
Make sure that you are including the correct imports. Depending on
what is in your classpath, you may have accidentally imported
java.sql.Date or some other rogue import.
Try printing the contents
of birthDate before entering the try block and verify that it really
contains a string of format dd-MMM-yyyy
-
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class BirthDate {
public static void main(String[] args) {
Date birth = null;
String birthDate = "30-MAR-2012";
DateFormat formatter = null;
try {
formatter = new SimpleDateFormat("dd-MMM-yyyy");
birth = (Date) formatter.parse(birthDate); // birtDate is a string
}
catch (ParseException e) {
System.out.println("Exception :" + e);
}
if (birth == null) {
System.out.println("Birth object is still null.");
} else {
System.out.println("Default date format " + birth);
System.out.println("Our SimpleDateFormat " + formatter.format(birth));
System.out.println("Our SimpleDateFormat with all uppercase " + formatter.format(birth).toUpperCase());
}
}
}
Your code works fine. If you care to use Joda Time you can use this. You can go through the documentation to unleash the complete functionality in case you plan to use the time for DB testing and stuff.
import org.joda.time.DateTime;
DateTime dt = new DateTime("YYYY-MM-DD");//new DateTime("2012-03-30")
System.out.println(dt);