shift in mysql between sql timestamp and the hour I put - java

I am using intellij for a javaee project and I get problems with time storage : there is a shift of 2 hours between what I put and the hour really stored in mysql.
some searches on internet gave nothing at the moment.
here is the java statement in which I set the hour of 15:30
Bien bien = new Bien(0, "mon super bien #2", 320, 5, 3, true,
520000, "4 impasse des bleuets",
LocalDateTime.of(2019, Month.MAY,1,15,30),
false, bien0.getTypeChauffage(), bien0.getOptions(), bien0.getVille());
and you can see on the picture at the right that the stored hour is 13:30!! 2 hours were lost.
some informations :
I live in France, which is UTC+2 on summer hour; so I put this line in mysql' my.ini:
default-time-zone='+02:00'
and in phpmyadmin, if I type
select now();
I get the correct hour.
The wrong time is got from both intellij and phpmyadmin.
The wrong time was got even before changing the default-time-zone in mysql.(but when I changed the timezone the previously entered datetime were shifted).
the conection string is very usual,without any extra parameter(only database, port,user,password).
I will continue to search, but if someone can help me it would be kind.
here is an output from phpMyAdmin:

The timezone in the database is always stored in UTC. I suppose you did not change the timezone in your phpmyadmin or intellj configuration, so you get to see the raw data.
If you haven't found this yet, check How do I set the time zone of MySQL?.

Related

Store and retrieve a date in MySQL without any timezone information using MySQL Connector/J 8.0

We are now in the process of updating the MySQL Connector/J of a Spring Boot application from version 5 to 8 (we are actually updating the Spring Boot version from 2.0 to 2.1, but I don't think it's relevant for our problem).
After upgrading the connector (the database remains the same: MySQL 5.7) we found that all the DATETIME values stored in the database were being shifted by the timezone difference between the server and the client (UTC and UTC+1). If we, for example, try to read a value like 2019-01-01 02:17:00 we are getting 2019-01-01 03:17:00.
We are aware that the new connector is the one making that time shift but we need our dates to be timezone independent. According to the documentation of MySQL 5.7 it looks like DATETIME is the way to go:
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.)
The only thing we can do right now is either downgrade the connector to previous version or change all the DATETIME columns to a BIGINT.
Is there any way of storing a date and a time without any timezone automatic conversion in MySQL?
Adding timezone to connection string should solve this problem. Try to add following text to your connection url:
useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=CET
In the past I've used this trick to make sure that the effective server time zone is the same as the client time zone:
String connectionUrl = "jdbc:mysql://localhost:3307/mydb?useUnicode=true"
+ "&serverTimezone=" + ZoneId.systemDefault().getId();
System.out.println(connectionUrl);
// jdbc:mysql://localhost:3307/mydb?useUnicode=true&serverTimezone=America/Denver
Connection conn = DriverManager.getConnection(connectionUrl, myUid, myPwd);

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!

How to get time zone of the client

I want to access timezoneId of client. For this I had tried different approaches to get timezoneId information. Like:
calculating timezone from offset & daylight saving time,
getting user location(i.e.longitude, latitude value) to know the timezoneId of that location
I am getting the result but exact results (for all timezones) For example two countries having same offset value then I am unable to locate exact one based on their system timezone setting; like:for Arizona and Mountain Time(US & Canada) both having offset value is UTC-7.00
Right now for both the value it is giving "MST" i.e. Mountain Standard Time as timezoneId. But I want what ever I will configure means if I will select Arizona then it will return Arizona and if I will select Mountain Time(US & Canada) then it will give its corresponding timezoneId.
Can you help me to get exact timezoneId ?
Thanks,
There is small lib jsTimezoneDetect. It should give you America/Arizona, etc.
http://pellepim.bitbucket.org/jstz/
Try this,
var d = new Date();
var n = d.toString();
//This will give you like MST, according to browser's time
var timeZone = (n.split("(")[1]).replace(")", "");

insert and extract hour an minute from oracle

