java.sql.timestamp versus date - java

I am using Derby database with Java and Eclipse. I have a table which has a TIMESTAMP field and I use a model to populate a JTable from it. I am finding timestamp and data and java.sql and java.utils very confusing. The following line of code errors with cannot cast date to timestamp. mod is the model interfacing Derby table and JTable.
int rowcount = mod.getRowCount();
java.sql.Timestamp ts = (java.sql.Timestamp) mod.getValueAt(rowcount-1,1);
My objective is to get the date of the most recent record and subtract 30 days then run an sql query on the same database to find all the records more recent than that date. How do I recover the first timestamp, subtract the 30 days, then construct a query with the result of the subtraction as the condition in a WHERE clause. Sounds simple but I am having such difficulty that I feel I must be missing some fundamental principal. I thought conversion to long and back again might be the route but came up against the same cast problem.

Timestamp is declared as
public class Timestamp extends java.util.Date { ... }
Therefore you can't cast date to timstamp, you could create a timestamp from a date.
Timstamp ts = new Timestamp( date.getTime() );
To subtract 30 days this sequence might be helpful:
Calendar cal = new GregorianCalendar();
cal.setTime( date.getTime() );
cal.add( Calendar.DAY_OF_MONTH, -30 );
Date d30 = cal.getTime();
Anyway I would try to perform this using only SQL.

Related

Why querying a date BC is changed to AD in Java?

