I have a column in my table from type datetime, I am retrieve that column to my java application using jdbc.
my problem is that when I stored 2014-05-13 23:49:18.150 in my database, it becomes 2014-04-13 in my java application.
how to get all the date include time (house, seconds , minutes ).
java code
callableStatement = con
.prepareCall("{call getStatusForOrder(?,?,?,?,?)}");
callableStatement.setInt(1, order.getID());
callableStatement.registerOutParameter(2, java.sql.Types.INTEGER);
callableStatement.registerOutParameter(3, java.sql.Types.DATE);
callableStatement.registerOutParameter(4, java.sql.Types.DATE);
callableStatement.registerOutParameter(5, java.sql.Types.BIT);
callableStatement.execute();
int statusID = callableStatement.getInt(2);
Date startTime = callableStatement.getDate(3);
Date endTime = callableStatement.getDate(4);
boolean isActive = callableStatement.getBoolean(5);
System.out.println("IsActive = " + isActive);
System.out.println("Start Date = " + startTime.toString());
Use the Timestamp instead of Date, both datetime and datetime2 map to java.sql.Timestamp.
See the documentation.
PS. Do not forget to use callableStatement.getTimestamp instead of callableStatement.getDate.
http://docs.oracle.com/javase/6/docs/api/java/sql/CallableStatement.html#getTimestamp(int)
Use a DateFormat to display it.
SHORT is completely numeric, such as 12.13.52 or 3:30pm
MEDIUM is longer, such as Jan 12, 1952
LONG is longer, such as January 12, 1952 or 3:30:32pm
FULL is pretty completely specified, such as Tuesday, April 12, 1952 AD or 3:30:42pm PST.
I think you must use Timestamp (if I recall it right, haven't programmed Java for a while) instead of Date
Types.DATE signifies a JDBC (and SQL) datatype that only has a date component, and no time. You need to use Types.TIMESTAMP and the associated get/setTimestamp(..) methods and class java.sql.Timestamp if you want to have the time portion included.
Related
I'm trying to use new java.time classes with most recent version of Sql Server JDBC driver. As I read it should just work with methods: PreparedStatement.setObject() and ResultSet.getObject().
So I created sample code, and can't get it work with ResultSets. I don't know what I'm doing wrong here.
Connection connection = DriverManager.getConnection(connectionString);
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM myTable WHERE ? BETWEEN date_from AND date_to");
preparedStatement.setObject(1, LocalDateTime.now()); // That works
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
Object o = resultSet.getObject("date_from");
o.getClass() returns java.sql.Timestamp
LocalDateTime dateTime = resultSet.getObject("date_from", LocalDateTime.class);
}
This throws an exception:
com.microsoft.sqlserver.jdbc.SQLServerException: The conversion to class java.time.LocalDateTime is unsupported.
Driver version: mssql-jdbc-6.5.4.jre8-preview.jar
SQL Server version: 2016
https://learn.microsoft.com/en-us/sql/connect/jdbc/jdbc-4-2-compliance-for-the-jdbc-driver?view=sql-server-2017
How to interpret this sentence in table at bottom:
New Java classes in Java 8:
LocalDate/LocalTime/LocalDateTime,
OffsetTime/OffsetDateTime
New JDBC types:
TIME_WITH_TIMEZONE,
TIMESTAMP_WITH_TIMEZONE,
REF_CURSOR
REF_CURSOR is not supported in SQL Server. Driver throws a SQLFeatureNotSupportedException exception if this type is used. The driver supports all other new Java and JDBC type mappings as specified in the JDBC 4.2 specification.
I don't know what I'm doing wrong here.
You're not doing anything wrong. You have encountered a deficiency in Microsoft's JDBC driver for SQL Server prior to version 7.1.0, discussed here.
If you are using mssql-jdbc version 7.1.0 or later then you can use getObject(x, LocalDateTime.class) as expected.
For mssql-jdbc versions prior to 7.1.0, as others have suggested, you'll need to retrieve a Timestamp and convert it to a LocalDateTime. However, be aware that the simplistic solution ...
LocalDateTime dateTime = resultSet.getTimestamp("date_from").toLocalDateTime()
... will corrupt certain date/time values if the default time zone for the JVM observes Daylight Saving Time, a.k.a. "Summer Time". For example,
// time zone with Daylight Time
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));
// test environment
Statement st = conn.createStatement();
st.execute("CREATE TABLE #tmp (id INT PRIMARY KEY, dt2 DATETIME2)");
st.execute("INSERT INTO #tmp (id, dt2) VALUES (1, '2018-03-11 02:00:00')");
ResultSet rs = st.executeQuery("SELECT dt2 FROM #tmp WHERE id=1");
rs.next();
// test code
LocalDateTime x = rs.getTimestamp("dt2").toLocalDateTime(); // bad
System.out.println(x.toString());
will print "2018-03-11T03:00". Note that the time is "03:00", not "02:00".
Instead, you'll need to retrieve the Timestamp as UTC and then convert it into a LocalDateTime for UTC, thus removing the time zone component
// time zone with Daylight Time
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));
// test environment
Statement st = conn.createStatement();
st.execute("CREATE TABLE #tmp (id INT PRIMARY KEY, dt2 DATETIME2)");
st.execute("INSERT INTO #tmp (id, dt2) VALUES (1, '2018-03-11 02:00:00')");
ResultSet rs = st.executeQuery("SELECT dt2 FROM #tmp WHERE id=1");
rs.next();
// test code
Timestamp ts = getTimestamp("dt2", Calendar.getInstance(TimeZone.getTimeZone("UTC")));
LocalDateTime x = LocalDateTime.ofInstant(ts.toInstant(), ZoneId.of("UTC")); // good
System.out.println(x.toString());
which prints "2018-03-11T02:00".
This is because the Microsoft SQL Server JDBC driver implementation of resultSet.getObject(...) cannot auto convert from java.sql.Timestamp to LocalDateTime.
As a workaround you can get the value as java.sql.Timestamp and then convert java.sql.Timestamp to LocalDateTime by using: java.sql.Timestamp.toLocalDateTime()
LocalDateTime dateTime = resultSet.getTimestamp("date_from").toLocalDateTime()
It looks like the mssql-jdbc driver doesn't fully implement the java.time support specified in JDBC 4.2. It doesn't support it for ResultSet.getObject, but it does support it for PreparedStatement.setObject.
The workaround, as suggested by the answer of Loc Le, is to retrieve as Timestamp and convert that to a LocalDateTime.
If you are stuck and want to try the "old way" of doing it:
Here is a simples example of equivalent conversions. Test yourself.
#Test
public void testingConversionTimestampAndLocalDateTime(){
Timestamp initialTimestamp = new Timestamp(System.currentTimeMillis());
LocalDateTime localDateTime = LocalDateTime.ofInstant(initialTimestamp.toInstant(), ZoneId.of("America/Sao_Paulo"));
ZoneOffset zoneOffset = ZoneId.of("America/Sao_Paulo").getRules().getOffset(localDateTime);
Timestamp timestamp = Timestamp.from(localDateTime.toInstant(zoneOffset));
Timestamp timestamp1 = Timestamp.valueOf(localDateTime);
assertEquals(initialTimestamp, timestamp);
assertEquals(initialTimestamp, timestamp1);
}
i tried to store in two column current data and time on my microsft access database from java, but when i open my file no data has been stored. I tried to print the columns but it print "null".
How can i do?
Date date = new Date();
final String formattedDate = new SimpleDateFormat("yyyy-MM-dd").format(date.getTime());
final String formattedTime = new SimpleDateFormat("HH:mm:ss").format(date.getTime());
final java.sql.Date sqlDate = java.sql.Date.valueOf(formattedDate);
final java.sql.Time sqlTime = java.sql.Time.valueOf(formattedTime);
...
PreparedStatement ps=con.prepareStatement("insert into Table1(Data) values(?)");
ps.setDate(1,sqlDate);
ps=con.prepareStatement("insert into Table1(Hour) values(?)");
ps.setTime(1,sqlTime);
ps.executeUpdate();
This is the printed result :
ID Name Date Hour
0001 Mary null null
A couple of points:
As far as I can tell, there is no point in keeping your date and your time in two separate columns in your database table. I would use one column of datatype datetime.
The classes java.util.Date, SimpleDateFormat, java.sql.Date and Time are long outdated and poorly designed. Better to use java.time, the modern Java date and time API. It is so much nicer to work with.
Taking for granted that date and time are in separate columns your code may look like this:
LocalDateTime dateTimeNow = LocalDateTime.now(ZoneId.of("Europe/Rome"));
LocalDate dateToday = dateTimeNow.toLocalDate();
LocalTime timeNow = dateTimeNow.toLocalTime();
PreparedStatement ps
= con.prepareStatement("insert into Table1(Data, Hour) values(?, ?)");
ps.setObject(1, dateToday);
ps.setObject(2, timeNow);
ps.executeUpdate();
This will insert one row containing both the current day and the current time. Please use your desired time zone where I put Europe/Rome since both date and time depend on time zone.
Link: Oracle tutorial: Date Time explaining how to use java.time.
When java.util.Date is parsing "01/01/1901" to a Date objet, Java API is converting the date to “01/01/1901 0:08:39” instead of “01/01/1901 0:00:00” and this is happening only for Malaysia time zone.
This is happening because in 1901 Malaysia decided to synchronize his time zone with Penang, Malacca and Singapore and for that reason they added 8 minutes and 39 seconds. Java knows this and for that reason is automatically adding minutes and seconds to the date object (Because in Malaysia the hour 00:00:00 doesn’t exist for date 01/01/1991).
Malaysia TZ change:
https://www.timeanddate.com/time/change/malaysia/kuala-lumpur?year=1901
Java Source:
public class SimpleDateFormatExample {
public static void main(String[] args) {
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
// Locale for formatter
Locale malaysianLocale = new Locale("ms", "MY");
// Default date and time format for Malaysia
DateFormat defaultMalaysianFormatter = DateFormat.getDateTimeInstance(
DateFormat.DEFAULT, DateFormat.DEFAULT, malaysianLocale);
// This step is crucial
TimeZone malaysianTimeZone= TimeZone.getTimeZone("Asia/Kuala_Lumpur");
defaultMalaysianFormatter.setTimeZone(malaysianTimeZone);
try {
format.setTimeZone(malaysianTimeZone);
Date a = format.parse("01/01/1901");
String t = defaultMalaysianFormatter.format(a);
System.out.println(t);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
Example java output:
01 Januari 1901 12:08:39 AM
In Oracle Database TO_date function is not working in the same fashion, we believe that Oracle database doesn’t consider the time zone and for that reason it is not retrieving the correct values when send via SQL query.
Oracle Sql Source:
ALTER SESSION SET TIME_ZONE='Asia/Kuala_Lumpur';
select to_date('19010101 00:00:00','YYYYMMDD HH24:MI:SS') from dual;
Example Oracle output:
01-JAN-01 00:00:00
This issues are specific for Malaysia Time zone and for 1901 01/01
Why Java and Oracle database are behaving in different fashion?
Too long for a comment:
A DATE data type does not have a location or time zone. If you want that then you need to use a TIMESTAMP WITH TIME ZONE data type:
ALTER SESSION SET TIME_ZONE='Asia/Kuala_Lumpur';
SELECT FROM_TZ(
CAST(
DATE '1901-01-01' + INTERVAL '08:39' MINUTE TO SECOND
AS TIMESTAMP
),
'Asia/Kuala_Lumpur'
)
FROM DUAL;
Outputs:
1901-01-01 00.09.04.000000000 ASIA/KUALA_LUMPUR
Specifying any value between 1900-01-01 00:00:00 and 1900-01-01 00:08:38 will give ORA-01878: specified field not found in datetime or interval as Oracle knows it is an invalid date/time/time zone combination.
Why the output is 00:09:04 and not 00:08:39 is another question...
You can also use an ANSI timestamp literal:
SELECT TIMESTAMP '1901-01-01 00:08:39 Asia/Kuala_Lumpur' FROM DUAL;
java.util.Date date = new java.util.Date();
java.sql.Date today = new java.sql.Date(date.getTime()); //2012-03-23
java.sql.Time time = new java.sql.Time(date.getTime()); //02:32:46
PreparedStatement pst = null;
String queryString = "INSERT INTO PR_VISITOR(PRISONER_ID,VISITOR_NAME,FATHER_NAME,DOV,IN_TIME) VALUES (?,?,?,?,?)";
pst = connect.prepareStatement(queryString);
pst.setString(1, pr_id);
pst.setString(2, visit);
pst.setString(3, father);
pst.setDate(4, today);
pst.setTime(5, time);
int officerQuery = pst.executeUpdate();
if (officerQuery == 1) {
response.sendRedirect("/FYP3.4/prisonAdmin/visitor_out.jsp");
JOptionPane.showMessageDialog(null, "Visitor information registered !!", "Visitor Information", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(null, "Unable to Add information !!", "Visitor Information", JOptionPane.ERROR_MESSAGE);
}
By using the above code i'm trying to insert the current date and time into table,which have the separate columns. When i'm executing the above query then it insert the todays date in the time IN_TIME field too.
EDIT
DATATYPE OF IN_TIME and DOV are DATE .
Need Help.. !!
Since DOV and IN_TIME is date you don't need to separate date and hour. The type date in Oracle holds date and time. I suggest you change your table to have just one date column.
To insert the current time you can use the Oracle's sysdate function:
INSERT INTO PR_VISITOR(PRISONER_ID,VISITOR_NAME,FATHER_NAME,DATETIME_COLUMN) VALUES (?,?,?,?,SYSDATE)
To format your output of the date value you can use the SimpleDateFormat class in Java or to_char in Oracle.
A DATE column in an Oracle database will always store both a day (i.e. March 22, 2012) and a time to the second (i.e. 3:30:00 PM). A java.sql.Date and a java.sql.Time store the day and time as well but to the millisecond.
It doesn't really make sense to have separate columns in Oracle for the day and for the time but particularly not where both columns are declared as DATE data types. It would be much more conventional to use a single column declared as a DATE. If you really wanted to, you could truncate the day so that it represents midnight on the current day and then store the time component as, say, an INTERVAL DAY TO SECOND. But that would generally add a fair amount of complexity to the system for very little gain.
You're much better off using oracle's 'systimestamp'. The reason being, if you're java code is running in one timezone, and oracle lives in another. Forcing your own Time object, could cause problems.
Do you really need separate fields for this? I would think just having a timestamp would be enough.
Use SimpleDateFormat. This is one way I have used it:
Date now = Calendar.getInstance().getTime());
DateFormat df = new SimpleDateFormat("yyyyMMdd");
String date = df.format(now);
DateFormat tf = new SimpleDateFormat("HHmmss");
String time = tf.format(now);
Follow this,it will help both in java and oracle
create table datetime(date_time timestamp);
insert into datetime values (sysdate);
To get date:
select to_char(date_time,'DD-MON-YY') from datetime;
eg:12-JUL-12
To get month:
select to_char(date_time,'mm') from datetime;
eg:7
To get time:
select to_char(date_time,'HH24:MI:SS') from datetime;
eg:23:56:15
cheers!!
I am wanting to insert a datetime into a MySql data base using Java and a prepared statement:
Calendar cal = Calendar.getInstance();
PreparedStatement stmnt = db.PreparedStatement("INSERT INTO Run " +
"(Time) VALUE (?) ");
stmnt.setDate(1, new java.sql.Date(cal.getTime()));
stmnt.executeQuery();
NOTE: there is currently an error - cannot find symbol (java.sql.Date) line 4 here
db is an instance of a sort of wrapper class that exposes what I need from java.sql - its just getting a prepared statement from my connection object here.
Time (the column) is a date time in my database, and I can only see setDate and setTime method but I want to store both - also my code does not work anyway ;-)
If anyone could give me some pointers on inserting a combined date time (current time would be a great help as that's my first goal) into a MySql DB using a prepared statement I would be very grateful.
Thanks
The constructor for java.sql.Date takes a long (milliseconds since 1970) java.sql.Date
To get milliseconds from a java.uitl.Calendar, you use cal.getTimeInMillis()
Your code would be:
Calendar cal = Calendar.getInstance();
PreparedStatement stmnt = db.PreparedStatement("INSERT INTO Run " + "(Time) VALUE (?) ");
stmnt.setDate(1, new java.sql.Date(cal.getTimeInMillis()));
stmnt.executeQuery();
the following code should allow you to insert a date with millisecond accuracy. I have used it with HSQLDB, Sybase, SQL-Server and MySql without any problems.
java.util.Date date = getMyDate();
if (date == null) {
statement.setNull(insertionIndex, Types.TIMESTAMP);
} else {
statement.setTimestamp(insertionIndex, new Timestamp (date.getTime()));
}