I am calling a stored procedure in a database.
Two of its parameters requires date and time in sql date format.
String x = new SimpleDateFormat("MM-dd-yyyy").format(new Date()) + " 00:00:00 AM";
String y = new SimpleDateFormat("MM-dd-yyyy").format(new Date()) + " 11:59:00 PM";
Date fromDate = null;
Date toDate = null;
try {
fromDate = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss a").parse(x);
toDate = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss a").parse(y);
} catch (ParseException ex) {
}
CallableStatement proc_stmt = con.prepareCall("{ call someproc(?,?) }");
proc_stmt.setDate(1, (java.sql.Date) fromDate);
proc_stmt.setDate(2, (java.sql.Date) toDate);
I believe if i send just the date(excluding time), the code works, but its of no use to me as the database does not generate correct results.
When i run the above code I get
ClassCastException:java.util.Date cannot be cast to java.sql.Date
Any solution?
Use java.sql.Timestamp class which holds date and time for sql fields, and CallableStatement#setTimestamp:
proc_stmt.setTimestamp(1, new java.sql.Timestamp(fromDate.getTime());
create new object of java.sql date and then pass the java.util date in it.
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
I usually go for along the lines of
proc_stmt.setDate(1, new java.sql.Date(fromDate.getTime()));
Why are you formatting a Date to a String and then parsing it again? You shouldn't need a string representation at all. Avoid string conversions as far as you can - you're not really interested in the text representation of the date; you're just trying to specify a value.
You should be able to use:
// TODO: Consider time zones
Calendar calendar = Calendar.getInstance();
// Clear the time part of the calendar (leaving you with "start of day")
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Timestamp start = new Timestamp(calendar.getTimeInMillis());
// Adjust to "end of day"
calendar.add(Calendar.DATE, 1);
calendar.add(Calendar.MILLISECOND, -1);
Timestamp end = new Timestamp(calendar.getTimeInMillis());
CallableStatement statement = con.prepareCall("{ call someproc(?,?) }");
statement.setTimestamp(1, start);
statement.setTimestamp(2, end);
Note that I've switched to using java.sql.Timestamp instead of java.sql.Date as it looks like you really do want a date and time whereas java.sql.Date only represents a date.
A couple of other points:
If you could use Joda Time, it would make the first part of the code simpler. Joda Time is a much better date/time API in general.
I would suggest you change your stored procedure to use an exclusive end time if possible. That way you can just specify the start of today and the start of tomorrow. You don't need to worry about the granularity of the value, because you can always create abutting but non-overlapping intervals. In particular, I've currently only set end to the end of the day down to the last millisecond - but java.sql.Timestamp
Related
This question already has answers here:
How to set time zone of a java.util.Date?
(12 answers)
Closed 5 years ago.
I have a dates stored in mysql with no timezone, like 2001-01-10 00:00:00.
I have tomcat running in timezone +10:00 for example.
I need to generate a Date() that have no offset int the object.
If I do this:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTime( new Date(/*from 2001-01-10 00:00:00*/) );
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date newDate = cal.getTime();
The result Date object still having the zoneinfo and zoneoffset reporting to server timezone, not UTC.
I need to generate a Date() Object that have ZERO TIME, but mantain the date stored in mysql, independent of tomcat timezone.
In other words, I want to generate date with zero hour/min/sec independent of server timezone.
The date generated shows 2001-01-01T00:00:00.000+1400
the time is zero but offset is +14:00.
I want to generate 2001-01-01T00:00:00.000+0000
The mysql datatime is DATETIME
The Date object does not keep timezone information, imagine it as a class with only a long property which stores the number of milliseconds that passed from 1970.
The SimpleDateFormat class or other libraries like JODA are responsible of keeping track of timezone when they transform the date to string.
The date itself doesn't have any time zone. Its toString() method uses the current default time zone to return a String representing this date, as explained in this post. However, you can precise the target timezone during the formatting, to obtain the desired result:
// 2001-01-01T00:00:00.000+00:00
long timestamp = 978307200_000L;
Date newDate = new Date(timestamp);
SimpleDateFormat u = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
u.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat k = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
k.setTimeZone(TimeZone.getTimeZone("Pacific/Kiritimati"));
assertEquals("2001-01-01T00:00:00.000+0000", u.format(newDate));
assertEquals("2001-01-01T14:00:00.000+1400", k.format(newDate));
Well, the only way that I can acquire desired result, is making an adjust to Java Date, I get the current offset of Tomcat and add/remove him from the Date, the follow function make the date returned by rest is allways the same, independent of the tomcat timezone. I use JODA DateTime for this.
public Date adjustDateTimeZoneToUTC( Date date )
{
Date utcDate = null;
if( date != null )
{
int curOffset = TimeZone.getDefault().getRawOffset();
DateTime dt = new DateTime(date).withZoneRetainFields(DateTimeZone.UTC);
// Se o offset for NEGATIVO(-12:00), deve-se somar esse tempo
// Se o offset for POSITIVO(+12:00), deve-se subtrair esse tempo
if( curOffset >= 0 ) {
dt.minusMillis(curOffset);
} else {
curOffset *= -1;
dt.plusMillis(curOffset);
}
utcDate = dt.toDate();
}
return utcDate;
}
On the client side, using angular datepicker or other javascript calendar, you need to do the same way on javascript, for you date stay imutable on different timezones. Like the sample:
$dateParser.timezoneOffsetAdjust = function (date, timezone, undo) {
if (!date) {
return null;
}
// Right now, only 'UTC' is supported.
if (timezone && timezone === 'UTC') {
date = new Date(date.getTime());
date.setMinutes(date.getMinutes() + (undo ? -1 : 1) * date.getTimezoneOffset());
}
return date;
};
I need to get a java.sql.date in the following format "MM-dd-yyyy", but I need it to stay a java.sql.date so I can put it into a table as date field. So, it cannot be a String after the formatting, it has to end up as a java.sql.date object.
This is what I have tried so far:
java.util.Date
today=new Date();
String date = formatter.format(today);
Date todaydate = formatter.parse(date);
java.sql.Date fromdate = new java.sql.Date(todaydate.getTime());
java.sql.Date todate=new java.sql.Date(todaydate.getTime());
String tempfromdate=formatter.format(fromdate);
String temptodate=formatter.format(todate);
java.sql.Date fromdate1=(java.sql.Date) formatter.parse(tempfromdate);
java.sql.Date todate1=(java.sql.Date) formatter.parse(temptodate);
You can do it the same way as a java.util.Date (since java.sql.Date is a sub-class of java.util.Date) with a SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat(
"MM-dd-yyyy");
int year = 2014;
int month = 10;
int day = 31;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1); // <-- months start
// at 0.
cal.set(Calendar.DAY_OF_MONTH, day);
java.sql.Date date = new java.sql.Date(cal.getTimeInMillis());
System.out.println(sdf.format(date));
Output is the expected
10-31-2014
Use below code i have convert today date. learn from it and try with your code
Date today = new Date();
//If you print Date, you will get un formatted output
System.out.println("Today is : " + today);
//formatting date in Java using SimpleDateFormat
SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM-dd-yyyy");
String date = DATE_FORMAT.format(today);
System.out.println("Today in MM-dd-yyyy format : " + date);
Date date1 = formatter.parse(date);
System.out.println(date1);
System.out.println(formatter.format(date1));
A simpler solution would be to just convert the date in the query to epoch before comparing.
SELECT date_column from YourTable where UNIX_TIMESTAMP(date_column) > ?;
Then, simply pass date.getTime() when binding value to ?.
NOTE: The UNIX_TIMESTAMP function is for MySQL. You'll find such functions for other databases too.
java.util.Date today=new Date();
java.sql.Date date=new java.sql.Date(today.getTime()); //your SQL date object
SimpleDateFormat simpDate = new SimpleDateFormat("MM-dd-yyyy");
System.out.println(simpDate.format(date)); //output String in MM-dd-yyyy
Note that it does not matter if your date is in format mm-dd-yyyy or any other format, when you compare date (java.sql.Date or java.util.Date) they will always be compared in form of the dates they represent. The format of date is just a way of setting or getting date in desired format.
The formatter.parse will only give you a java.util.Date not a java.sql.Date
once you have a java.util.Date you can convert it to a java.sql.Date by doing
java.sql.Date sqlDate = new java.sql.Date (normalDate.getTime ());
Also note that no dates have any built in format, it is in reality a class built on top of a number.
For anyone reading this in 2017 or later, the modern solution uses LocalDate from java.time, the modern Java date and time API, instead of java.sql.Date. The latter is long outdated.
Formatting your date
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-uuuu", Locale.US);
LocalDate fromDate = LocalDate.now(ZoneId.of("Asia/Kolkata"));
String tempFromDate = fromDate.format(formatter);
System.out.println(tempFromDate);
This prints something like
11-25-2017
Don’t confuse your date value with its textual representation
Neither a LocalDate nor a java.sql.Date object has any inherent format. So please try — and try hard if necessary — to keep the two concepts apart, the date on one side and its presentation to a user on the other.
It’s like int and all other data types. An int can have a value of 4284. You may format this into 4,284 or 4 284, 004284 or even into hex representation. This does in no way alter the int itself. In the same way, formatting your date does not affect your date object. So use the string for presenting to the user, and use LocalDate for storing into your database (a modern JDBC driver or other modern means of database access wil be happy to do that, for example through PreparedStatement.setObject()).
Use explicit time zone
Getting today’s date is a time zone sensitive operation since it is not the same date in all time zones of the world. I strongly recommend you make this fact explicit in the code. In my snippet I have used Asia/Kolkata time zone, please substitute your desired time zone. You may use ZoneId.systemDefault() for your JVM’s time zone setting, but please be aware that this setting may be changed under our feet by other parts of your program or other programs running in the same JVM, so this is fragile.
Date date1= new java.util.Date();
java.sql.Date Sqldob = new java.sql.Date(date1.getTime());
System.out.println("date" +Sqldob);
Time Sqldob1 = new Time(date1.getTime());
System.out.println("User Time: " +Sqldob1);
String yourTime="09:30:00";
SimpleDateFormat ra = new SimpleDateFormat("HH:mm:ss");
Date yourDate = ra.parse(yourTime);
Time sqlTime3 = new Time(yourDate.getTime());
System.out.println("your time"+sqlTime3);
if(Sqldob1.before(sqlTime3)){
Sqldob1 = sqlTime3;
System.out.println("inside loop");
}
In the code above I am comparing two time variables for equality, but it is giving me the same value -1 for all the types of input
You need to use the Date#before(Date),Date#after(Date) and Date#equals(Date) methods for basic date comparisons.
E.g:
Date d1 = new Date();
Date d2 = new Date();
if(d1.after(d2)){
// Do something
}
if(d1.before(d2)){
// Do something
}
if(d1.equals(d2)){
// Do something
}
You can use the Date#compareTo(Date) method also, but then, you need to interpret the output of the compareTo method accordingly.
As the docs say:
The value 0 if the argument Date is equal to this Date; a value less
than 0 if this Date is before the Date argument; and a value greater
than 0 if this Date is after the Date argument.
In your case, you are getting -1 because
new SimpleDateFormat("HHH:mm:ss"); is wrong. Should be new SimpleDateFormat("HH:mm:ss");
int compare= sqlTime3.compareTo(Sqldob1); This sqlTime3 has only time in it. The date is the epoch date as you've not mentioned that, and hence, its always going to be before new Date() which is today.
Your solution:- (Hope this addresses your problem)
java.util.Date date1= new java.util.Date();
Time Sqldob1 = new Time(date1.getTime());
System.out.println("User Time: " +Sqldob1);
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 19); // Your hour
cal.set(Calendar.MINUTE, 30); // Your Mintue
cal.set(Calendar.SECOND, 00); // Your second
Time sqlTime3 = new Time(cal.getTime().getTime());
System.out.println("your time: "+sqlTime3);
if(Sqldob1.before(sqlTime3)){
Sqldob1 = sqlTime3;
System.out.println("inside loop");
}
You need to parse the date and call methods like before(), after() and equals() like this,
if(date.before(date1)){
System.out.println(" date is before date1 ");
}
if(date.after(date1)){
System.out.println(" date is after date1 ");
}
If both date and date1 are equal you can use equals method,
if(date.equals(date1)){
System.out.println(" date and date1 are equal");
}
Modern version:
LocalDateTime dateTime1 = LocalDateTime.now(ZoneId.systemDefault());
LocalDate dob = dateTime1.toLocalDate();
System.out.println("date " + dob);
LocalTime dob1 = dateTime1.toLocalTime();
System.out.println("User Time: " + dob1);
String yourTime = "09:30:00";
LocalTime time3 = LocalTime.parse(yourTime);
System.out.println("your time " + time3);
if (dob1.isBefore(time3)) {
dob1 = time3;
System.out.println("inside if statement");
}
When I ran this code this morning, it printed:
date 2017-07-07
User Time: 05:32:01.881
your time 09:30
inside if statement
The point is: With the old and now long outdated classes Date and Time it is easy not to get things right. With the modern classes I use here, it’s much easier to get them right.
Are you using java.sql types because you really need to get your date and time from a database and/or store them into one? This was what these were for, you shouldn’t really have used them for other purposes. I use “was” and “were” intentionally because you don’t need them for this purpose either anymore. With a new JDBC driver, you can get a LocalDateTime from the database and store one back, or depending on your column datatype get an Instant and convert it to LocalDateTime:
LocalDateTime dateTime2 = instantFromDb.atZone(ZoneId.systemDefault())
.toLocalDateTime();
PS Item 2. in SoduRahul’s answer gives the real and correct explanation of what went wrong in your program: though Time was meant for time-of-day only, your Sqldob1 ends up holding today’s date and sqlTime3 the date of the epoch (January 1, 1970), so the former will always be after the latter by their before method.
compareTo() method always return zero for equal and non-zero for unequal dates.
I am trying to figure out how to get a date that is exactly one year less than the current date and pass it as a parameter to HQL.
I tried to use Calendar. But I am lost in converting this to right Date format required for Oracle.
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.YEAR, -1);
String dateLimit = cal.getTime().toString();
Date dateFormatter = new SimpleDateFormat("dd-MMM-yyyy").parse(dateLimit); // This one shows I need to either wrap it up in try catch or specify in throws.
//Date cutOffDate = dateFormatter.parse(dateLimit); //tried this. no avail
queryBuilder.append(" and c.dateOfContact >= :cutOffDate ");
parameters.put("cutOffDate", dateFormatter);
Alternatively, are there any Hibernate built-in function for date manipulation? All I want is to pass a date to the query, which is a year less than the current date.
Oracle date format is dd-MMM-yyyy. (ex: 21-Jun-2013)
i think this will work:
parameters.put("cutOffDate", cal.getTime());
If the type of c.dateOfContact is java.util.Date or java.sql.Date than cal.getTime() has to work.
Date d = cal.getTime();
Query query = em.createQuery(QUERYSTRING)setParameter("cutOffDate", d);
The above should work, don't format your date as a string, because then you will be comparing a String and a Date.
I have a Timestamp and Date variables and i want to compare it for equality (only date part of course). It was surprise for me that contructor Date(long) saves time part, so this code does not work correct:
date = resultSet.getDate(1);
timestamp = resultSet.getTimestamp(2);
//...
if (date.equals(new Date (timestamp.getTime())) ...
I solve this with code like:
DateFormat dateFormat = new SimpleDateFormat ("yyyyMMdd");
if (date.equals(dateFormat.parse(dateFormat.format(timestamp)))) ...
Or i can convert timestamp to date in sql query, but i need a timestamp representation too. Is there a better way to cut a time part from Timestamp.
Java 8 approach of conversion:
Date date = Date.valueOf(timestamp.toLocalDateTime().toLocalDate());
And vice versa:
Timestamp timestamp = Timestamp.valueOf(date.toLocalDate().atStartOfDay());
Using the method from this answer we get:
date = resultSet.getDate(1);
timestamp = resultSet.getTimestamp(2);
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(date);
cal2.setTimeInMillis(timestamp.getTime());
boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
It's worth reading the linked answer as it talks about the shortcomings of this method with respects to timezones and so on (and some of the other answers to that question give alternate approaches which you may prefer).
You have three options with this one.
First is to use Yoda time and class DateTimeComparator.getDateOnlyInstance()
Second is to use commons from apache and DateUtils.isSameDay()
Third use the [Calendar] and set the time and compare the year, month and day of year only. As Dave Webb proposed.
Another approach is to use the "day" part of the epoch value:
Date d = new Date();
Timestamp t = new Timestamp(d.getTime());
long dateEpochDays = d.getTime() % (1000*60*60*24);
long timeStampEpochDays = t.getTime() %(1000*60*60*24);
System.out.println("date: " + dateEpochDays + " timestamp: " + timeStampEpochDays);