My program in Java connects to a Database (Oracle XE 11g) which contains many dates (date format of OracleXE is set to syyyy/mm/dd).
Doing a query in the database with negative dates (before Christ) works fine. When I do it in Java, they are all changed to AD (Anno Domini). How can I retrieve dates in Java respecting AD/BC?
My Java code here does the query to the DB and puts the result in a table.
try {
Object item=cbPD.getSelectedItem();
String dacercare=item.toString();
query = "SELECT DISTINCT PD.Titolo,PD.Inizio,(Select E.nome From Evento E WHERE PD.Inizio_Evento=E.CODE),
PD.Fine, (Select E.nome From Evento E WHERE PD.Fine_Evento=E.CODE ) FROM Periododelimitato PD WHERE PD.Titolo=?";
PreparedStatement stAccess = Login.connessione.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
stAccess.setString(1,dacercare);
rset = stAccess.executeQuery();
j = modelPD.getRowCount();
for (i=0; i<j; i++) modelPD.removeRow(0);
Date data;
while (rset.next()) {
data = rset.getDate(2);
modelPD.addRow(new Object[]{rset.getString(1),data, rset.getString(3), rset.getString(4), rset.getString(5)});
}
}
Here an Example using a specific Query:
try {
query = "SELECT PD.Inizio FROM PeriodoDelimitato PD WHERE PD.CodP=?";
String dacercare="8"; //look for record with this specific Primary key
PreparedStatement stAccess = Login.connessione.prepareStatement(query,
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
stAccess.setString(1, dacercare);
rset = stAccess.executeQuery();
while(rset.next()) {
Date dateBC = rset.getDate(1);
modelPD.addRow(new Object[]{null, dateBC, null, null, null});
}
Output in Java is:
0509-01-01
Output using the same query (substituing ? with the primary key specified) in Sql developer:
-0509/01/01
Note on the query: the column selected in this example is in Oracle a DATE type.
Adding information: DBMS is Oracle (XE 11g), DB has been built on IDE (SQL developer). The program is written in Java through Netbeans 8.2. I connect to the database in Netbeans adding the Library "ojdbc6.jar".
First, it’s not immediately clear how you should handle historic and not least prehistoric dates and how you should expect them to behave. It’s not something I know, but I doubt that any calendar in common use today was used in the 6th century BCE (before the common era, “BC”). Maybe you were already aware, I just wanted to mention it for anyone else reading this answer.
With thanks to Basil Bourque’s (now deleted) answer, what you have observed seems to be the intended behaviour with java.sql.Date. I tried printing dates from year 2 CE (common era, “AD”) and then year 2 BCE and compared. First 2 CE:
LocalDate ld = LocalDate.of(2, 1, 1);
java.sql.Date sqlDate = java.sql.Date.valueOf(ld);
System.out.println("java.sql.Date " + sqlDate + " millis " + sqlDate.getTime());
java.sql.Date 0002-01-01 millis -62104237200000
This is as expected. For 2 BCE we need to supply -1 to LocalDate since 0 means 1 BCE, and -1 means 2 BCE. Insert LocalDate.of(-1, 1, 1) in the above code, and the output is
java.sql.Date 0002-01-01 millis -62198931600000
We note that the date is printed the same. 0002 is hardly downright incorrect, but it doesn’t tell us whether it’s year 2 CE or BCE. I believe that this explains the behaviour you observed. Next we note that the millisecond values are different, so the dates are different as they should be. The diffirence is 94694400000 milliseconds, which equals 1096 days or 3 years if one of them is a leap year. The leap year may surprise, but otherwise I think it’s correct.
There is something fishy, though. When I converted the sql date back into a LocalDate, the era was lost, I always got a date in the common era. Since you don’t need this conversion, you probably don’t need to care.
I believe the good solution will be to drop the outdated Date class completely and use the modern LocalDate throughout. You should be aware that this follows the so-called proleptic Gregorian calendar, which may not always give the exact same dates as Date. Also this requires JDBC 4.2 compliant driver, so your ojdbc6.jar won’t do. Even though this may mean you’re prevented, I am letting the suggestion stand for anyone else reading along. I have not tested, but I think the following should work:
LocalDate dateBC = rset.getObject(1, LocalDate.class);
A solution using the old Date type to query SQL dates BC and AC that is working is to declare into my class a SimpleDataFormat with the format specified below
public SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd G");
Then I declared a Date dataOUT invoking the format method of SimpleDataFormat giving as input the Date BC queried from the Database
dataOUT=sdf.format(rset.getDate(2));
Thank you all for the time dedicated to my question!

DateTime withTimeAtStartOfDay with timezone

could somebody help or give me some hint with following problem. I have trouble with creating Timestamp in Java. In my db i have timestamp stored in UTC time for example 2016-10-20 23:30:00.000000 and my timezone is Europe/Prague so time is +1 Hour. And if i want to select records from 2016-10-21 i have to select also records from 2016-10-20 23:00:00.000000 if i want to have correct results. I am using Postgresql and JOOQ.
public DateTime getDateTimeWithZone() {
return new DateTime().withZone(MyFormatter.getDateTimeZone());
}
This code is in service class Localization service.
Then in controller i create joda time Interval.
Interval range = new Interval(localizationService.getDateTimeWithZone().withTimeAtStartOfDay(), localizationService.getDateTimeWithZone().withTimeAtStartOfDay().plusDays(1));
This gives me
2016-10-21T00:00:00.000+01:00/2016-10-22T00:00:00.000+01:00
and then in method for selecting records from db via JOOQ i use this construction
Timestamp start = new Timestamp(dtRange.getStartMillis());
Timestamp end = new Timestamp(dtRange.getEndMillis());
and result is
start = 2016-10-21 00:00:00.0
end = 2016-10-22 00:00:00.0
but i need to have start and end one hour back
Also i tried to modify method getDateTimeWithZone() with UTC time
public DateTime getDateTimeWithZone() {
return new DateTime().withZone(DateTimeZone.UTC);
}
range is the same. I think problem is with .withTimeAtStartOfDay() but in this case i need to have .withTimeAtStartOfDay() return 2016-10-20 23:00:00.0000. Is there any way how to do it with joda time or new java.time or write some own implementation od DateTime and override .withTimeAtStartOfDay() to return shifted DateTime. I will appreciate any help.

Comparing to get seconds difference between java and mysql datetime

I read a mysql date time field into one string e.g.
String arriveTime = rs1.getString("arriveTime");
Next step I try to get the current date and time using java to be similar format like the one I got from mysql.
DateFormat outDf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentDateTimer=null;
Date date = Calendar.getInstance().getTime();
currentDateTimer=outDf.format(date);
How can I minus the currentDateTime and arriveTime to get the net results in seconds. I would prefer to do it purely via java
First, I would not read a MySQL date-time into a String. I would change this,
String arriveTime = rs1.getString("arriveTime");
to
java.sql.Date arriveTime = rs1.getDate("arriveTime");
Then you can use basic subtraction to get the result in milliseconds, then divide by a thousand to get that in seconds - so
long diff = new java.util.Date().getTime() - arriveTime.getTime();
System.out.println(diff / 1000);
I read a mysql date time field into one string
If the column is varchar type it is ok you can read it using resultsetObject.getString()
But if your column type is Date then is it always recommended to get the value using resultset.getDate()
Mysql stores date in the format yyyy-MM-dd
I try to get the current date and time using java to be similar format
like the one I got from mysql.
When you do resultset.getDate() it will give you the java.sql.Date in format yyyy-MM-dd

sql.Date using ebean. hh:mm:ss not included in MySQL table using util-date Date.getTime()

Im receiving util.Date 's from twitter4j getCreatedAt() method.
Date d = twitter.getCreatedAt();
System.out.println(d);
Out: 'Mon Feb 17 00:10:34 PST 2014'
I'm trying to convert that to a sql.Date including the time. With the code I'm using right now, querying mysql from terminal shows a date like:
2014-02-16 00:00:00
Here's the code in the Tweet Model. (Using Play 2, btw)
#Id
public long id;
#Formats.DateTime(pattern="yyyy-MM-dd HH:mm:ss")
public Date date;
When a status comes in I construct it like so:
this.date = new java.sql.Date(status.getCreatedAt().getTime());
I think it could possibly be something to do with the time zones?
java.sql.Date just keeps the normalized date, see this from Oracle documentation:
To conform with the definition of SQL DATE, the millisecond values
wrapped by a java.sql.Date instance must be 'normalized' by setting
the hours, minutes, seconds, and milliseconds to zero in the
particular time zone with which the instance is associated.
If you want to use time with the date you have to use java.sql.Timestamp instead of java.sql.Date

Java: Insert into a table datetime data

I am trying to insert into a variable in MS- SQL database the current date and the time.
I use this format:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Calendar cal = Calendar.getInstance();
System.out.println(dateFormat.format(cal.getTime()));
and I get this as a result 2013-01-28 09:29:37.941
My field in the database is defined datetime and as I have seen in other tables which have the same field, the date and the time is written exactly like this 2011-07-05 14:18:33.000.
I try to insert into the database with a query that I do inside a java program, but I get this error
SQL Exception: State : S0003 Message: The conversion of a varchar
data type to a datetime data type of the value is out of range. Error
: 242
My query is like that:
query = "INSERT INTO Companies CreatedOn"+
"VALUES ('" + dateFormat.format(cal.getTime()) + "')"
but I don't understand what I am doing wrong.
According to the error description, you are inserting an incorrect type into the database. See JDBC to MSSQL. You should convert Calendar to Timestamp.
Try using:
PrepareStatement statement
= connection.prepareStatement("INSERT INTO Companies CreatedOn VALUES(?)");
java.sql.Timestamp timestamp = new java.sql.Timestamp(cal.getTimeInMillis());
statement.setTimestamp(1, timstamp);
int insertedRecordsCount = statement.executeUpdate();
First of all, do NOT use string concatenation. Have you ever heart about SQL injection?
Correct way how to do that is to use prepared statement:
Idea is you define statement with placeholders and than you define value for those placeholders.
See #Taky's answer for more details.
dateFormat#format this method returns formatted string not Date object. Database field is DateTime and it is expecting java.sql.Timestamp to be inserted there not String according to docs.
To conform with the definition of SQL DATE, the millisecond values
wrapped by a java.sql.Date instance must be 'normalized' by setting
the hours, minutes, seconds, and milliseconds to zero in the
particular time zone with which the instance is associated.
Try java.sql.Timestamp object instead of String in query and I'd recommend you to use PreparedStatement.
This is because you are trying to save String date value to Date type DB field.
convert it to Data dataType
You can also use the datetime "unseparated" format yyyymmdd hh:mm:ss
You could use Joda framework to work with date/time.
It maps own date/time types to Hibernate/SQL types without problem.
When you set parameters in HQL query joda carries about right type mapping.
If you want to store current date and time then you should use MYSQL inbuilt method NOW().
for brief documentation refer http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html . so your code will be like.
INSERT INTO Companies CreatedOn VALUES(NOW())"
However If you want to do it using java Date-util then it should be
Calendar cal = Calendar.getInstance();
java.sql.Timestamp timestamp = new Timestamp(cal.getTimeInMillis());

Categories