In my Java app I must save data to Oracle 11g with object created date and time and for this I convert java.util.Date() to java.sql.Date() in format as new java.sql.Date(new java.util.Date().getTime()). But I noticed, that after the data inserted, oracle truncate the time part of date and I get something like 16/09/2015. but I need format like this: 16/09/2015 9:55:44. the second format created by oracle's sysdate() procedure. How I can get the second format from java code?
From memory (it's been a while), java.sql.Date is used to hold dates (no time) only, if you want time information as well, you need to use java.sql.TimeStamp instead.
Do not use java.sql.Date if you want to store date and time. Just use java.util.Date without any conversion. Simple and easy. There is no need for java.sql.TimeStamp either.
And make sure your NLS settings (e.g. in SQL Developer) are such that they display both date and time as Oracle does not distinguish between dates with and without time.
I guess Oracle does not truncate. For example, if you use Oracle SQL Developer, you have to update NLS parameter "Date Format" to see a time.
By default it just equal "DD-MON-RR"
Related
I am porting my Java application which was developed for Windows to AIX Unix. On Windows it uses SQL Server for configuration. On AIX we are trying to use H2 database. Most of the code works but I am getting following error when executing query which has a datetime criteria.
org.h2.jdbc.JdbcSQLDataException: Cannot parse "DATE" constant "26-Jun-2019"; SQL statement:
SELECT EM_SCHEDULER_DAILY_POLL.* FROM EM_SCHEDULER_DAILY_POLL, EM_CONTROLLER WHERE EM_SCHEDULER_DAILY_POLL.CONTROLLER_ID =
EM_CONTROLLER.CONTROLLER_ID AND EM_SCHEDULER_DAILY_POLL.DATE_TIME
BETWEEN '26-Jun-2019' AND '26-Jun-2019 23:59:59' AND
POLLED_SUCCESSFULLY=0 AND EM_SCHEDULER_DAILY_POLL.CONTROLLER_ID=30
[22007-199]
This SQL works perfectly on SQL server but gives above exception on H2DB. How to solve this issue? I need both date and time in query.
Try using ISO date literals:
WHERE
EM_SCHEDULER_DAILY_POLL.DATE_TIME >= '2019-06-26' AND
EM_SCHEDULER_DAILY_POLL.DATE_TIME < '2019-06-27'
Note that since you are just looking for records on a single date, you could also try casting the column to date and doing a single comparison:
WHERE CAST(EM_SCHEDULER_DAILY_POLL.DATE_TIME AS DATE) = '2019-06-26'
As another comment, the first version I gave, with the two inequalities is sargable, meaning that the database should be able to use an index on the DATE_TIME column, while the second version, using the cast to date, probably cannot use an index. Therefore, the first version is the preferred way to go, if you ever need to tune or optimize your database.
You are passing a value with a time but H2 Date only don't have one.
Just remove the time in your second constant.
'26-Jun-2019 23:59:59' --> '26-Jun-2019'
DATE The date data type. The format is yyyy-MM-dd.
Mapped to java.sql.Date, with the time set to 00:00:00 (or to the next
possible time if midnight doesn't exist for the given date and
timezone due to a daylight saving change). java.time.LocalDate is also
supported on Java 8 and later versions.
Example:
DATE
Source :Data type of H2.
And since you just want one day (at least in that example), you can simply use :
DATE_TIME = '26-Jun-2019'
Note that Tim Biegeleisen's answer about ISO should be checked too, this format is not the best
Use TO_DATE function
Example - TO_DATE('01-12-2019','dd-MM-yyyy')
Insert into student(Id,Name,DOB) values(1, 'Abc', TO_DATE('01-12-2019','dd-MM-yyyy'))
There is a converter PARSEDATETIME() fuction.
For example if the date is 12/03/2013 we need to convert as PARSEDATETIME('12/03/2013','dd/MM/yyyy') check this SO.
The SQL statement look like Insert into invoice(id, invoice_date) values(1, PARSEDATETIME('12/03/2013','dd/MM/yyyy'))
So far, I have not found a clear answer to this.
I'd like to know what the equivalent is for a SQL type DATETIME and the java type, using a PreparedStatement.
I have found: http://www.java2s.com/Code/Java/Database-SQL-JDBC/StandardSQLDataTypeswithTheirJavaEquivalents.htm
But it states that SQL type "DATETIME" is the same as sql.date, but when looking at the SQL date docs (http://download.oracle.com/javase/7/docs/api/java/sql/Date.html), it says the time is truncated (all zeros).
What I want is to be able to specify a preparedStatement.setDateTime() or some sort.
The only other way I see is using a timestamp, but that would require me to change the column type, while I cannot imagine someone else never had this problem before?
Any hints?
Edit: I am using MYSQL.
The java.sql package has three date/time types:
java.sql.Date - A date only (no time part)
java.sql.Time - A time only (no date part)
java.sql.Timestamp - Both date and time
You want the last one: java.sql.Timestamp.
If you are using these types, you don't need to call a specific setter; just use:
java.util.Date date = new Date();
Object param = new java.sql.Timestamp(date.getTime());
// The JDBC driver knows what to do with a java.sql type:
preparedStatement.setObject(param);
The equivalent of MS SQL Server or MySQL DATETIME data type or Oracle DATE data type is java.sql.Timestamp.
In Java we have java.util.Date to handle both Date and Time values.
In SQL, you have commonly Dates (only dates), Time (only time) and DateTime/Timestamp (date and time).
In your Java program, usually you'll always have java.util.Date, so each time you're setting Dates/Times/DateTimes in PreparedStatements, always choose exactly which one you need, according to the database.
I had a similar problem with my Mysql having SQL date and locally in my app i only had Date
I solved like this
java.sql.Date dataStartSql = new java.sql.Date(start.getTime());
After that used the setDate normally, and I used a getTimestamp to retrive the first value.
where start is a Date object.
Is there a way to set the default DateFormat class used for parsing strings into dates?
My background: I get exceptions reading date values from JDBC because the date string is not in the expected format.
(text added on 2011-07-22):
Seems I need to precise my question description: I use a foreign, proprietary database together with a proprietary JDBC driver. There is no possibility to know or even change the column type on database side. When I try to read the ResultSet columns via ResultSet.getDate() or ResultSet.getObject() some exception is triggered inside the JDBC driver like "10 Jul 1999 is not a valid date". What I want to achieve is to avoid this internal exception by setting some appropriate global default date format. Maybe I would need to implement some custom Locale first and the install that Locale globally?
There should be totally no need for this.
Dates should be stored in DB as a DATE, DATETIME or TIMESTAMP field, depending on the DB used and the information you'd like to store (e.g. date only or date and time combined), not as a VARCHAR or something. Such a date-specific field stores the value under the covers basically as an integer/long with the epoch time as value.
Assuming that you're using a date+time field type such as DATETIME or TIMESTAMP, then you should be saving it in the DB using PreparedStatement#setTimestamp(). Here's an example, assuming that the date variable is of a java.util.Date type:
preparedStatement.setTimestamp(1, new Timestamp(date.getTime()));
And you should be retrieving them from the DB using ResultSet#getTimestamp() which returns a Timestamp which in turn is a subclass of java.util.Date, so you could just safely upcast it:
Date date = resultSet.getTimestamp("columnname");
As to parsing/formatting the java.util.Date object from/into a human readable String format, this should technically happen in the view side, not in the persistence layer. How exactly to do this in turn depends on the view/UI technology/framework used, such as Swing, JSP, JSF, Struts2, Spring-MVC, etcetera. As it's not clear from your question which one you're using, it's not possible to give a suitable answer. In general, they all use SimpleDateFormat API under the covers. You could even use it in raw form.
You can set your default Locale:
Locale.setDefault(Locale.US);
Alternatively, you can use one of the DateFormat static methods which accepts a Locale to just get the format for the Locale you're interested in. If your date format doesn't match one of the standard ones, you'll need to create your own SimpleDateFormat (based on a pattern) and make sure you always use that one instead of the default one.
I have a wierd hibernate related issue while setting a date field in an entity.
The date is interpreted as UTC in the java program (i did a System.out to make sure the date assigned is in 'UTC'. However, when hibernate actually persists to the database, the date is converted to local time and stored)
ex. the value has been set in the entity setter as "2009-09-09 00:08:08" - GMT
the actual value persisted to the database is "2009-09-08 08:08:08" - eastern time US.
I am unable to find out where and why this is happening and how to prevent it. Thanks
P.S. I am using joda date library and annotate the field with
#org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
However, when hibernate actually persists to the database, the date is converted to local time and stored) ex. the value has been set in the entity setter as "2009-09-09 00:08:08" - GMT the actual value persisted to the database is "2009-09-08 08:08:08" - eastern time US.
Ok, first, whatever column type are you using to store your date in MySQL (TIMESTAMP or DATETIME), neither stores the time zone. From Re: Storing timezone with datetime:
TIMESTAMP is seconds since 1970, sitting in 4 bytes. It is stored in GMT. That is, the TZ offset is applied as you store a value, then reapplied when you fetch it. (...)
DATETIME is an 8-byte string of digits "yyyymmddhhmmss". (...)
And second, unless a buggy behavior, my understanding is that the conversion is supposed be done either by the server or by the JDBC driver depending on the the server time zone settings so that you don't get inconsistent data.
In both cases, my point is that storing "2009-09-09 00:08:08" - GMT or "2009-09-08 08:08:08" - eastern time US from Java should yield to the same value in the database.
However, it looks like a different conversion is done when displaying them. This begs the question: how did you actually check the value of the "persisted date". Does the "problem" occur in your SQL client? In Java code?
References
9.6. MySQL Server Time Zone Support
21.3.4.1. Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J
Bug #15604: TimeZone discarded storing java.util.Calendar into DATETIME
MySQL documentation for DateTime says "MySQL retrieves and displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format". That means mysql converts the 'milliseconds since epoch' to the above format. So now my question becomes, is timezone info also stored in mysql?
I've updated my initial answer (which was not totally accurate/exhaustive). Whether you're using DATETIME or TIMESTAMP, the answer is no.
Another observation I made is, the above date 'conversion' issue exists only when Im setting the date in the Java application. If I create a mysql trigger to update/set date using 'UTC_TIMESTAMP()', the date is displayed in the 'UTC' time.
The UTC_TIMESTAMP() function always returns the current UTC date and time.
What I'd like to know is:
How did you "reveal" the problem? With a SQL client or from Java?
What is the local time zone of the JVM?
What is the MySQL Server time zone?
What is the version of the MySQL JDBC Driver?
Could you do a test with raw JDBC?
In order to treat dates as UTC in the DB (for read/write), you can use this small open source library DbAssist. It uses a custom UtcDateType in order to map java.util.Date fields in your entities, so that they are treated by Hibernate as UTC in the DB. Since you are using JPA annotations, you would use the following dependency:
<dependency>
<groupId>com.montrosesoftware</groupId>
<artifactId>DbAssist-5.2.2</artifactId>
<version>1.0-RELEASE</version>
</dependency>
Applying the fix is easy, for example, when using Spring Boot, you have to make sure that you have #EnableAutoConfiguration annotation before the application class. If you are using another Hibernate version, just refer to github wiki to find the proper version of the fix and the installation guide. You can also read more about the time zone shift issue in this article.
This behaviour of Joda Time Contrib is fixed in my project Usertype for Joda Time and JSR310. See http://usertype.sourceforge.net/ which is practically otherwise a drop in replacement for JodaTime Hibernate.
I have written about this issue: http://blog.jadira.co.uk/blog/2010/5/1/javasqldate-types-and-the-offsetting-problem.html
Hope this helps,
Chris
I am inserting a record to orcle db through java application. The date value inserted as 02/10/0010 instead of 02/10/2010 HH:MM:SS AM/PM? I am using oracle jdbc connection. Does it problem with JDBC driver ?
Any input on this.
If you're using Oracle and JDBC, don't store Date in your table as a String. Make it a real Date and you'll spare yourself all this pain.
Check your date source. Is it two digit year or four?
Also, there are Oracle date mask formats which might cause that. Check the default for the installation.
Agree.
If you use a Java Date format (dunno its class just now) then JDBC driver performs all what is needed to store it in a Date column.
If you use String in java and/or varchar2 in Oracle table, you are doing it wrong. This will lead to implicit conversions, NLS settings and all that pain... if you are in this bad shape then you need explicit conversions and format masks on each date usage.
Use proper types.
I'm guessing that the value you're passing in is "02/10/10".
Date functions are pretty inconsistent about what they do with 2 digit years. If you are trying to enter dates for your "timeline of ancient history", having the computer assume that 2-digit dates must be shorthand for the 21st century would be very annoying. We really are better off with a WYSIWYG date interpretation.