I work with oracle
I want to insert data which contains hour and minute
I have this column : DATE_ARCH
the type of this column is date
I have this java code which should insert date in this column
transfers.setDateArch(new java.sql.Date(
System.currentTimeMillis()));
but when I try to extract hour and minute from DATE_ARCH
using this sql code :
select to_char(transfers.DATE_ARCH , 'HH:MM') from transfers where id_transfer='TR-300'
I have all time this value :
12:05
Updated :
I try with this code :
Timestamp t = new Timestamp(new Date().getTime());
transfers.setDateArch(t);
I try to extract hour and minute using this code :
select to_char(transfers.DATE_ARCH , 'HH24:MI') from transfers where id_transfer='TR-258'
but I have in all case this value :
00:00
as I already said the type of DATE_ARCH is date
When I try in sql with :
UPDATE transfers SET DATE_ARCH = SYSDATE
I have the correct value using
select to_char(transfers.DATE_ARCH , 'HH24:MI') from transfers where id_transfer='TR-258'
now I want to know how can I insert date with hour and minute using java code
You are correct. I do not know enough about the java interface to Oracle to know the right solution. But, your solution is inserting the date with no time. The expression:
to_char(transfers.DATE_ARCH , 'HH:MM')
is returning "12" because that is midnight and "05" because it is May. The correct expression for minutes is:
to_char(transfers.DATE_ARCH , 'HH:MI')
and for a 24-hour clock:
to_char(transfers.DATE_ARCH , 'HH24:MI')
I do not, alas, know how to fix the java code. But perhaps there is a DateTime method that you can use.

How to set default time zone in Java and control the way date are stored on DB?

I've the following problem, that showed up when I installed my webapp's war on a virtual linux server. Here it is: my server system time seems correct, in fact typing date on shell comes out with:
Mon Apr 11 11:47:30 CEST 2011
which is my "wall clock time". Even mysql works fine, if I do select now(), I get:
mysql> select now()
-> ;
+---------------------+
| now() |
+---------------------+
| 2011-04-11 11:52:57 |
+---------------------+
1 row in set (0.01 sec)
But my application (Spring+hibernate on Java6 + tomcat 6) will save every date on DB with a GMT timezone (and the time is correctly offset with the difference from GMT, which is good). Now the problem is that I get all dates displayed with GMT, even if I do:
static final DateFormat format = new SimpleDateFormat(
"dd/MM/yyyy 'alle' HH:mm", Locale.ITALY);
I don't get the hours correctly offset, but they remain in GMT and they display GMT if I put Z (that displays timezone) in the pattern.
Under Windows instead I had date values stored in my native timezone on mySQL. So on my windows machine where I develop I will have all the dates in CEST. This is annoying as I don't know how to predict the way the system will behave and I have to do boring tests and figure out how to change this.
Do you have ever seen this problem? How to deal with it?
DateFormat does support a notion of time zone. Add something like:
format.setTimeZone(TimeZone.getTimeZone("Europe/Rome");
SimpleDateFormat sf1 = new SimpleDateFormat("dd/MM/yyyy 'alle' HH:mm:ss");
sf1.setTimeZone(TimeZone.getTimeZone("Europe/Rome"));
System.out.println(sf1.format(new Date()));
// List all Timezone
System.out.println(Arrays.asList(TimeZone.getDefault()));
DateFormat does not care about time zones, only formatting. In order to change to timezone you need something like Calendar.setTimezone().
PreparedStatement st = con
.prepareStatement("insert into knjiga_osisi (rb_knjiz,Inv_br,Naziv_os,datum_k,rb_pk,opis,ulaz,izlaz,stanje,osnovica_zam,otpis,sadasnjav, vrednost_pp,rashodovanav) values (?,?,?,STR_TO_DATE(?, '%d-%m-%Y'),?,?,?,?,?,?,?,?,?,?)");
This is code for java.
Mysql - java european date format
This line is for date
STR_TO_DATE(?, '%d-%m-%Y')
U can test in mysql only date row:
SELECT ID, DATE_FORMAT(Date, '%d-%M-%Y') FROM table1;

Categories